1. 页面展示
输入谁想对谁说的话,点击提交,内容就会显示在下方,如下所示:
2. 静态页面设计
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="表白墙.css">
</head>
<body>
<h2>表白墙</h2>
<p id="desc">输入后点击提交,会将信息显示在表格中</p>
<div>
<span>谁:</span>
<input type="text" id="from">
</div>
<div>
<span>对谁:</span>
<input type="text" id="to">
</div>
<div>
<span>说什么:</span>
<input type="text" id="content">
</div>
<div>
<button id="submit">提交</button>
</div>
<p id="show"></p>
</body>
<script src="表白墙.js"></script>
</html>
CSS样式代码
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body {
background-image: url(11.jpg);
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-size: cover;
}
h2 {
color: aqua;
text-align: center;
margin: 35px 0;
}
#desc {
text-align: center;
font-size: 0.8em;
color: gray;
margin-bottom: 10px;
}
div {
height: 50px;
/*div中的子元素设置为弹性布局,div占据整行*/
display: flex;
/* 水平居中 */
justify-content: center;
/* 垂直居中 */
align-items: center;
}
div>span {
color: pink;
height: 30px;
width: 70px;
}
div>input {
height: 40px;
width: 200px;
font-size: 18px;
line-height: 30px;
/* 输入框内容上下不间隔,左右间隔 */
padding: 0 10px;
}
div>button {
width: 270px;
height: 40px;
background-color: orange;
color: white;
border: none;
}
#submit:active {
background-color: gray;
}
#show {
color: greenyellow;
text-align: center;
}
JS代码
//获取文本框的内容
//需要在点击时获取
var submit = document.querySelector("#submit");
submit.onclick = function(){
var from = document.querySelector("#from");
var to = document.querySelector("#to");
var content = document.querySelector("#content");
var show = document.querySelector("#show");
var str = from.value;
str += "对";
str += to.value;
str += "说:";
str += content.value;
show.innerHTML = str;
}
缺陷及改进
上述只是静态页面,也就是无论何时访问,页面都不会改变,并且上次提交的表白信息在下次访问时就会消失,所以我们需要制作成服务器版表白墙,也就是每次访问的时候所有的表白消息都可以展示出来,即访问时从数据库查询消息展示在前端,输入消息点击提交保存在数据库以后并展示在前端
3. 使用Thymeleaf改造HTML
我们采用form表单的提交方式,请求方法为post请求,展示的表白消息使用Thymeleaf对其改造,改造后的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="表白墙.css">
</head>
<body>
<h2>表白墙</h2>
<p id="desc">输入后点击提交,会将信息显示在表格中</p>
<form action="message" method="post">
<div class="form-row">
<span>谁:</span>
<input type="text" id="from" name="from">
</div>
<div class="form-row">
<span>对谁:</span>
<input type="text" id="to" name="to">
</div>
<div class="form-row">
<span>说什么:</span>
<input type="text" id="content" name="content">
</div>
<div class="form-row">
<input type="submit" id="submit">
</div>
</form>
<p class="row" th:each="m : ${messages}">
<span th:text="${m.from}"></span>对
<span th:text="${m.to}"></span>说:
<span th:text="${m.content}"></span>
</p>
</body>
<script src="表白墙.js"></script>
</html>
4. 准备工作
创建Maven项目后,在pom.xml中添加依赖
- 后端使用Servlet进行开发
- 使用模板引擎
- 数据库使用Mysql
- 引入单元测试框架,做某个功能的测试
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>web-practise</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- 单元测试框架 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
</dependencies>
<build>
<finalName>web-practise</finalName>
</build>
</project>
创建相关的包
引入前端资源
5. 功能设计
5.1 数据库设计
分析:页面上将展示多条消息,每条消息都要从数据库中查询,并且输入消息点击提交后,会将消息保存在数据库,消息总共有三个字段,分别是谁,对谁,说什么,所以我们要创建一个message表,存放消息
drop database if exits biaobai;
create database biaobai character set utf8mb4;
use biaobai;
create table message(
`from` varchar(10),
`to` varchar(10),
`content` varchar(50),
);
5.2 数据库表对应的实体类
public class Message {
private String from;
private String to;
private String content;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Message{" +
"from='" + from + '\'' +
", to='" + to + '\'' +
", content='" + content + '\'' +
'}';
}
}
5.3 监听器
@WebListener
public class TemplateEngineListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
TemplateEngine engine = new TemplateEngine();
ServletContext sc = sce.getServletContext();
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(sc);
resolver.setPrefix("/WEB-INF/templates/");//前缀
resolver.setSuffix(".html");//后缀
resolver.setCharacterEncoding("utf-8");//设置渲染编码
engine.setTemplateResolver(resolver);
sc.setAttribute("engine",engine);//将引擎设置到ServletContext中
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
说明:TemplateEngine和ServletContextTemplateResolver的创建和初始化只执行一次,所以采用监听器的设计模式监听ServletContext的创建,ServletContext在Tomcat启动时自动创建,在Tomcat关闭时自动消失,所以在ServletContext创建的时候自动执行引擎和解析器的逻辑代码,将引擎写到ServletContext中,后续的Servlet直接从ServletContext中获取引擎即可
5.4 数据库工具类
提供获取数据库连接,统一释放资源
//数据库工具类,提供获取数据库连接,释放资源统一代码
public class DBUtil {
//一个程序,连接一个数据库,只需要一个连接池,其中保存了多个数据库连接对象
private static MysqlDataSource ds; //静态变量,类加载时执行初始化,只执行一次
//获取连接池,内部使用,不开放
private static DataSource getDataSource(){
if(ds == null){
ds = new MysqlDataSource();
ds.setURL("jdbc:mysql://127.0.0.1:3306/biaobai");
ds.setUser("root");
ds.setPassword("xiaobai520..@@@");
ds.setUseSSL(false); //不安全连接,不设置会有警告
ds.setCharacterEncoding("UTF-8");
}
return ds;
}
//获取数据库连接对象,开放给外部的jdbc代码使用
public static Connection getConnection(){
try {
return getDataSource().getConnection();
} catch (SQLException e) {
throw new RuntimeException("获取数据库连接报错",e);
}
}
//释放资源,查询操作需要释放三个资源
public static void close(Connection c, Statement s, ResultSet rs){
try {
if(rs != null) rs.close();
if(s != null) s.close();
if(c != null) c.close();
} catch (SQLException e) {
throw new RuntimeException("释放数据库资源出错",e);
}
}
//更新操作释放两个资源
public static void close(Connection c,Statement s){
close(c,s,null);
}
}
5.5 创建MessageServlet类
创建MessageServlet类,注解为@WebServlet("/message"),继承HttpServlet,重写doPost方法
- 解析请求,设置请求编码格式,获取到三个输入框内容,from,to,content
- 创建一个Messge实体类重写toString方法,提供Setter和Getter方法
- 将from,to,content设置到一个Message对象中,然后将这个对象插入到数据库中
- 插入到数据库中后,还要在前端展示出来,即每次访问message路径的时候都要在数据库中查询所有的消息,并展示在前端,故要重写doGet方法,在doGet方法中做对应的逻辑处理
- 在doGet方法中,设置响应编码格式,从ServletContext中获取引擎,创建web上下文,设置动态参数键为messages,值为从数据库中查询到所有消息的集合,整合模板和数据,将整合后的字符串写给前端,由浏览器渲染
- 在doPost方法中调用doGet方法是为了每次提交完后都要将消息展示在前端,因为和前面是相同的逻辑,所以直接调用doGet方法
@WebServlet("/message")
public class MessageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
WebContext wc = new WebContext(req,resp,getServletContext());
wc.setVariable("messages",MessageDao.selectMessage());
String html = engine.process("表白墙",wc);
resp.getWriter().write(html);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String from = req.getParameter("from");
String to = req.getParameter("to");
String content = req.getParameter("content");
Message m = new Message();
m.setFrom(from);
m.setTo(to);
m.setContent(content);
//messages.add(m);
MessageDao.insertMessage(m);
doGet(req,resp);
}
}
上述涉及到往数据库插入消息和从数据库查询消息的逻辑,这两个逻辑将在MessageDao中展示
5.6 数据库逻辑处理
//dao是专门做数据库操作的
public class MessageDao {
//将一个message对象插入到数据库对应的message表中
public static void insertMessage(Message m){
//jdbc步骤:
//1.获取数据库连接
//2.获取操作命令对象
//3.执行sql
//4.处理结果集
//5.释放资源
Connection c = null;
PreparedStatement ps = null;
try {
c = DBUtil.getConnection();
String sql = "insert into message(`from`,`to`,content) values(?,?,?)";
ps = c.prepareStatement(sql);
ps.setString(1,m.getFrom());
ps.setString(2,m.getTo());
ps.setString(3,m.getContent());
int n = ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException("插入message出错",e);
} finally {
DBUtil.close(c,ps);
}
}
//查询所有的消息,放在集合中返回
public static List<Message> selectMessage(){
List<Message> list = new ArrayList<>();
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
c = DBUtil.getConnection();
String sql = "select * from message";
ps = c.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
Message m = new Message();
String from = rs.getString("from");
String to = rs.getString("to");
String content = rs.getString("content");
m.setFrom(from);
m.setTo(to);
m.setContent(content);
list.add(m);
}
} catch (SQLException e) {
throw new RuntimeException("查询message出错",e);
} finally {
DBUtil.close(c,ps,rs);
}
return list;
}
//插入的测试
@Test
public void testInsert(){
Message m = new Message();
m.setFrom("hlk");
m.setTo("fs");
m.setContent("521");
insertMessage(m);
}
//查询的测试
@Test
public void testSelect(){
List<Message> list = selectMessage();
System.out.println(list);
}
}
6. 项目源码
在最后附上源码链接 ,表白墙源码: 简易表白墙制作
版权归原作者 X_H学Java 所有, 如有侵权,请联系我们删除。