week13_day02_Filter&&JSON

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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-玫瑰少年-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值