jdbc预编译的操作命令对象,类似模板引擎:
select * from emp where id=?
这里的?就是占位符
这整个就相当于模板
preparedStatement.setInt(1,123)
1表示第几个占位符
123表示替换的值
模板和替换的值一起就组织为一个拼接的数据库可以执行的sql
select * from emp where id=123
作用:
网页模板引擎产品有很多:freemarker、velocity、thymeleaf(springboot官方默认的模板技术)
在maven中央仓库搜索Thymeleaf
选择一个合适的版本,例如3.0.12:
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
创建hello.html, 放到 webapps/WEB-INF/templates 目录中
<h3>网页模板技术学习</h3>
<p th:text="${message}"></p>
th:text 是 Thymeleaf 的语法. 浏览器不能直接识别 th:text 属性.
先创建模板引擎和模板解析器
//使用thymeleaf模板技术
//创建一个模板引擎
TemplateEngine engine = new TemplateEngine();
//创建一个渲染网页模板的解析器:getServletContext是HttpServlet中的方法,返回Servlet上下文对象
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
resolver.setCharacterEncoding("utf-8");//设置渲染时编码
//设置网页模板文件,路径的前缀和后缀
resolver.setPrefix("/WEB-INF/templates/");//前缀
resolver.setSuffix(".html");//后缀
//将模板解析器绑定到模板引擎中
engine.setTemplateResolver(resolver);
再设置数据和模板名称
//创建一个web上下文(环境的语义,里边有一个map结构,可以存放键值对的数据)
WebContext webContext = new WebContext(req,resp,getServletContext());
//设置了一个键值对的数据,可以理解为:为网页模板定义了一个变量(变量名为message,值为hello...)
//queryString传入msg=xxx
webContext.setVariable("message",req.getParameter("msg"));
//模板引擎渲染网页模板:第一个参数为模板名称,第二个参数为web上下文(里边保存了数据)
//会根据模板解析器设置的前缀+模板名称+后缀,为模板路径查找到模板,再组织模板内容+数据
//返回值就是渲染后的网页字符串
String html = engine.process("hello",webContext);
最后把渲染的html设置到响应正文
resp.getWriter().write(html);
命令 | 功能 |
---|---|
th:text | 在标签中展示表达式求值结果的文本内容 |
th:[HTML]标签属性 | 设置任意的HTML标签属性的值 |
th:if | 当表达式的结果为真时则显示内容,否则不显示 |
th:each | 循环访问元素 |
$ {变量名}来引用Java代码中,设置的键值对数据(${键}就是值)
最终是把webContext设置的键值对数据中,键为message的值,设置到标签内容中
一些常用的需要设置的属性
1.设置a标签的href属性:
前端代码:
<a th:href="${a1}">搜狗</a> <!-- 渲染为<a href="键为a1的值" -->
<a th:href="${a2}">百度</a>
后端代码:
//写网站的绝对路径还是要加http://写全
webContext.setVariable("a1","http://www.sogou.com");
webContext.setVariable("a2","http://www.baidu.com");
2.条件判断:
前端代码:
<p th:if="${isLogin}">已经登录了</p>
后端代码:
webContext.setVariable("isLogin",true);
true时,html中会包含< p >
false时,html中不包含< p >
3.循环:
th:each的功能就是可以循环的构造出多个元素
语法格式为:
th:each=“自定义的元素变量名称:${集合变量名称}”
//Arrays.asList中的参数为可变参数,是将可变参数数组转变为List
webContext.setVariable("names", Arrays.asList("张三","李四","王五"));
关于创建模板引擎和模板解析器
整个web应用,只需要初始化一次(代码中的对象engine、resolver,只需要创建一次)
原因:对象及属性不会改变
改造:放在Servlet的init方法
Servlet有三个生命周期方法:
还存在问题:每个Servlet都需要在init方法中创建(一个webapp中,还是有多个engine,resolver对象)
解决这个问题:ServletContext、ServletContextListener
上下文/环境,常用于设置一些数据到上下文环境中
上下文环境中的对象,就可以互相引用对方的数据
很多地方都有Context这样的概念,他是一个语义上的概念
多个servlet间,无法直接传递数据,但可以通过共享的一个上下文环境,来设置/使用一些数据(数据传递)
ServletContext对象的重要方法:
方法 | 描述 |
---|---|
void setAttribute(String name,Object obj) | 设置属性(键值对) |
Object getAttribute(String name) | 根据属性名获取属性值,如果name不存在,返回null |
Object removeAttribute(String name) | 删除对应的属性 |
ServletContext类似Map结构,存放多组键值对的数据
代码示例:多个Servlet共享数据
//写入Context
@WebServlet("/write")
public class ContextWriteServlet extends HttpServlet {
//write?data=xxx
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String data = req.getParameter("data");
//把数据写入Servlet共享的上下文环境
ServletContext sc = getServletContext();
sc.setAttribute("d",data);
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write("写入Context成功");
}
}
//读取Context
@WebServlet("/read")
public class ContextReadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//把数据写入Servlet共享的上下文环境
ServletContext sc = getServletContext();
Object data = sc.getAttribute("d");
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().write("读取Context:"+data);
}
}
监听器,属于一种设计模式
如html中,标签中的事件——如< button onclick >
这个事件,其实就是监听器的设计模式
在html或js中,为一个dom元素,绑定一个事件(事件注册),不需要手动调用该事件的函数,而是在事件发生的时候,由浏览器来调用事件绑定的函数
这样事件发生需要执行的代码,和事件发生,两个就解耦
ServletContextListener,也是类似的一种监听器的设计。不要在事件发生的时候,自己写代码做事情,而是先注册一个函数/方法到监听器中,在某个事件发生后,就会自动执行
代码示例:监听ServletContext的创建
@WebListener
public class MyListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
// 这个会在 context 被创建的时候调用.
// 创建的时机在所有 Servlet 实例化之前.
System.out.println("ServletContext 创建");
// 通过 sce 的 getServletContext 方法获取到刚刚创建好的 ServletContext 对象
ServletContext context = sce.getServletContext();
context.setAttribute("message", "message 的初始值");
}
public void contextDestroyed(ServletContextEvent sce) {
//这个会在 context 被销毁的时候调用. 此处我们不关注
}
}