刚刚在测试接口的时候发现一个奇怪的问题:通过拦截器获取 controller 类注解,有些能获取到,有些又不能获取到,见鬼了。

  【环境】:

    1. springboot :2.2.0.RELEASE

  【场景】:

    1. 定义一个登陆拦截器,对请求的 token 进行校验;

    2. 定义两个注解:

      RequiredLogin :要求登录注解

      NoRequiredLogin :不要求登录注解

    3. 在要求登录的 controller 类上添加 RequiredLogin 注解,然后在拦截器中获取 controller 是否有该注解,如果有,则进行token校验;

  【问题】:

    两个不同的 controller ,都添加了 RequiredLogin 注解,在拦截器中使用同样的代码获取注解,期中一个 controller 能够获取到,一个不能。

  【代码】

    拦截器代码:


@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
startMillis.set(System.currentTimeMillis());
if (handler instanceof HandlerMethod) {
HandlerMethod myHandlerMethod = (HandlerMethod) handler;
Object bean = myHandlerMethod.getBean();
Annotation classLoginAnnotation = bean.getClass().getAnnotation(RequiredLogin.class);// 类级别的要求登录标记
System.out.println("类:"+bean.getClass()+",类注解:"+classLoginAnnotation);
Method method = myHandlerMethod.getMethod();
Annotation methodLoginAnnotation = method.getAnnotation(RequiredLogin.class);// 方法级别的要求登录标记
Annotation methodNologinAnnotation = method.getAnnotation(NoRequiredLogin.class);// 方法级别的不要求登录标记 if ((classLoginAnnotation != null && methodNologinAnnotation == null)
|| (classLoginAnnotation == null && methodLoginAnnotation != null)) {
//验证登陆
if (isLogin(request))
return true;
else {
// 未登录
ApiResp apiResp=ApiRespBuilder.buildFailResp(ErrorCodeEnum.code_1001);
response.setHeader("content-type", "application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSONObject.fromObject(apiResp).toString());
return false;
}
}
}
return true;
}

    controller 代码:

@RequestMapping("/device")
@RestController
@RequiredLogin
public class DeviceController extends BaseController {
@RequestMapping("/hotel")
@RestController
@RequiredLogin
public class HotelController extends BaseController {

  【结果】

    分别对两个不同 controller 的接口进行请求,并且都不带token,发现 HotelController 返回要求登录,而 DeviceController 接口进入业务代码然后由于没有token报错

      HotelController:

        

      DeviceController:

        

    打印结果:

      HotelController:

        

      DeviceController:

        

      从打印结果看,两个类的打印信息确实有些不一样,但是我看不懂。。。我也仔细对比两个 Controller 类,但是好像没啥不同。

  【说明】

    这个拦截器我是从以前的代码拷贝来的,在很多项目中使用过了,一直没有这个问题。于是我对比之前代码的 springboot 版本。之前的版本的 2.2.1,现在的版本是 2.2.0,于是以为是版本问题,但是改成 2.2.1 后也没有用。

  【解决】

    拦截器代码改一下,直接使用 HandlerMethod 的 getBeanType 方法获取 controller 的 class 信息,而不是先 获取 bean,在 getClass():

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
startMillis.set(System.currentTimeMillis());
if (handler instanceof HandlerMethod) {
HandlerMethod myHandlerMethod = (HandlerMethod) handler;
Annotation classLoginAnnotation = myHandlerMethod.getBeanType().getAnnotation(RequiredLogin.class);// 类级别的要求登录标记
Method method = myHandlerMethod.getMethod();
Annotation methodLoginAnnotation = method.getAnnotation(RequiredLogin.class);// 方法级别的要求登录标记
Annotation methodNologinAnnotation = method.getAnnotation(NoRequiredLogin.class);// 方法级别的不要求登录标记 if ((classLoginAnnotation != null && methodNologinAnnotation == null)
|| (classLoginAnnotation == null && methodLoginAnnotation != null)) {
//验证登陆
if (isLogin(request))
return true;
else {
// 未登录
ApiResp apiResp=ApiRespBuilder.buildFailResp(ErrorCodeEnum.code_1001);
response.setHeader("content-type", "application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSONObject.fromObject(apiResp).toString());
return false;
}
}
}
return true;
}

  【原因】

    还不知道,不太懂 spring 深层原理。。(仅记录一下问题经验)

拦截器中获取不到controller注解问题的更多相关文章

  1. spring boot拦截器中获取request post请求中的参数

    最近有一个需要从拦截器中获取post请求的参数的需求,这里记录一下处理过程中出现的问题. 首先想到的就是request.getParameter(String )方法,但是这个方法只能在get请求中取 ...

  2. [技巧篇]08.Struts2拦截器中获取Servlet API方法

    讲课中遇到的解决Session拦截器的后腿问题,还有如何在拦截器中获取Servlet API,这里留一个备注,方便学生查找

  3. MVC 在action拦截器中获取当前进入的控制器和aciton名

    我们在实现了action拦截器以后(继承至System.Web.Mvc.IActionFilter),需要在重写的方法OnActionExecuting中去获得当前进入的控制器和action名称,如何 ...

  4. springboot拦截器中获取配置文件值

    package com.zhx.web.interceptor; import com.zhx.util.other.IpUtil; import org.slf4j.Logger; import o ...

  5. spring boot拦截器中获取request post请求中的参数(转)

    文章转自 https://www.jianshu.com/p/69c6fba08c92

  6. 【spring boot】在自定义拦截器中从request中获取json字符串

    又这样的需求,需要在自定义的拦截器中获取request中的数据,想获取到的是JSON字符串 那需要在拦截器中写这样一个方法 public static String getOpenApiRequest ...

  7. 解决SpringMVC拦截器中Request数据只能读取一次的问题

    解决SpringMVC拦截器中Request数据只能读取一次的问题 开发项目中,经常会直接在request中取数据,如Json数据,也经常用到@RequestBody注解,也可以直接通过request ...

  8. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  9. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

随机推荐

  1. linux查看 LAMP环境安装路径

    Apache: 如果采用RPM包安装,安装路径应在 /etc/httpd目录下 apache配置文件:/etc/httpd/conf/httpd.conf Apache模块路径:/usr/sbin/a ...

  2. un-资源-开源-WebGallery:Windows Web App Gallery

    ylbtech-资源-开源-WebGallery:Windows Web App Gallery Windows Web App Gallery 1.返回顶部   2.返回顶部   3.返回顶部   ...

  3. 【转载】 Tensorflow中padding的两种类型SAME和VALID

    原文地址: https://blog.csdn.net/jasonzzj/article/details/53930074 -------------------------------------- ...

  4. 七、postman-request methods

    一.一些常见的请求方法 GET POST PUT DELETE PATCH

  5. 戒邪淫利器:《楞严经 四种清净明诲》实例及原经文 (转自学佛网:http://www.xuefo.net/nr/article55/545256.html)

    今日得持首楞严,不读天下糟粕书! 当你读完楞严经后就会很真实的升起这个感觉!根本觉得其他书都是多余的!所以<楞严经>还是要多读,多看!并且<楞严经>戒淫的效果特别好!好好的珍惜 ...

  6. Java Thread Local – How to use and code sample(转)

    转载自:https://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ Thread Local ...

  7. [转]jkeyll的安装步骤

    链接地址:https://nxjniexiao.github.io/2018/08/17/jkeyll-install/

  8. 【网络开发】UDP组播接收端解析

    UDP组播接收端解析 网络中的一台主机如果希望能够接收到来自网络中其它主机发往某一个组播组的数据报,那么这么主机必须先加入该组播组,然后就可以从组地址接收数据包.在广域网中,还涉及到路由器支持组播路由 ...

  9. composer 添加贝宝PayPal

    composer require "paypal/rest-api-sdk-php:1.7.2"

  10. JIRA中的并联审批流程定制

    JIRA号称可以跟踪任何事务,让JIRA的流程来匹配团队的工作流程,而不是让你的团队适应JIRA的工作流程.但是在实践中,有些有些流程用JIRA还是比较困难的,比如并联审批流程,一个并联审批流程需求大 ...