week13

    技术2022-07-11  118

    3.Filter 过滤器。 3.1.filter的功能 1.可以设置拦截或者放行(验证,是否登录,info页面仅登录可用) 2.可以在请求到达servlet之前修改request对象,也可以在响应之后修改response对象(字符编码格式)

    3.2.如何编写Filter 1.编写一个类实现javax.servlet.Filter接口 2.注册该filter(先在web.xml中根据提示完成)

    3.3.Filter的生命周期 1.Init:随着应用的启动而实例化 2.doFilter:每访问一次filter,就会执行该方法一次 3.Destroy:应用的卸载或者服务器关闭

    3.4.Servlet和filter如何关联在一起 最简单的方式就是通过url-pattern。servlet和filter设置相同的url-pattern。 为什么没有报错? 不是说url-pattern不可以设置相同的嘛?为什么filter和servlet设置同一个url-pattern不会报错? 不可以设置相同的url-pattern是因为针对的是servlet。servlet从功能上来说,是开发动态web资源,做出响应的,如果多个servlet配置了相同url-pattern,究竟应该选择哪个来执行呢? 但是filter功能上来说,和servlet完全不同,filter定位拦截、过滤,而不是做出响应。 更多的是功能上的一个差异。功能上的一个定义。

    3.4.1.filter和servlet设置相同url-pattern,servlet代码不执行 为什么呢? filter默认执行的是拦截操作,如果想要放行代码往下执行,必须要有这句话 此时filter和servlet的代码均会被执行到。

    3.4.2.filter可以设置/*吗? 可以的。不会存在servlet的那些诸多烦恼。但是filter一般不会设置/。 设置了/*之后所有的servlet都不会出现中文乱码了。

    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_4_0.xsd" version="4.0"> <filter> <filter-name>firstFilter</filter-name> <filter-class>FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>

    FilterDemo:

    import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * @author shihao * @create 2020-07-01 9:44 */ //@WebFilter public class FilterDemo implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletResponse.setContentType("text/html;charset=utf-8"); System.out.println("doFilter"); //让filter放行servlet的代码 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println("destroy"); } }

    FirstServlet:

    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.IOException; /** * @author shihao * @create 2020-07-01 10:05 */ @WebServlet("/servlet") public class filterServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("servlet"); } }

    SecondServlet:

    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.IOException; @WebServlet("/servlet2") public class SecondServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("servlet2"); response.getWriter().println("您好servlet"); } }

    3.5.filter链 在一个请求的处理中,可以设置多个filter,然后会形成一个链,依次执行。 可以设置多个filter,多个filter如果url-pattern相同,也不会有任何问题。因为filter是一个过滤器或者说拦截器,而不是像servlet一样,是一个做出响应的组件,所以不会有任何问题。 那么,接下来有一个问题? 如果多个filter同时参与到一个请求的处理中,那么先调用哪个filter呢? 1.对于在web.xml中声明的filter,满足如下规律: 首先看能够处理当前请求的filter有哪些,其次再看 mapping声明的先后顺序,就是最终的调用顺序。所以看上面的web.xml,会先调用firstServlet再调用secondServlet。 2.对于注解的方式,顺序是类名首字母的ASCII先后顺序。 AFilter SFilter,先A后S

    3.6.整个请求的处理流程 比如一个叫做ROOT的应用,里面配置servlet,url-pattern叫做/servlet,同时配置了两个filter,一个AFilter叫做/*,一个BFilter叫做/servlet。都是采用注解的方式。 当访问如下请求时 http://localhost:8080/servlet2

    执行流程如下: 1.浏览器地址栏输入如下地址,构建一个请求报文 2.请求报文传输到指定机器的指定端口8080端口 3.被connector接收到,然后将其转成request对象,同时生成一个response对象 4.这两个对象被传给engine,engine挑选host来处理该请求 5.将这两个对象传给选好的host,host选择合适的Context来处理 6.这两个对象传给Context,请求的资源/servlet,Context根据请求的资源在当前应用下寻找合适的组件来处理该请求 7.首先先查找filter,哪些filter可以处理(匹配)该请求,将这两个filter按照一定的顺序组成一个链表 8.接下来去查找servlet,匹配到对应的servlet,然后将servlet添加到filter的链后面 9.接下来依次调用链上的组件,然后将request和response依次传进去,先执行filter接下来执行servlet,然后执行完毕,返回 10.connector读取reponse里面的数据生成响应报文

    类比转发包含

    3.6.1.filter链的执行顺序 控制台输出: 执行流程: 访问:http://localhost:8080/servlet2

    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_4_0.xsd" version="4.0"> <filter> <filter-name>firstFilter</filter-name> <filter-class>FilterDemo</filter-class> </filter> <filter-mapping> <filter-name>secondFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>secondFilter</filter-name> <filter-class>FilterDemo2</filter-class> </filter> </web-app>

    filterServlet2 :

    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.IOException; @WebServlet("/servlet2") public class filterServlet2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("servlet2"); response.getWriter().println("您好servlet"); } }

    FilterDemo :

    import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; /** * @author shihao * @create 2020-07-01 9:44 */ //@WebFilter public class FilterDemo implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletResponse.setContentType("text/html;charset=utf-8"); System.out.println("doFilter before"); //让filter放行servlet的代码 filterChain.doFilter(servletRequest, servletResponse); System.out.println("doFilter after"); } @Override public void destroy() { System.out.println("destroy"); } }

    FilterDemo 2:

    import javax.servlet.*; import java.io.IOException; public class FilterDemo2 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init2"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("doFilter2 before"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("doFilter2 after"); } @Override public void destroy() { System.out.println("destroy2"); } }

    3.7.Login2 功能 1.设置编码格式 2.拦截放行 登录页面 Info.jsp 要求有登录才可以访问。

    有的页面需要验证权限info.jsp,有的页面不需要验证权限login.jsp。

    建议大家课后自己去画一个流程图 1.当前访问的资源应该用哪个API?

    getRequestURI /app/login getRequestURL http://localhost:8080/app/login getServletPath /login getContextPath /app

    2.放行对应的是哪句代码?filterChain.doFilter(request,response)

    globalFilter :

    package com.cskaoyan; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author shihao * @create 2020-07-01 14:22 */ @WebFilter("/*") public class globalFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //强转 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; //中文乱码 req.setCharacterEncoding("utf-8"); resp.setContentType("text/html;charset=utf-8"); //info.jsp进行权限验证,如果登录,则可以该页面,如果没有登录,直接定位到登录页面 String servletPath = request.getServletPath(); if (auth(servletPath)) { //需要权限验证 String username = (String) request.getSession().getAttribute("username"); if (username == null) { //没有登陆,拦截 response.sendRedirect(request.getContextPath() + "/login.jsp"); //response.setHeader("refresh","2;url=" + request.getContextPath() + "/login.jsp"); return; } } //不需要进行权限验证 chain.doFilter(req, resp); } /** * 哪些访问路径需要权限验证 * @param servletPath * @return */ private boolean auth(String servletPath) { if ("/info.jsp".equals(servletPath)){ return true; } return false; } public void init(FilterConfig config) throws ServletException { } }

    1.JSON 需要记住一点:{}表示的是一个对象,[]表示的是一个数组或者集合。 两者之间都可以正常执行,没有报错,他们之间的区别是什么呢? 上面的严格来说才表示的是json对象,下面表示的json字符串。 java端服务端产生的数据如果要和前端进行通讯,那么采用的就是json字符串来进行 通讯。

    1.1.java语言如何操作json 前后端分离的概念。页面和数据分别来自于两个不同的系统。 比如一个项目:页面内来自于localhost:8080,数据来自于localhost:8084, java语言提供对应页面所需要的数据。 数据返回就是以json字符串的形式来返回。

    1.1.1.java对象如何转成json字符串 {“name”:“zhangsan”, “age”: 24} 可以用一个网站来校验besjon.com 专门用来校验json字符串。

    mainTest :

    /** * @author shihao * @create 2020-07-01 22:05 */ public class mainTest { public static void main(String[] args) { Person person = new Person(); person.setName("zhangsan"); person.setAge(24); //需要把person对象转成json字符串 //var person = {"name": "zhangsan", "age": 24} String perStr = "{\"name\": " + "\"" + person.getName() + "\"" + ", \"age\": " + person.getAge() + "}"; System.out.println(perStr); } }

    使用工具类来完成这些操作。 Gson google json解析工具 Fastjson alibaba Jackson SpringMVC框架内置 不管怎么样,完成的功能都是一样的。

    mainTest2 :

    import com.google.gson.Gson; /** * @author shihao * @create 2020-07-01 22:09 */ public class mainTest2 { public static void main(String[] args) { Person person = new Person(); person.setName("zhangsan"); person.setAge(24); //将java对象转换成json对象 Gson gson = new Gson(); String s = gson.toJson(person); System.out.println(s); } }

    将数组或者集合转成json字符串呢? mainTest2 :

    ```java import com.google.gson.Gson; import java.util.ArrayList; import java.util.List; /** * @author shihao * @create 2020-07-01 22:09 */ public class mainTest2 { public static void main(String[] args) { Person person = new Person(); person.setName("zhangsan"); person.setAge(24); //将java对象转换成json对象 Gson gson = new Gson(); String s = gson.toJson(person); System.out.println(s); Person person2 = new Person(); person2.setName("lisi"); person2.setAge(22); List<Person> people = new ArrayList<>(); people.add(person); people.add(person2); String s1 = gson.toJson(people); System.out.println(s1); } } 1.1.2.json字符串如何转成java对象 mainTest3 : ```java import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import java.util.ArrayList; import java.util.List; /** * @author shihao * @create 2020-07-01 22:25 */ public class mainTest3 { public static void main(String[] args) { //如果被parse的对象是[],用Array //如果被parse的对象是{},用Object //{"name":"zhangsan","age":24} //[{"name":"zhangsan","age":24},{"name":"lisi","age":22}] String person = "{\"name\":\"zhangsan\",\"age\":24}"; String people = "[{\"name\":\"zhangsan\",\"age\":24},{\"name\":\"lisi\",\"age\":22}]"; //将json字符串转成对应的java类型 Gson gson = new Gson(); Person person1 = gson.fromJson(person, Person.class); //如何将一个数组对象的数据转成List对象的java数据类型 //1. JsonElement jsonElement = new JsonParser().parse(people); //根据json字符串最外侧是[]还是{}灵活的去选择getAsJsonArray还是getAsJsonObject JsonArray jsonArray = jsonElement.getAsJsonArray(); List<Person> list = new ArrayList(); for (JsonElement p : jsonArray) { Person person2 = gson.fromJson(p, Person.class); list.add(person2); } System.out.println(list); } }
    Processed: 0.017, SQL: 9