java Servlet注解实现过滤器
写在前面的话: 这篇文章是与Token验证关联的,看友们可以去看看俺的这篇Servlet的Token的实现
实现Servlet过滤器方式:
1、在xml文件里面配置
2、在文件头添加注解、
首先我们应该知道什么是过滤器:
java过滤器:顾名思义,就是在java中起到过滤的作用的一个方法。
可以在一个请求到达servlet之前,将其截取进行逻辑判断,然后决定是否放行到请求的servlet中。
也可以在一个response到达客户端之前,截取结果进行逻辑判断,然后决定是否允许返回给客户端。
在前面文章Token的实现中,我们可以知道,用户第一次登录是没有Token的,需要验证生成。同时前端需要在每次业务请求带上后端返回最新的一个Token,下面我们用过滤器进行Token的过滤。
1、首先新建一个java文件,继承Filter,并在文件头上加上@WebFilter注解,这里的Url是业务页面的请求地址,/*
可匹配多个请求并处理
@WebFilter(urlPatterns = "/recharge/*")
public class Myfilter implements Filter {
继承了Filter接口,就需要实现的三个方法:
看单词的意思,doFilter方法应该就是处理过滤的方法
@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请求:
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"
}
]
}
最后请看效果图:
登录请求:
业务请求:
今天就到这里啦,有疑问的看友请留言或私聊我哦