MVC模型
- 存在问题
- Servlet中,要处理的事有:处理请求、调度页面、渲染页面,而渲染页面是前端代码,应该出现在前端程序中,也就是说要继续对Servlet进行拆分,拆分成MVC模型。
- 之前学习的技术,无法将java数据直接展示到页面。
- MVC模型
- m : model , 模型
- 封装数据,就是javabean
- v : view , 视图
- 渲染页面,就是thymeleaf (将java数据展示到页面)
- c : controller , 控制器
- 处理请求,调度页面
thymeleaf
- 概述
- Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP,Velocity, FreeMaker等, 它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板 引擎。它的主要作用是在静态页面上渲染显示动态数据
- 优势
- thymeleaf技术是SpringBoot框架默认支持的数据渲染引擎。
物理视图和逻辑视图
- 物理视图
- 就是请求转发的一个资源的绝对路径
- 逻辑视图
- 物理视图=视图前缀+逻辑视图+视图后缀
- 比如:/pages/user/login.html=/pages/user/(视图前缀) + login(逻辑视图) + .html(视图后缀)
thymeleaf入门
- 开发步骤
- ①引入thymeleaf相关jar包
- ②在web.xml中,配置视图前缀、视图后缀
- ③定义ViewBaseServlet
- 解析渲染thymeleaf
- ④自定义Servlet继承ViewBaseServlet
- ⑤编写html页面,渲染java数据
- ①引入thymeleaf相关jar包
- ②在web.xml中,配置视图前缀、视图后缀
<context-param>
<param-name>view-prefix</param-name>
<param-value>/pages/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>
- ②在web.xml中,配置视图前缀、视图后缀
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 1.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2.创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 3.给解析器对象设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
String viewPrefix = servletContext.getInitParameter("view-prefix");
templateResolver.setPrefix(viewPrefix);
// ③设置后缀
String viewSuffix = servletContext.getInitParameter("view-suffix");
templateResolver.setSuffix(viewSuffix);
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 4.创建模板引擎对象
templateEngine = new TemplateEngine();
// 5.给模板引擎对象设置模板解析器
templateEngine.setTemplateResolver(templateResolver);
}
/**
* 执行视图
* @param templateName : 逻辑视图
* @param req : 请求
* @param resp : 响应
* @throws IOException
*/
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, getServletContext());
// 3.处理模板数据
templateEngine.process(templateName, webContext, resp.getWriter());
}
}
④自定义Servlet继承ViewBaseServlet
@WebServlet("/demo01")
public class Demo01Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = "用户已经存在!";
req.setAttribute("msg", msg);
//请求转发到demo01.html
processTemplate("demo01", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
⑤编写html页面,渲染java数据
<!DOCTYPE html>
<!--开启thymeleaf空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>demo01</title>
</head>
<body>
<span th:text="${msg}"></span>
</body>
</html>
注意事项
- 如果要在html页面中,使用thymeleaf指令,需要开启thymeleaf空间
thymeleaf修改标签内容
- 概述
- 使用th:text指令操作标签内容,类似于vue的v-text指令
- 代码实现
@WebServlet("/demo02")
public class Demo02Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String msg = "用户名已经存在!";
req.setAttribute("msg", msg);
//req.getRequestDispatcher("/pages/demo02.html").forward(req, resp);
processTemplate("demo02", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>demo01</title>
</head>
<body>
<span th:text="${msg}"></span>
</body>
</html>
thymeleaf修改标签属性
- 概述
- 使用"th:属性名"指令来修改标签属性,类似于vue的"v-bind:属性名"/":属性名"指令
- 代码实现
@WebServlet("/demo03")
public class Demo03Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = "张三";
req.setAttribute("username", username);
//req.getRequestDispatcher("/pages/demo02.html").forward(req, resp);
processTemplate("demo03", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>demo03</title>
</head>
<body>
<input type="text" th:value="${username}">
</body>
</html>
thymeleaf解析URL
- 概述
- @{}等同于项目的访问路径
- 代码实现
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<base th:href="@{/}">
<title>thymeleaf解析url</title>
</head>
<body>
<a href="/web08/pages/demo01.html">跳转demo01</a>
<a href="pages/demo01.html">跳转demo01</a>
<a th:href="@{/pages/demo01.html}">跳转demo01</a>
<a th:href="@{/pages/demo02.html}">跳转demo02</a>
<a th:href="@{/pages/demo03.html}">跳转demo03</a>
<a href="/web08/demo05?username=root&password=root">请求Demo05Servlet</a>
<a th:href="@{/demo05(username=root,password=root)}">请求Demo05Servlet</a>
</body>
</html>
thymeleaf操作域对象
- 域对象
- ServletContext : 整个项目
- HttpSession : 当前会话
- ServletRequest : 当前请求
- 代码实现
@WebServlet("/demo06")
public class Demo06Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//ServletContext
getServletContext().setAttribute("msg3","hello3");
//HttpSession
req.getSession().setAttribute("msg2","hello2");
//ServletRequest
req.setAttribute("msg1", "hello1");
processTemplate("demo06", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf操作域对象</title>
</head>
<body>
<span th:text="${msg1}"></span>
<span th:text="${session.msg2}"></span>
<span th:text="${application.msg3}"></span>
</body>
</html>
OGNL表达式
- 概述
OGNL使用
代码实现
@WebServlet("/demo07")
public class Demo07Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Student student = new Student();
student.setStudentName("陈磊");
student.setSubject(new Subject("java"));
List<School> schoolList = new ArrayList<>();
schoolList.add(new School("晨光幼儿园"));
schoolList.add(new School("晨光小学"));
schoolList.add(new School("晨光中学"));
schoolList.add(new School("晨光大学"));
student.setSchoolList(schoolList);
Map<String, Teacher> teacherMap = new HashMap<>();
teacherMap.put("谈局",new Teacher("谈局"));
teacherMap.put("小赵",new Teacher("小赵"));
teacherMap.put("老邱",new Teacher("老邱"));
student.setTeacherMap(teacherMap);
req.setAttribute("student",student);
processTemplate("demo07", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>OGNL表达式使用</title>
</head>
<body>
<!--获取student姓名-->
<span th:text="${student.studentName}"></span>
<!--获取subject名称-->
<span th:text="${student.subject.subject}"></span>
<!--获取第二个学校名称-->
<span th:text="${student.schoolList[1].schoolName}"></span>
<!--获取谈局的教师姓名-->
<span th:text="${student.teacherMap.谈局.teacherName}"></span>
</body>
</html>
thymeleaf条件渲染
- 概述
- 使用th:if指令进行条件渲染,类似于vue的v-if指令
- 代码实现
/**
* thymeleaf条件渲染
*/
@WebServlet("/demo08")
public class Demo08Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("flag", true);
processTemplate("demo08", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf条件渲染</title>
</head>
<body>
<span th:if="${flag}">
您已经登录了,欢迎回来~~~
</span >
<span th:if="${!flag}">
您还没有登录,请登录~~~
</span>
</body>
</html>
thymeleaf分支渲染
- 概述
- 使用th:switch和th:case进行分支渲染
- 代码实现
@WebServlet("/demo09")
public class Demo09Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//管理员(admin),普通用户(user),游客(visitor)
String role = "admin";
req.setAttribute("role", role);
processTemplate("demo09", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf分支渲染</title>
</head>
<body>
<div th:switch="${role}">
<span th:case="admin">管理员</span>
<span th:case="user">普通用户</span>
<span th:case="visitor">游客</span>
</div>
</body>
</html>
thymeleaf列表渲染
- 概述
- 使用th:each进行列表渲染,类似于vue的v-for
- 代码实现
@WebServlet("/demo10")
public class Demo10Servlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Teacher> teacherList = new ArrayList<>();
teacherList.add(new Teacher("谈局"));
teacherList.add(new Teacher("小赵"));
teacherList.add(new Teacher("老邱"));
req.setAttribute("teacherList", teacherList);
processTemplate("demo10", req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>thymeleaf列表渲染</title>
</head>
<body>
<ul>
<li th:each="teacher:${teacherList}">
<span th:text="${teacher.teacherName}"></span>
</li>
</ul>
<ul>
<li th:each="teacher:${teacherList}" th:text="${teacher.teacherName}">
</li>
</ul>
</body>
</html>