java Servlet注解实现过滤器

写在前面的话: 这篇文章是与Token验证关联的,看友们可以去看看俺的这篇Servlet的Token的实现

实现Servlet过滤器方式:

1、在xml文件里面配置
2、在文件头添加注解

首先我们应该知道什么是过滤器:

java过滤器:顾名思义,就是在java中起到过滤的作用的一个方法
可以在一个请求到达servlet之前,将其截取进行逻辑判断,然后决定是否放行到请求的servlet中。
也可以在一个response到达客户端之前,截取结果进行逻辑判断,然后决定是否允许返回给客户端。

io java 过滤流抽象类 java过滤器实现_开发语言

前面文章Token的实现中,我们可以知道,用户第一次登录是没有Token的,需要验证生成。同时前端需要在每次业务请求带上后端返回最新的一个Token,下面我们用过滤器进行Token的过滤

1、首先新建一个java文件,继承Filter,并在文件头上加上@WebFilter注解,这里的Url是业务页面的请求地址,/*可匹配多个请求并处理

io java 过滤流抽象类 java过滤器实现_ide_02

@WebFilter(urlPatterns = "/recharge/*")
public class Myfilter implements Filter {

继承了Filter接口,就需要实现的三个方法:

看单词的意思,doFilter方法应该就是处理过滤的方法

io java 过滤流抽象类 java过滤器实现_io java 过滤流抽象类_03

@Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

这里需要注意的一点是:要明白这是前端发来的业务请求,需要过滤器来验证Token
简单写一个前端的业务dopost请求:

io java 过滤流抽象类 java过滤器实现_后端_04

package com.example.demo.newyears.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.IOException;

/**
 * @Author:Yun
 * @Date:2022/01/10/10:34
 * @Description:
 **/

@WebServlet(name = "recharge", urlPatterns = "/recharge")
public class Recharge extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (resp.getHeader("Token") != null) {
            resp.getWriter().println(req.getAttribute("id"));
        }
    }
}

过滤器的工作:那么过滤器的工作就是拿到前端的请求头中的Token,并对Token进行处理,然后要注意的一点就是后端有异常需要处理,因为过滤器处理后,后端拿到的Token可能已经被过滤器过滤返回给前端了,那么后端就需要处理一下异常。

过滤器代码如下:

package com.example.demo.newyears.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;

/**
 * @Author:Yun
 * @Date:2022/01/10/8:52
 * @Description:
 **/
//拦截所有指定的url
@WebFilter(urlPatterns = "/recharge/*")
public class Myfilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //在过滤器中设置了返回体的编码格式的话,那么在业务页面就不需要再一个个页面去设置了
        ((HttpServletResponse) servletResponse).setHeader("Content-Type", "application/json;charset=UTF-8");
//        String token = "";
//        if (servletRequest instanceof HttpServletRequest) {
**//这里需要注意,doFilter方法中的servletRequest,servletResponse和HttpServletRequest是对应一个请求**
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        try {
        //该方法再下面的代码段
            Token.timethan(req, resp);
        } catch (NullPointerException | ParseException e){
            e.printStackTrace();
        }
        //验证Token
//        ((HttpServletResponse) servletResponse).setHeader("Token", "xxxxxxxxxxx");
        //todo servlet执行之前
        //继续往前走,职责链,这句话很关键
        filterChain.doFilter(servletRequest, servletResponse);
        //todo servlet的内容
    }
}

这里需要注意,doFilter方法中的servletRequest,servletResponse和HttpServletRequest是对应一个请求,所以再这里可以对请求中的参数进行获取,并设置想要传递的参数

完整源代码:

Myfilter.java

package com.example.demo.newyears.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;

/**
 * @Author:Yun
 * @Date:2022/01/10/8:52
 * @Description:
 **/
//拦截所有指定的url
@WebFilter(urlPatterns = "/recharge/*")
public class Myfilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        ((HttpServletResponse) servletResponse).setHeader("Content-Type", "application/json;charset=UTF-8");
//        String token = "";
//        if (servletRequest instanceof HttpServletRequest) {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
//            token = req.getHeader("Token");
//            req.setAttribute("id", 24);
        //setArribute设置的内容,可以在servlet doget中拿到
//        }
        try {
            Token.timethan(req, resp);
        } catch (NullPointerException | ParseException e){
            e.printStackTrace();
        }
        //验证Token
//        ((HttpServletResponse) servletResponse).setHeader("Token", "xxxxxxxxxxx");

        //todo servlet执行之前
        //继续往前走,职责链
        filterChain.doFilter(servletRequest, servletResponse);
        //todo servlet的内容
    }
}


Recharge.java

package com.example.demo.newyears.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.IOException;

/**
 * @Author:Yun
 * @Date:2022/01/10/10:34
 * @Description:
 **/

@WebServlet(name = "recharge", urlPatterns = "/recharge")
public class Recharge extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (resp.getHeader("Token") != null) {
            resp.getWriter().println(req.getAttribute("id"));
        }
    }
}


Token.java

    /**
     * 后端拿到前端请求头的token对象,验证身份,比较有效时间
     *
     * @param req
     * @param resp
     * @return
     * @throws ParseException
     */
    public static void timethan(HttpServletRequest req, HttpServletResponse resp) throws ParseException, IOException {

        //拿到token对象
        try {
            String str = Base644.decoding(req.getHeader("Token"));
            //将token切割成两部分
            //str:"id:1001,status:1,endtime:2022-01-08 19:18:43";fb675266364f697519dac6d1e6ec1da3
            String ahead = str.substring(0, str.indexOf(";"));
            String behind = str.substring(str.indexOf(";") + 1, str.length());

            //时间从字符串中截取出来
            String ss = ahead.substring(ahead.indexOf("e"), ahead.length());
            String cc = ss.substring(ss.indexOf(":") + 1, ss.length());

            //将字符串的时间转为long类型的数据进行比较
            SimpleDateFormat sif = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date data = sif.parse(cc);
            long stime = data.getTime();
            Date date1 = new Date();
            Date dateafter = new Date(date1.getTime());
            long nowtime = dateafter.getTime();
            long differen = stime - nowtime;

            //解析当前token对象的id,状态
            int id = Integer.parseInt(ahead.substring(ahead.indexOf("i") + 3, ahead.indexOf(",")));
            int status = Integer.parseInt(ahead.substring(ahead.indexOf("s") + 7, ahead.lastIndexOf(",")));

            if (getMd5(ahead).equals(behind)) {
                try {
                    if (differen < 0) {
                        resp.getWriter().println("请重新登录!");
                    } else {
                        resp.getWriter().println("前端请求的业务处理结果,后端已送到,请接受!");
                        //创建一个新的Token
                        resp.getWriter().println("Token:" + createToken(id, status));
                        resp.setHeader("Token", createToken(id, status));
                        req.setAttribute("id", id);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                resp.getWriter().println("请重新登录!");
            }
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建Token对象
     *
     * @param id
     * @param status
     */
    public static String createToken(int id, int status) throws UnsupportedEncodingException {
        SimpleDateFormat sif = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        Date dateafter = new Date(date.getTime() + 300000);
        Object endtime = sif.format(dateafter);
        String json = "id:" + id + ",status:" + status + ",endtime:" + endtime;
        JSONObject jsonObject = new JSONObject();
        String ss = jsonObject.toJSONString(json);
        System.out.println(ss);

        String begin = ss + ";" + getMd5(ss);
        //调用并转换成base64
        return Base644.encoding(begin);
    }

Token.http

GET http://localhost:8080/war/helloworld?name=cc&password=cc123
Accept: application/json;application/json;charset=utf-8

###
POST http://localhost:8080/war/recharge
Content-Type: application/json;charset=utf-8
Token: ImlkOjEwMDEsc3RhdHVzOjEsZW5kdGltZToyMDIyLTAxLTEwIDEyOjAwOjA0IjtkYjE3Y2M4YjJlZWVkZGJjMjhlMDBhMTA0MTdjNTM0OA==

{
  "id": 1001,
  "name": "云先生",
  "date": [
    {
      "create_time": "2022-01-06"
    }
  ]
}

最后请看效果图:

登录请求:

io java 过滤流抽象类 java过滤器实现_java_05


业务请求:

io java 过滤流抽象类 java过滤器实现_ide_06

今天就到这里啦,有疑问的看友请留言或私聊我哦