MVC 三层架构:
Model(模型)、View(视图)、Controller(控制器)
控制器:Controller,可以理解成 Servlet
1.接收用户的请求(req:请求参数、Session 信息等)
2.响应给客户端内容(业务层)
3.重定向或转发(视图跳转)
Model:控制业务操作,保存数据、修改数据、删除数据、查询数据
1.业务处理:业务逻辑(Service)
2.数据持久层:CRUD(Dao)
View:视图层,可以理解成 JSP
1.展示数据
2.提供链接发起 Servlet 请求(a、form、img 等)
Servlet 专注于处理请求和控制视图跳转
JSP 专注于显示数据
举个例子:
用户登录
接收用户的登录请求
处理用户的请求,获取用户登录的参数,username、password
交给业务层处理登录业务(判断用户名和密码是否正确:事务)
Dao 层查询用户名和密码是否正确
查数据库
都对上了再逐一返回上述步骤
Filter 过滤器:用来过滤网站的数据
pom.xml 导入连接数据库的包
    <!-- 连接数据库 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.33</version>
    </dependency>实现 Filter 接口
重写对应的方法
初始化:web服务器启动,就开始初始化,随时等待过滤对象出现
filterChain.doFilter(servletRequest,servletResponse); 固定写法,让过滤器执行
销毁:web服务器关闭时,过滤销毁
代码如下:
package com.demo.filter;
import javax.servlet.*;
import java.io.IOException;
//implements接口
public class CharacterEncodingFilter implements Filter{
    //初始化:web服务器启动,就开始初始化,随时等待过滤对象出现
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //Filter.super.init(filterConfig);
        System.out.println("初始化");
    }
    /*
    1.过滤中的所有代码,在过滤特定请求时都会执行
    2.必须要让过滤器继续执行 filterChain.doFilter(servletRequest,servletResponse);
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //处理编码
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=UTF-8");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    //销毁:web服务器关闭时,过滤销毁
    @Override
    public void destroy() {
        //Filter.super.destroy();
        System.out.println("销毁");
    }
}再写个能在页面上显示中文的类
不加 setCharacterEncoding 是乱码,数据多就不适用了,所以用过滤器一步到位
package com.demo.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Demo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("过滤");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
web.xml 注册和映射:
Filter 与 Servlet 配置的写法相似
<filter-mapping> 下的 <url-pattern> 路径一般会加个其他自己设置的路径
比如 /admin/*、/servlet/*,表示这个路径下的全部都会走过滤器
    <servlet>
        <servlet-name>demo</servlet-name>
        <servlet-class>com.demo.servlet.Demo</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>demo</servlet-name>
        <url-pattern>/demo</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>com.demo.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>运行后,地址栏添加后缀,页面显示中文
如果需要实现权限拦截(比如用户注销),可以在监听器里设置 Session 值不匹配进入错误页面
但需要强转成 HttpServletRequest、HttpServletResponse
监听器:
例:统计在线人数
package com.demo.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
//统计网站在线人数,实则统计Session
public class OnlineCountListener implements HttpSessionListener {
    //创建Session监听
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        ServletContext servletContext = se.getSession().getServletContext();
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
        if(onlineCount==null){
            onlineCount = new Integer(1);
        }else{
            int i = onlineCount.intValue();
            onlineCount = new Integer(i+1);
        }
        servletContext.setAttribute("OnlineCount",onlineCount);
    }
    //销毁Session监听
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        ServletContext servletContext = se.getSession().getServletContext();
        System.out.println(se.getSession().getId());
        Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
        if(onlineCount==null){
            onlineCount = new Integer(0);
        }else{
            int i = onlineCount.intValue();
            onlineCount = new Integer(i-1);
        }
        servletContext.setAttribute("OnlineCount",onlineCount);
    }
}index.jsp 添加一行
<h1>当前有<span><%=this.getServletConfig().getServletContext().getAttribute("OnlineCount")%></span>人在线</h1>web.xml 注册监听器
    <!-- 注册监听器 -->
    <listener>
        <listener-class>com.demo.listener.OnlineCountListener</listener-class>
    </listener>手动销毁监听器:se.getSession().invalidate();
自动销毁监听器:时间自己设置
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>监听器在 GUI 图形用户界面中经常使用,小窗体,可以监听用户操作,关闭、缩小、放大等










