一、前后端分离

1.1 前后端分离开发方式

  1. 前后端分开开发:前端的代码中不可能出现后台的代码,而后台的代码也是不可能出现前端的代码(不出现后端页面跳转),前端需要的数据都由后台程序员提供,只需要提供对外的接口(servlet)。<br /> 动静分离:动态资源(servlet)与静态资源(htmlcssjs等)分离,将动态资源与静态资源部署到不同的服务器上,Apache是一个服务器,而 Tomcat是它的一个插件,Tomcat主要的优势使用来处理动态资源(servlet),但是处理静态资源的能力很差,第三阶段会将静态资源部署到nginx服务器上。<br />![](https://cdn.nlark.com/yuque/0/2020/jpeg/2621095/1607333135937-108e7fb4-ffeb-411a-b5a4-9bbd33b727a8.jpeg#align=left&display=inline&height=572&margin=%5Bobject%20Object%5D&originHeight=572&originWidth=1000&size=0&status=done&style=none&width=1000)

1.2 前后端不分离开发方式

   前端代码中需要编写后台的代码,最典型的技术JSP,模板引擎(freemarker、thymeleaf等),利用后台的代码生成前端的页面,而且是经常出现后端跳转页面<br />![](https://cdn.nlark.com/yuque/0/2020/jpeg/2621095/1607333142256-63530926-c8ef-4549-9dd5-56e2a146454b.jpeg#align=left&display=inline&height=662&margin=%5Bobject%20Object%5D&originHeight=662&originWidth=1000&size=0&status=done&style=none&width=1000)

后台进行页面跳转方式:请求转发、重定向
**

二、请求转发、重定向

2.1 请求转发

跳转之后页面的url还是上一次请求的url,URL不会变<br />    将请求转发给另外一个程序,例如当前servlet接收到一个请求但是它自己处理不了,这个时候可以将该请求转发给其他人(servlet)处理<br />    请求转发只有一个请求<br />![](https://cdn.nlark.com/yuque/0/2020/jpeg/2621095/1607333223452-640ee223-d610-40e6-9788-2d8a5625c30c.jpeg#align=left&display=inline&height=487&margin=%5Bobject%20Object%5D&originHeight=487&originWidth=1000&size=0&status=done&style=none&width=1000)

2.2 重定向

重定向:第一次发送请求后,服务器会返还响应给浏览器,浏览器根据响应信息重新定向发送请求,请求会有两次,url会变(因为第二次会发送请求)
41 - 前后端分离、请求转发与重定向、监听器、thymeleaf - 图1

2.3 转发请求与重定向的区别

不同点:
1.请求转发可以共享请求参数
重定向不能共享请求参数

2.请求转发跳转到目标页面,地址栏地址不发生改变
重定向跳转到目标页面,地址栏地址会发生改变
3.请求转发不支持跨域访问,但可以访问WEB-INFO下的资源包括HTML
重定向可以跨域访问

相同点:
AServlet跳转到BServlet为例,两种方法都只会响应B页面的数据,不会响应A页面的数据

三、监听器

监听对象创建、属性变化,在servlet主要用来对域对象进行监听,request、session、context对象进行监听
在servlet中监听器总共分为3种8类
代码举例:
Context监听器:

@WebListener
public class MyContextListener implements ServletContextAttributeListener {

    public MyContextListener() {
    }

    public void attributeAdded(ServletContextAttributeEvent event)  { 
        System.out.println("context添加了数据");
        System.out.println(event.getName() + ":" + event.getValue());
    }

    public void attributeRemoved(ServletContextAttributeEvent event)  { 
        System.out.println("context移除了数据");
        System.out.println(event.getName() + ":" + event.getValue());

    }

    public void attributeReplaced(ServletContextAttributeEvent event)  { 
        System.out.println("context修改了数据");
        System.out.println(event.getName() + ":" + event.getValue());
        System.out.println(event.getSource());
    }

}
@WebListener
public class MyContextLifecycleListener implements ServletContextListener {

    public MyContextLifecycleListener() {
    }

    // context销毁时,项目停止时
    public void contextDestroyed(ServletContextEvent arg0)  { 
        System.out.println("保存数据");
    }

    // context初始化完毕,项目启动成功
    public void contextInitialized(ServletContextEvent arg0)  { 
        //在后台开启一些守护线程做一些底层的操作
        System.out.println("项目启动成功");
    }

}

四、thymeleaf

4.1 页面静态化

将动态的页面转换成静态的页面,意义:加速项目响应速度、优化搜索搜索引擎的命中率
SpringBoot官方推荐的模板引擎:thymeleaf

4.2 thymeleaf

模板页面:
HTML标签中引入thymeleaf模板标签库 ](http://www.thymeleaf.org%22%3E/)
取值:

文本

或者

[[${time}]]

4.2.1 基本使用

前端代码:

<!DOCTYPE html>
<!-- 引入thymeleaf的标签库 -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- 
        th:text用来给标签的text设置文本 
        th:href
    -->
    <p th:text="${time}">文本</p>
</body>
</html>

后端代码:

public static void main(String[] args) throws IOException {

        //通过模板引擎生成一个静态页面

        //1.创建模板引擎:去用来生成静态页面
        TemplateEngine templateEngine = new TemplateEngine();

        //2.创建文件模板解析器:读取模板文件,分析文件
        FileTemplateResolver resolver = new FileTemplateResolver();

        //3.设置字符编码:汉字乱码问题
        resolver.setCharacterEncoding("UTF-8");

        //4.设置模板参数
        resolver.setPrefix("");//前缀:模板文件所在的位置,在javaSE环境下""代表当前项目下
        resolver.setSuffix(".html");//后缀,表示模板的文件格式

        //5.将文件解析器设置到模板引擎上
        templateEngine.setTemplateResolver(resolver);

        //6.创建context用来存放页面上需要使用到的数据
        Context context = new Context();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        context.setVariable("time", dateFormat.format(new Date()));

        //7.生成静态的HTML页面
        //参数1:模板的名字
        //参数2:存放数据对象
        //参数3:流对象,用来生成静态页面
        templateEngine.process("goods", context, new FileWriter("index.html"));

    }

4.2.2 存放对象

前端代码:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- 内联取值:不推荐 -->
    <p>[[${goods.id}]]</p>
    <p th:text="${goods.name}">商品名字</p>
    <p th:text="${goods.price}">商品价格</p>
</body>
</html>

后端需要修改代码:

        //6.创建context用来存放页面上需要使用到的数据
        Context context = new Context();

        Goods goods = new Goods(1001,"我的校园生活",250);
        context.setVariable("goods", goods);

        //7.生成静态的HTML页面
        //参数1:模板名字
        //参数2:存放数据对象
        //参数3:流对象,用来生成静态页面
        templateEngine.process("goods2", context,new FileWriter("index2.html"));

4.2.3 if判断是否展示数据

前端代码:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- th:if判断是否为true,为true才能看见 -->
    <p th:if="${isMan}">男生能看到的</p>
    <p th:if="${isWomen}">女生能看到的</p>
    <!-- th:unless判断是否为false,为false才能看见 -->
    <p th:unless="${isVip}">不是会员能看到的</p>
    <p th:unless="${isVip} == false">会员看到的</p>
</body>
</html>

后端需要修改代码:

        //6.创建context用来存放页面上需要使用到的数据
        Context context = new Context();
        context.setVariable("isMan", true);
        context.setVariable("isWomen", false);
        context.setVariable("isVip", true);

        //7.生成静态的HTML页面
        //参数1:模板名字
        //参数2:存放数据对象
        //参数3:流对象,用来生成静态页面
        templateEngine.process("if", context,new FileWriter("index3.html"));

4.2.4 each循环展示数据

前端代码:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <!-- 有几个商品对象,就会生成几个div -->
    <div th:each="goods:${goodsList}">
        <p th:text="${goods.id}" style="color: red;">id</p>
        <p th:text="${goods.name}">name</p>
        <p th:text="${goods.price}">price</p>
    </div>
</body>
</html>

后端需要修改代码:

        //6.创建context用来存放页面上需要使用到的数据
        Context context = new Context();
        Goods g1 = new Goods(1001,"Java入门1",50);
        Goods g2 = new Goods(1002,"Java入门2",60);
        Goods g3 = new Goods(1003,"Java入门3",70);
        Goods g4 = new Goods(1004,"Java入门4",80);

        List<Goods> goodsList = Arrays.asList(g1,g2,g3,g4);

        context.setVariable("goodsList", goodsList);

        //7.生成静态的HTML页面
        //参数1:模板名字
        //参数2:存放数据对象
        //参数3:流对象,用来生成静态页面
        templateEngine.process("each", context,new FileWriter("each2.html"));

4.2.5 url

前端代码:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <a href="http://www.baidu.com">百度</a><br>
    <a th:href="@{http://sina.com/goods/findById(id=${goods.id})}">商品详情</a>
    <a th:href="@{http://sina.com/goods/{id}/findById(id=${goods.id})}">商品详情</a>

</body>
</html>

后端需要修改代码:

        //6.创建context用来存放页面上需要使用到的数据
        Context context = new Context();
        Goods g1 = new Goods(1001,"Java入门1",50);

        context.setVariable("goods",g1);

        //7.生成静态的HTML页面
        //参数1:模板名字
        //参数2:存放数据对象
        //参数3:流对象,用来生成静态页面
        templateEngine.process("url", context,new FileWriter("url2.html"));