说明:filter文件里面DemoFilter类实现Filter接口。
- package com.itheima.filter;
-
-
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import java.io.IOException;
- //用于指定一个过滤器要拦截的URL模式。
- @WebFilter(urlPatterns = "/*")
- public class DemoFilter implements Filter {
- @Override //初始化方法, 只调用一次
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("init 初始化方法执行了");
- }
-
- @Override //拦截到请求之后调用, 调用多次
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- System.out.println("Demo 拦截到了请求...放行前逻辑");
- //放行
- chain.doFilter(request, response);
-
- System.out.println("Demo 拦截到了请求...放行后逻辑");
- }
-
- @Override //销毁方法, 只调用一次
- public void destroy() {
- System.out.println("destroy 销毁方法执行了");
- }
- }
- package com.itheima;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.web.servlet.ServletComponentScan;
- //开启了servlet组件支持(拦截支持)
- @ServletComponentScan
- @SpringBootApplication
- public class TliasWebManagementApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(TliasWebManagementApplication.class, args);
- }
-
- }
说明:请求->放行前逻辑->放行->资源->放行;创建一个另一个XbcFilter类实现Filter接口。执行顺序根据类名字母顺序一次进行。
- package com.itheima.filter;
-
- import javax.servlet.*;
- import javax.servlet.annotation.WebFilter;
- import java.io.IOException;
- //执行顺序类名首字母靠前就在前
- @WebFilter(urlPatterns = "/*")
- public class XbcFilter implements Filter {
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- System.out.println("Abc 拦截到了请求...放行前逻辑");
- //放行
- chain.doFilter(request,response);
-
- System.out.println("Abc 拦截到了请求...放行后逻辑");
- }
- }
- package com.itheima.filter;
-
- import com.alibaba.fastjson.JSONObject;
- import com.itheima.controller.utils.JwtUtils;
- import com.itheima.pojo.Result;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.util.StringUtils;
-
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @Slf4j
- @WebFilter(urlPatterns = "/*")
- public class LoginCheckFilter implements Filter {
- @Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- // 强转我们可以使用HttpServletRequest和ServletResponse对象中的所有方法,而不受Spring框架的限制。
- HttpServletRequest req = (HttpServletRequest) request;
- HttpServletResponse resp = (HttpServletResponse) response;
-
- //1.获取请求url。
- String url = req.getRequestURL().toString();
- log.info("请求的url: {}", url);
-
- //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
- if (url.contains("login")) {
- log.info("登录操作, 放行...");
- chain.doFilter(request, response);
- // 如果不写return语句,那么程序会继续执行下一个过滤器,直到过滤器链中的最后一个过滤器执行完毕。
- return;
- }
-
- //3.获取请求头中的令牌(token)。
- String jwt = req.getHeader("token");
-
- //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
- if (!StringUtils.hasLength(jwt)) {
- log.info("请求头token为空,返回未登录的信息");
- Result error = Result.error("NOT_LOGIN");
- //手动转换 对象--json --------> 阿里巴巴fastJSON
- String notLogin = JSONObject.toJSONString(error);
- // HttpServletResponse接口提供了一个getWriter()方法,该方法返回一个PrintWriter对象,用于将数据写入HTTP响应中。
- resp.getWriter().write(notLogin);
- return;
- }
-
- //5.解析token,如果解析失败,返回错误结果(未登录)。
- try {
- // ctrl+alt+t try,catch使用
- JwtUtils.parseJWT(jwt);
- } catch (Exception e) {//jwt解析失败
- e.printStackTrace();
- log.info("解析令牌失败, 返回未登录错误信息");
- Result error = Result.error("NOT_LOGIN");
- //手动转换 对象--json --------> 阿里巴巴fastJSON
- // 将error对象转成字符串
- String notLogin = JSONObject.toJSONString(error);
- // 直接响应给浏览器
- resp.getWriter().write(notLogin);
- return;
- }
-
- //6.放行。
- log.info("令牌合法, 放行");
- chain.doFilter(request, response);
-
- }
- }
说明:是一种动态拦截方法调用的机制,类似于过滤器。Spig框架中提供的,用来动态拦截控制器方法的执行。
- package com.itheima.interceptor;
-
- import com.alibaba.fastjson.JSONObject;
- import com.itheima.controller.utils.JwtUtils;
- import com.itheima.pojo.Result;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Component;
- import org.springframework.util.StringUtils;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- @Slf4j
- //IOC容器管理
- @Component
- public class LoginCheckInterceptor implements HandlerInterceptor {
- @Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
- public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
- //1.获取请求url。
- String url = req.getRequestURL().toString();
- log.info("请求的url: {}",url);
-
- //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
- if(url.contains("login")){
- log.info("登录操作, 放行...");
- return true;
- }
-
- //3.获取请求头中的令牌(token)。
- String jwt = req.getHeader("token");
-
- //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
- if(!StringUtils.hasLength(jwt)){
- log.info("请求头token为空,返回未登录的信息");
- Result error = Result.error("NOT_LOGIN");
- //手动转换 对象--json --------> 阿里巴巴fastJSON
- String notLogin = JSONObject.toJSONString(error);
- resp.getWriter().write(notLogin);
- return false;
- }
-
- //5.解析token,如果解析失败,返回错误结果(未登录)。
- try {
- JwtUtils.parseJWT(jwt);
- } catch (Exception e) {//jwt解析失败
- e.printStackTrace();
- log.info("解析令牌失败, 返回未登录错误信息");
- Result error = Result.error("NOT_LOGIN");
- //手动转换 对象--json --------> 阿里巴巴fastJSON
- String notLogin = JSONObject.toJSONString(error);
- resp.getWriter().write(notLogin);
- return false;
- }
-
- //6.放行。
- log.info("令牌合法, 放行");
- return true;
- }
-
- @Override //目标资源方法运行后运行
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("postHandle ...");
- }
-
- @Override //视图渲染完毕后运行, 最后运行
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("afterCompletion...");
- }
- }
- package com.itheima.config;
-
- import com.itheima.interceptor.LoginCheckInterceptor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- @Configuration //配置类
- public class WebConfig implements WebMvcConfigurer {
-
- @Autowired
- private LoginCheckInterceptor loginCheckInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- // registry添加一个拦截器,定义的一个loginCheckInterceptor类;拦截什么路径的资源 /**表示所有容器,/*表示一级路径,不拦截/login资源
- registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
- }
- }