在学习:Servlet 过程中,从数据库获取表 hero,然后把hero表中的信息以列表的形式返回给客户端,需要用到 Thymeleaf 框架,下面来讲解下!
一、Thymeleaf 框架介绍
- 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
- 2.Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、改jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- 3.Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
二、导入Thymeleaf框架
- 依赖:会引入我们使用Thymeleaf框架的一些 jar 包
<!-- Thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
三、提供数据
- 获取数据库连接对象,执行sql语句获取表:hero 中的数据
- 说明:对于JDBC的知识,我近期会更新JDBC和Servlet的相关博客,这里就不多阐述了!
public class HeroDao {
//返回所有用户
public List<Hero> findAll() {
ArrayList<Hero> list = new ArrayList<>();
//获取连接
try(Connection conn = DBUtils.getConn()){
String sql = "select * from hero";
//执行sql语句
Statement s = conn.createStatement();
//得到结果集并遍历
ResultSet re = s.executeQuery(sql);
while (re.next()){
//得到hero信息
int age = re.getInt(1);
String name = re.getString(2);
String type = re.getString(3);
int money = re.getInt(4);
//new Hero(*,*,*,*);加入到list集合 并返回
list.add(new Hero(age,name,type,money));
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
我们在终端来看看我们:hero 表中的数据
下面我们用两种方式来实现:hero表中的信息以列表的形式返回给客户端
第一种: 也就是最初的版本,把我们 java 代码和 html 代码拼在一起
@WebServlet(name = "FindAllServlet",urlPatterns = "/findall")
public class FindAllServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HeroDao dao = new HeroDao();
//查询多个英雄信息 封装到Hero对象中
//把多个英雄对象装进List集合
List<Hero> list = dao.finAll();
response.setContentType("text/html;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.print("<table border='1'>");
pw.print("<caption>英雄列表</caption>");
pw.print("<tr><th>id</th><th>name</th><th>type</th><th>money</th><th>操作</th></tr>");
for (Hero hero:list){
System.out.println(list+"....................");
pw.print("<tr>");
pw.print("<td>"+hero.getId()+"</td>");
pw.print("<td>"+hero.getName()+"</td>");
pw.print("<td>"+hero.getType()+"</td>");
pw.print("<td>"+hero.getMoney()+"</td>");
pw.print("<td><a href='delete?id="+hero.getId()+"'>删除</a></td>");
pw.print("</tr>");
}
pw.print("</table>");
pw.close();
}
}
没有学过Servlet 的看不懂没有关系,我们只需要看懂这部分:
- 分析上述结果:我们把 java 代码和 html 写在一起,这对我我们修改java代码或者html来说都是很不便利的;其次面对大量的html时,这种方式是很麻烦耗时的!
第二种:使用Thymeleaf 框架
将服务器端的数据和html页面进行整合,得到一个装着数据和标签的新的html.
- 1、导入依赖,上面已经导入了
- 2、在项目resources目录下创建list.html(动态页面/模板页面),把页面相关标签添加进去
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<caption>英雄列表</caption>
<tr>
<th>id</th><th>名字</th><th>类型</th><th>价格</th><th>操作</th>
</tr>
<!--th:each 是遍历的语法,${list}取出context中的数据,h代表遍历每一个英雄对象-->
<tr th:each="h:${list}">
<td th:text="${h.id}"></td>
<td>th:text="${h.name}"></td>
<td th:text="${h.type}"></td>
<td th:text="${h.money}"></td>
</tr>
</table>
</body>
</html>
说明:th:each 是遍历的语法,${list}取出context中的数据,h代表遍历每一个英雄对象,Context相当于一个容器,里面存储的就是我们的数据
准备工作已经做好了,下面就是 怎么把我们的数据和html结合
,生成新的html啦,看下面
- 创建Context用于保存所有需要在页面上展示的动态数据
Context context = new Context();
context.setVariable("list",list);
- 创建解析器 该解析器会自动查找src/main/resources目录下的模板页面
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setTemplateMode("html");//模板类型,指定为html格式
resolver.setCharacterEncoding("UTF-8");//模板使用的字符集(我们的页面都是UTF-8编码的)
- 实例化模板引擎,让解析器和模板引擎关联
TemplateEngine te = new TemplateEngine();
te.setTemplateResolver(resolver);//设置模板解释器,使其了解模板相关信息
- 将页面和数据整合到一起的到一个新的html字符串
String html = te.process("list.html",context);
- 把得到的新的html返回给浏览器 异常抛出
response.setContentType("text/html;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.print(html);
上面的这些步骤我们可以封装到一个工具类:ThUtils 里面,因为这些内容都是定死的,我们没有必要每次使用都把这些内容都写一遍
- ThUtils 工具类
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class ThUtils {
private static TemplateEngine te;
static {
//创建模板引擎对象
te = new TemplateEngine();
//创建解析器 该解析器会自动查找src/main/resources目录下的模板页面
ClassLoaderTemplateResolver r =
new ClassLoaderTemplateResolver();
//设置字符集
r.setCharacterEncoding("UTF-8");
//让解析器和模板引擎关联
te.setTemplateResolver(r);
}
//Context导包 org.thymeleaf.Context
public static void print(String fileName,Context context,
HttpServletResponse response) throws IOException {
//将页面和数据整合到一起的到一个新的html字符串
String html = te.process(fileName, context);
//把得到的新的html返回给浏览器 异常抛出
response.setContentType("text/html;charset=utf-8");
PrintWriter pw = response.getWriter();
pw.print(html);
pw.close();
}
}
实现代码:
@WebServlet(name = "FindAllServlet",urlPatterns = "/findall")
public class FindAllServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//查看所有用户
HeroDao dao = new HeroDao();
List<Hero> list = dao.findAll();
//通过 Thy模板引擎将页面和数据整合 并返回给客户端
///1、创建Context上下文(容器)
Context context = new Context();
//2、把数据装进容器 以键值对形式保存数据
context.setVariable("list",list);
//3、通过工具类将页面和数据整合 返回给客户端
ThUtils.print("list.html",context,response);
}
}
没有学过Servlet 的看不懂上面没有关系,我们只需要看懂这部分:
运行结果: