springboot 框架项目持续更新 mysql+mybatis+maven+redis+https+日志配置+自定义拦截器+Druid (二)——自定义拦截器

在第一篇中(https://blog.csdn.net/qq_39526250/article/details/80782864)我们已经搭建了基础的springboot项目讲述了搭建基本的springboot项目+mybatis+mysql数据库,详细的增删改查就不再写了,不知道的可以去百度或者提问。本文章开始讲述自定义拦截器的类容。

1.首先创建拦截器 AuthInterceptor 继承字 HandlerInterceptorAdapter 并重写 preHandle 方法

package com.bctc.servlet.Intercept;

import com.bctc.entity.SMKeyBeen;
import com.bctc.service.SSLService;
import com.bctc.servlet.redis.RedisUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 添加拦截器 AuthInterceptor 继承字 HandlerInterceptorAdapter 重写 preHandle 方法
 * 所有请求先进来这里
 */
@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
    private Logger log = Logger.getLogger(AuthInterceptor.class);
    @Autowired
    private SSLService sSLService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("--进入拦截器AuthInterceptor--");
        if (!HandlerMethod.class.isAssignableFrom(handler.getClass())) {
            log.info("--进入拦截器1,是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的子类或接口。 ");
            return true;
        }

        // 如果不是映射到方法直接通过
       /* if (!(handler instanceof HandlerMethod)) {
            log.info("--进入拦截器,但该方法不需要拦截,用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。 ");
            return true;
        }*/

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        String requestPath = request.getRequestURI();
        // log.debug("requestIp: " + getIpAddress(request));
        //log.debug("Method: " + method.getName() + ", OenIntercept: " + method.isAnnotationPresent(OenIntercept.class));
        //log.debug("requestPath: " + requestPath);
        if (!handlerMethod.hasMethodAnnotation(OenIntercept.class) && handlerMethod.getBeanType().getAnnotation(OenIntercept.class) == null && !handlerMethod.hasMethodAnnotation(TwoIntercept.class) && handlerMethod.getBeanType().getAnnotation(TwoIntercept.class) == null) {
            log.info("--进入拦截器,类和方法上都没有拦截注解");
            return true;
        }
        if (requestPath.contains("/111") || requestPath.contains("/swagger") || requestPath.contains("/configuration/ui")) {
            log.info("--1123");
            return true;
        }
        if (requestPath.contains("/error")) {
            log.info("--1111333");
            return true;
        }

        if (method.isAnnotationPresent(OenIntercept.class) || handlerMethod.hasMethodAnnotation(OenIntercept.class)) {
            log.info("---OenIntercept----");
            String token = request.getHeader("ACCESS_TOKEN");
            token = "P100AFH00W";
            log.debug("token: " + token);
            if (token.equals("") || token == null) {
                throw new Exception("无效token");
            }
            SMKeyBeen ssLs = sSLService.getSSLs(token);
            log.info(ssLs.getId());
            request.setAttribute("currentUser", ssLs);
            RedisUtils redisUtils = WebApplicationContextUtils
                    .getWebApplicationContext(request.getServletContext()).getBean(RedisUtils.class);
            redisUtils.set("niuhao", ssLs);
            return true;
        }
        if (method.isAnnotationPresent(TwoIntercept.class) || handlerMethod.hasMethodAnnotation(TwoIntercept.class)) {
            log.info("---TwoIntercept----");
            String token = request.getHeader("ACCESS_TOKEN");
            token = "P100AFH00W";
            log.debug("token: " + token);
            if (token.equals("") || token == null) {
                throw new Exception("无效token");
            }
            SMKeyBeen ssLs = sSLService.getSSLs(token);
            log.info(ssLs.getId());
            ssLs.setId(123456);
            request.setAttribute("TwoCurrent", ssLs);

            return true;
        }
        log.info("-离开拦截器");
        return true;
    }
}
/*Class.isAssignableFrom()方法 与 instanceof 关键字的区别

1. Class.isAssignableFrom()
是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的子类或接口。
格式为: Class1.isAssignableFrom(Class2)
调用者和参数都是java.lang.Class类型, 返回值:boolean类型

以:Object,String为例
a. "String是Object的父类"
   String.class.isAssignableFrom(Object.class) 结果false;

b. "Object是String的父类"
   Object.class.isAssignableFrom(String.class) 结果true;

c. "Object和Object相同"
   Object.class.isAssignableFrom(Object.class) 结果true;


2. instanceof
用来判断一个对象实例是否是一个类或接口的或其子类子接口的实例。
格式是:o instanceof TypeName
第一个参数是对象实例名,第二个参数是具体的类名或接口名。

以:Object,String为例
String str = new String();
String obj = new Object();

a. "Object是String的父类"
   str instanceof Object 结果true;

b. "String和String相同"
   str instanceof String 结果true;

*/

2.OenIntercept第一个拦截注解

package com.bctc.servlet.Intercept;
import java.lang.annotation.*;

/**
 * 第一个拦截注解
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface OenIntercept {
}

3.OenCurrent 用于标识用户实体类入参,参数级注解

package com.bctc.servlet.Intercept;

import java.lang.annotation.*;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@OenCurrent 用于标识用户实体类入参,参数级注解
public @interface OenCurrent {
}

4.添加参数解析器 OenCurrentMethodArgumentResolver

package com.bctc.servlet.Intercept;

import com.bctc.entity.SMKeyBeen;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

//     添加参数解析器 OenCurrentMethodArgumentResolver
public class OenCurrentMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        System.out.println("--OenCurrentMethodArgumentResolver--");
        return parameter.getParameterType().isAssignableFrom(SMKeyBeen.class)
                && parameter.hasParameterAnnotation(OenCurrent.class);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        SMKeyBeen userInfo = (SMKeyBeen) webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_REQUEST);
        if (userInfo != null) {
            System.out.println(userInfo.getId()+"----");
            return userInfo;
        }
        throw new MissingServletRequestPartException("currentUser");
    }
}

5.然后就是在MyWebMvcConfigurerAdapter配置拦截器(将下面内容复制进去就可以

package com.bctc.servlet.Intercept;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

/**
 * springboot1.0 继承WebMvcConfigurerAdapter
 * 注册拦截器和参数解析器在 WebMvcConfigurerAdapter 中,需要注意,拦截器中引用了 UserService 所以在注册时需要使用 @Bean 的形式以告诉 Spring 注入
 */

@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    //关键,将拦截器作为bean写入配置中
    @Bean
    public AuthInterceptor myAuthInterceptor() {
        return new AuthInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        InterceptorRegistration ir = registry.addInterceptor(myAuthInterceptor());
        // 配置不拦截的路径
        ir.excludePathPatterns("/RemotecontrolController/*");
        // 配置拦截的路径
        ir.addPathPatterns("/**");
        // 还可以在这里注册其它的拦截器
        //registry.addInterceptor(roleInterceptor).addPathPatterns("/getstudent");
        //registry.addInterceptor(new OtherInterceptor()).addPathPatterns("/**");
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        //第一个参数解析器
        argumentResolvers.add(oenCurrentMethodArgumentResolver());
        //第二个参数解析器
        argumentResolvers.add(twoCurrentUserMethodArgumentResolver());
        super.addArgumentResolvers(argumentResolvers);
    }

    @Bean//第一个参数解析器
    public OenCurrentMethodArgumentResolver oenCurrentMethodArgumentResolver() {
        return new OenCurrentMethodArgumentResolver();
    }

    @Bean//第二个参数解析器
    public TwoCurrentMethodArgumentResolver twoCurrentUserMethodArgumentResolver() {
        return new TwoCurrentMethodArgumentResolver();
    }
      /*  @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {

            registry.addResourceHandler("/static/**").addResourceLocations("/static/");

            super.addResourceHandlers(registry);
        }*/

}

6.在controller层中的使用

@RequestMapping("/getssl/{serialNumber}")
@ResponseBody
//@Pathvariable注解绑定它传过来的值到方法的参数上//RESTful 风格//http://10.20.10.86:9080/ssl/getssl/P100AFH00W
public Ret<Map> getSSL(@PathVariable("serialNumber") String serialNumber) throws Exception {}
@OenIntercept
@RequestMapping("/test")
String test(@OenCurrent SMKeyBeen sMKeyBeen) throws Exception {
    SMKeyBeen niuhao = (SMKeyBeen) redisUtils.get("niuhao");
    System.out.println(niuhao.getAddtime());
    System.out.println(redisUtils.get("niuhao11"));
    //System.out.println("---0-000-"+sMKeyBeen.getId());
    System.out.println("---0-000-" + sMKeyBeen.getId());
    return "111111111";
}

@TwoIntercept
@RequestMapping("/tWO")
@ResponseBody
public String tWO(@TwoCurrent SMKeyBeen sMKeyBeen) throws Exception {
    //  SMKeyBeen niuhao = crudRepository.findOne("123456");
    //  System.out.println(niuhao.getAddtime());
    //System.out.println("---0-000-"+sMKeyBeen.getId());
    System.out.println("---0-000-" + sMKeyBeen.getId());
    return "111122";
}

 

请求getssl方式时,因为没有拦截器注解所以会执行

--进入拦截器AuthInterceptor--

--进入拦截器,类和方法上都没有拦截注解

也就是说在拦截器AuthInterceptor中执行了

 

if (!handlerMethod.hasMethodAnnotation(OenIntercept.class) && handlerMethod.getBeanType().getAnnotation(OenIntercept.class) == null) == null) {
    System.out.println("--进入拦截器,类和方法上都没有拦截注解");
    return true;
}

请求test方式时,因为该方法上有@OenIntercept的注解,同时有OenCurrent 用于标识用户实体类入参,参数级注解

所以会先进入AuthInterceptor中执行

 

if (method.isAnnotationPresent(OenIntercept.class) || handlerMethod.hasMethodAnnotation(OenIntercept.class)) {

            log.info("--1111444IgnoreSecurity");
            String token = request.getHeader("ACCESS_TOKEN");
            token = "P100AFH00W";
            log.debug("token: " + token);
            if (token.equals("") || token == null) {
                throw new Exception("无效token");
            }
            SMKeyBeen ssLs = sSLService.getSSLs(token);
            System.out.println(ssLs.getId());
            request.setAttribute("currentUser", ssLs);
            return true;
        }

然后进入执行OenCurrentMethodArgumentResolver,test方法就可接收到实体参数sMKeyBeen(原本请求路径为http://10.20.10.86:9080/ssl/test)并没有参数传递,同过拦截器实现了修改请求的参数。

7.多个拦截器注解和参数解析器。在代码中标注第一个xxx的地方复制粘贴即可,将Application.java中相关代码改为如下

 

/**
 注册拦截器和参数解析器在 WebMvcConfigurerAdapter 中,需要注意,拦截器中引用了 UserService 所以在注册时需要使用 @Bean 的形式以告诉 Spring 注入
 */
@Configuration
public class MyWebMvcConfigurerAdapter extends WebMvcConfigurerAdapter {
    //关键,将拦截器作为bean写入配置中
    @Bean
    public AuthInterceptor myAuthInterceptor() {
        return new AuthInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        InterceptorRegistration ir = registry.addInterceptor(myAuthInterceptor());
        // 配置拦截的路径
        ir.addPathPatterns("/**");
        // 配置不拦截的路径
       // ir.excludePathPatterns("/ssl/getssl");
        // 还可以在这里注册其它的拦截器
        //registry.addInterceptor(roleInterceptor).addPathPatterns("/getstudent");
        //registry.addInterceptor(new OtherInterceptor()).addPathPatterns("/**");
    }
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        //第一个参数解析器
        argumentResolvers.add(oenCurrentMethodArgumentResolver());
        //第二个参数解析器
        argumentResolvers.add(twoCurrentUserMethodArgumentResolver());
        super.addArgumentResolvers(argumentResolvers);
    }
    @Bean//第一个参数解析器
    public OenCurrentMethodArgumentResolver oenCurrentMethodArgumentResolver() {
        return new OenCurrentMethodArgumentResolver();
    }
    @Bean//第二个参数解析器
    public TwoCurrentMethodArgumentResolver twoCurrentUserMethodArgumentResolver() {
        return new TwoCurrentMethodArgumentResolver();
    }
}

8.项目完整结构

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值