• Java Web之Filter和Listener对象


    前言

    Java Web中有3大组件

    • Servlet
    • Filter(过滤器)
    • Listener(监听器)

    3大组件的功能如下

    • Filter功能:     类似于Django中的中间件,可以在Servlet之前拦截请求和响应。
    • Servlet功能:  执行后台业务逻辑,处理客户端请求和响应。
    • Listener功能:用于监视Request、Session和ServletContext这三大域对象的创建、销毁以及域对象中存储对象的增加和减少事件,一旦域对象发生不同事件,即执行相应的动作。

    一、Filter(过滤器)

    Filter类似于Django中的中间件,可以在Servlet之前拦截请求和响应,检查请求和响应是否合法?

    1.创建模块

     

    2.创建过滤器

    package com.zhanggen.filter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import javax.servlet.*;
    import java.io.IOException;
    import java.util.Date;
    
    public class LogFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("进入目标资源之前" + new Date().toLocaleString());
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String loginURI = "/day07-filter-json/loginServlet";
            String secretToken = "s8170hhdk101hhdu";
            String requestURI = request.getRequestURI();
            //如果请求路径不是登录页面
            if (!loginURI.equals(requestURI)) {
                String userToken = (String) request.getSession().getAttribute("token");
                if (userToken != null && userToken.equals(secretToken)) {
                    //放行请求
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            } else {
                //跳转到登录页面
                response.sendRedirect("/day07-filter-json/login.html");
            }
            System.out.println("离开目标资源之后" + new Date().toLocaleString());
        }
    
        @Override
        public void destroy() {
    
        }
    }
    LogFilter.java

    3.配置过滤器

    可通过web.xml配置文件和注解两种方式配置过滤器。

    3.1.配置文件配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <!--过滤器配置-->
        <filter>
            <filter-name>logFilter</filter-name>
            <filter-class>com.zhanggen.filter.LogFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>logFilter</filter-name>
            <!-- 拦截请求的规则-->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <welcome-file-list>
            <!--设置默认首页-->
            <welcome-file>login.html</welcome-file>
        </welcome-file-list>
    </web-app>
    web.xml

    3.2.注解配置

    @WebFilter("/*")
    public class LogFilter implements Filter {

     

    二、过滤器链

    程序有时需要对同一个资源进行多重过滤,这就可以配置多个过滤器,称为过滤器链。

    注意:只有过滤器链中的所有的过滤器都对请求路径放行,请求才能访问到目标资源。

    1.创建过滤器链

     

     

    2.配置过滤器链

    通过web.xml配置文件和注解两种方式可以配置过滤器链。

    2.1.配置文件配置

    过滤链的执行顺序:根据filter-mapping在web.xml中的配置顺序,决定过滤器的执行顺序。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <!--过滤器链配置-->
        <filter>
            <filter-name>logFilter</filter-name>
            <filter-class>com.zhanggen.filter.LogFilter</filter-class>
        </filter>
        <filter>
            <filter-name>AFilter</filter-name>
            <filter-class>com.zhanggen.filter.AFilter</filter-class>
        </filter>
        <filter>
            <filter-name>BFilter</filter-name>
            <filter-class>com.zhanggen.filter.BFilter</filter-class>
        </filter>
    <!--    根据filter-mapping的先后顺序决定过滤器的执行顺序-->
        <filter-mapping>
            <filter-name>logFilter</filter-name>
            <!-- 拦截请求的规则-->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <filter-mapping>
            <filter-name>AFilter</filter-name>
            <!-- 拦截请求的规则-->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <filter-mapping>
            <filter-name>BFilter</filter-name>
            <!-- 拦截请求的规则-->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <welcome-file-list>
            <!--设置默认首页-->
            <welcome-file>login.html</welcome-file>
        </welcome-file-list>
    </web-app>
    web.xml

    2.2.注解配置

    过滤链的执行顺序:根据过滤器类名称的字符排序,值小的先执行

    三、Listener(监听器)

    web中的监听器在开发中使用的比较少,主要用于监听web三大域对象:Request、Session、ServletContext.
    主要监听这三个域对象的创建和销毁以及域对象中存储对象的增加和减少。

    web中的监听器一共有8个(扩展)分别用于监听不同的域对象。

            ServletContextListener             监听ServletContext对象的创建和销毁
            HttpSessionListener             监听HttpSession对象的创建和销毁
            ServletRequestListener          监听ServletRequest对象的创建和销毁
            
            ServletContextAttributeListener    监听ServletContext对象的数据的变化
            HttpSessionAttributeListener       监听HttpSession对象的数据的变化
            ServletRequestAttributeListener    监听ServletRequest对象的数据的变化
           
            HttpSessionBindingListener         监听自己被绑定、解绑到HttpSession中
            HttpSessionActivationListener      监听自己被钝化或激活了

    1.创建监听器

    使用ServletContextListener来学习下监听器的使用步骤,该监听器是监听器中使用率最高的一个,其它监听器的使用方式都类似。

    package com.zhanggen.listener;
    
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    @WebListener
    public class MyServletContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("Tomcat创建完成了。。");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("Tomcat即将销毁。。");
        }
    }
    MyServletContextListener.java

    2.配置监听器

    可以通过2中方式配置1个监听器。

    2.1.配置文件配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
    <!--  配置一个监听器-->
        <listener>
            <listener-class>com.zhanggen.listener.MyServletContextListener</listener-class>
        </listener>
        <welcome-file-list>
            <!--设置默认首页-->
            <welcome-file>login.html</welcome-file>
        </welcome-file-list>
    </web-app>
    web.xml

    2.2.注解配置

     

    四、Servlet传输Json数据

     在Java中通过以下工具可以实现json序列化。

    工具名称介绍
    Jsonlib Java类库,需要导入的jar包较多
    Gson google提供的一个简单的json转换工具
    Fastjson alibaba技术团队提供的一个高性能的json转换工具
    Jackson 开源免费的json转换工具,springmvc转换默认使用jackson

    Jackson完成数据转换使用的类是ObjectMapper,它有两个主要方法:

    • String writeValueAsString(Object obj): 将一个对象转换为json字符串
    • T readValue(String json, Class clazz): 将一个字符串转换为指定类型的对象

    1.导入jar包

     

    2.json序列化

    Java对象转换成json字符串

    package com.zhanggen.test;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.zhanggen.domain.User;
    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    
    //Java对象转换成json字符串
    public class Object2json {
        @Test
        //1.对象-->json
        public void testObject2Json() throws JsonProcessingException {
            // 创建1个对象
            User user = new User("a001", "张三丰", "男", 29, "武当山", "112", "1@qq.com");
            //将对象转换成json字符串
            String userJosn = new ObjectMapper().writeValueAsString(user);
            System.out.println(userJosn);
    
        }
        @Test
        //2.ArrayList-->json
        public void testList2Json() throws JsonProcessingException{
            ArrayList<User> userList = new ArrayList<>();
            userList.add(new User("a001", "张三丰", "男", 129, "武当山", "112", "1@qq.com"));
            userList.add(new User("a002", "冲虚道长", "男", 59, "武当山", "14", "2@qq.com"));
            String userListJosn = new ObjectMapper().writeValueAsString(userList);
            System.out.println(userListJosn);
        }
        @Test
        //2.ArrayList-->json
        public void testMap2Json() throws JsonProcessingException{
            HashMap<String,String> userMap=new HashMap();
            userMap.put("张三丰","129");
            userMap.put("冲虚道长","29");
            String userMapJson = new ObjectMapper().writeValueAsString(userMap);
            System.out.println(userMapJson);
    
        }
    }
    Object2json.java

    3.json反序列化

    json字符串转换成Java中的对象

    package com.zhanggen.test;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.zhanggen.domain.User;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    //把json字符串转换成Java中的对象
    public class Json2Object {
        @Test
        //1.json--->对象
        public void testJson2Object() throws IOException {
            //准备1个对象json字符串
            String jsonString = "{\"id\":\"a001\",\"name\":\"张三丰\",\"sex\":\"男\",\"age\":29,\"address\":\"武当山\",\"qq\":\"112\",\"email\":\"1@qq.com\"}";
            //将对象json字符串转换为对象
            User userObject = new ObjectMapper().readValue(jsonString, User.class);
            System.out.println(userObject);
    
        }
    
        //2.json-->ArrayList
        @Test
        public void testJson2List() throws IOException {
            String josnString = "[{\"id\":\"a001\",\"name\":\"张三丰\",\"sex\":\"男\",\"age\":129,\"address\":\"武当山\",\"qq\":\"112\",\"email\":\"1@qq.com\"},{\"id\":\"a002\",\"name\":\"冲虚道长\",\"sex\":\"男\",\"age\":59,\"address\":\"武当山\",\"qq\":\"14\",\"email\":\"2@qq.com\"}]";
            List userList = new ObjectMapper().readValue(josnString, List.class);
            System.out.println(userList);
        }
    
        //3.json-->map
        @Test
        public void testJson2Map() throws IOException {
            String jsonString = "{\"张三丰\":\"129\",\"冲虚道长\":\"29\"}";
            Map userMap = new ObjectMapper().readValue(jsonString, Map.class);
            System.out.println(userMap);
    
        }
    }
    Json2Object.java

     

    4.Servlet接收和响应json数据

    在Servlet后台,可以通过

    • 字节流
    • 字符流

    2种I/O流,接收和响应json数据。

    --------------------------------------------------------------------

    package com.zhanggen.servlet;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    
    
    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //0.设置请求头和响应头编码
            response.setContentType("application/json;charset=UTF-8");
            request.setCharacterEncoding("utf-8");
            //1.接收json数据
            BufferedReader reader = request.getReader();
            String json = reader.readLine();
            System.out.println(json);
            reader.close();
    
            //2.响应json数据
            PrintWriter out = response.getWriter();
            out.write("{\"name\":\"张根\"}");
            out.close();
    
        }
    }
    字符流

    --------------------------------------------------------------------

    package com.zhanggen.servlet;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.zhanggen.domain.User;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletInputStream;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    
    
    @WebServlet("/LoginServlet")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //0.设置请求头和响应头编码
            response.setContentType("application/json;charset=UTF-8");
            request.setCharacterEncoding("utf-8");
            String contentType = request.getContentType();
            //1.接收json字符串反序列化成Java对象
            BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8"));
            StringBuffer sb = new StringBuffer("");
            String temp;
            while ((temp = br.readLine()) != null) {
                sb.append(temp);
            }
            br.close();
            //1.1.反序列化,json字符串-----》Java对象
            System.out.println("json字符串---》" + sb.toString());
            User userObject = new ObjectMapper().readValue(sb.toString(), User.class);
            System.out.println("Java对象---》" + userObject);
            //2.响应json字符串
            //2.1.创建1个对象
            User user = new User("a001", "张三丰", "男", 29, "武当山", "112", "1@qq.com");
            //2.2.将对象转换成json字符串
            //2.3.序列化:Java对象----》json字符串
            String userJosn = new ObjectMapper().writeValueAsString(user);
            // 2.4通过字节输入流从byte数组中获取数据
            InputStream is = new ByteArrayInputStream(userJosn.getBytes("utf-8"));
            //2.5 从response对象中获取1个字节输出流
            ServletOutputStream op = response.getOutputStream();
            //2.6.通过字节输入流读取到字节数据,输出到字节输出流中
            int len;
            byte[] byteArray = new byte[1024];
            while ((len = is.read(byteArray)) != -1) {
                op.write(byteArray, 0, len);
    
            }
            //2.7.缓冲区完成
            op.flush();
    
        }
    }
    字节流

    --------------------------------------------------------------------

    前台如果使用的是ajax提交的post的请求体中携带的参数,后台接收的时候必须使用输入流接收。

    使用hutool工具包,将输入流读成原来的json字符串。

        //测试接收和响应json数据
        private void testJson(HttpServletRequest request, HttpServletResponse response) throws IOException {
            //1. 前台如果使用的是ajax提交的post的请求体中携带的参数,后台接收的时候必须使用输入流接收
            //1-1 接收数据称为数据流
            ServletInputStream inputStream = request.getInputStream();
            //1-2 使用hutool工具包,将输入流读成原来的json字符串
            String json1 = IoUtil.read(inputStream, "utf-8");
            //1-3 将json串再转换为一个Student对象
            Student student = new ObjectMapper().readValue(json1, Student.class);
            System.out.println(student);
            //2. 调用service进行更新
            student.setName("张根");
            String json2 = new ObjectMapper().writeValueAsString(student);
            response.getWriter().write(json2);
            
        }
    hutool工具包
  • 相关阅读:
    Redis线程模型理解
    策略模式
    Spring Cloud 5大组件介绍
    单例模式
    hotspot虚拟机的调试
    编译虚拟机jvm——openjdk的编译
    mybatis的搭建和注入spring的方式
    springMvc+hibernate的web application的构建
    关于本博客
    本博客已停更
  • 原文地址:https://www.cnblogs.com/sss4/p/16213226.html
Copyright © 2020-2023  润新知