应用场景举例:

当不同身份的用户请求一个接口时,用来校验用户某些身份,这样可以对单个字段数据进行精确权限控制,具体看代码注释

自定义注解

/**
* 对比请求的用户身份是否符合
* @author liuyalong
* @date 2020/9/25 16:03
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CompareUser {
/**
* The name of the request parameter to bind .
*/
@AliasFor("name") String value() default "";
@AliasFor("value") String name() default "";
}

给controller的字段添加注解

    @ApiOperation(value = "删除用户", notes = "根据手机号来删除用户")
@PostMapping(value = "/delete_phone")
public BaseCommonResult<Integer> deletePhone(@CompareUser(value = "phone") String phone) {
int i = userService.deleteByPhone(phone);
return BaseCommonResult.success(i);
}

参数解析器

记得继承后加@Component,这里是Base...所以不用

/**
* @author liuyalong
* @date 2020/9/25 15:56
*/
public class BaseCurrentUserInterceptor implements HandlerMethodArgumentResolver {
/**
* 用于判定是否需要处理该参数注解,返回true为需要,
* 并会去调用下面的方法resolveArgument。
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
//只处理CurrentUser注解修饰的参数
return parameter.hasParameterAnnotation(CompareUser.class);
} /**
* 对比用户信息
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
CompareUser parameterAnnotation = parameter.getParameterAnnotation(CompareUser.class); Class<?> parameterType = parameter.getParameterType();
if (parameterAnnotation == null) {
throw new IllegalArgumentException("Unknown parameter type [" + parameterType.getName() + "]");
} /*
* 获取要验证的字段名
*/ //检查是否给字段取了别名
String paramName = "".equalsIgnoreCase(parameterAnnotation.name()) ? parameterAnnotation.value() : parameterAnnotation.name();
if ("".equalsIgnoreCase(parameterAnnotation.name())) {
//从参数中获取定义的字段名
paramName = parameter.getParameter().getName();
} //获取请求字段的值
String paramValue = String.valueOf(webRequest.getParameter(paramName)); //从请求头中获取已经登录的用户
String userName = webRequest.getHeader(AuthConstant.USER_TOKEN_HEADER); //对于root用户,可以操作一切,所以直接返回
if (!AuthConstant.ROOT_USER.equals(userName)) {
//判断身份是否一致,不一致就抛出异常,让RestControllerAdvice处理
if (userName == null || !userName.equals(paramValue)) {
throw new NotSameAuthorException();
}
}
//将参数原封不动返回出去,需要还原回需要的类型
WebDataBinder binder = binderFactory.createBinder(webRequest, parameterType, paramName);
return binder.convertIfNecessary(paramValue, parameterType, parameter);
}
}

配置WebMvcConfigurer

注意这里提供了两种方式加载,因为

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private HandlerInterceptor handlerInterceptor; @Autowired
private HandlerMethodArgumentResolver currentUserInterceptor; @Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor).addPathPatterns("/**");
} //参数解析器,自定义的优先级最低,所以会失效,
// 解决方案是下面的 @PostConstruct ,把优先级调最高
// 但是这样@PathParam @RequestParam就失效了,@CompareUser(value="xxx")可以完全替换@RequestParam功能
// @Override
// public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
// resolvers.add(currentUserInterceptor);
//
// } /**
*参数解析器优先级调最高
*/
@PostConstruct
public void init() {
// 获取当前 RequestMappingHandlerAdapter 所有的 Resolver 对象
List<HandlerMethodArgumentResolver> resolvers = requestMappingHandlerAdapter.getArgumentResolvers();
List<HandlerMethodArgumentResolver> newResolvers = new ArrayList<>(resolvers.size() + 1); // 添加自定义参数解析器到集合首位
newResolvers.add(currentUserInterceptor); // 添加 已注册的 Resolver 对象集合
newResolvers.addAll(resolvers);
// 重新设置 Resolver 对象集合
requestMappingHandlerAdapter.setArgumentResolvers(newResolvers);
}
}

效果

只有特定身份人员才可以删除操作

最新文章

  1. VadRoot枚举进程模块在Windows7下的完整实现
  2. 【直播】APP全量混淆和瘦身技术揭秘
  3. 手机移动端WEB资源整合
  4. 关于JDK 安装,以及Java环境的设置
  5. svn命令
  6. MyBatis Generator 详解 【转来纯为备忘】
  7. &#39;MAMapKit/MAMapKit.h&#39; file not found
  8. 第一款支持容器和云部署的开源数据库Neo4j 3.0
  9. 使用Storm实现实时大数据分析
  10. http://www.cnblogs.com/leiOOlei/p/5075402.html
  11. 剑指offer--面试题19
  12. Codeforces Round #232 (Div. 1)
  13. Jquery 中each循环嵌套的使用示例教程
  14. python 数据清洗之数据合并、转换、过滤、排序
  15. 多版本python安装TensorFlow出现的各种事故
  16. JDK1.8源码(三)——java.util.HashMap
  17. numpy学习之前的必要数学知识:线性代数
  18. PrefixSpan
  19. python中的字符串编码问题——3.各操作系统下的不同编码方式
  20. java 进销存 库存管理 销售报表 商户管理 springmvc SSM crm 项目

热门文章

  1. 头秃了,二十三张图带你从源码了解Spring Boot 的启动流程~
  2. Python_进程process 与 线程thread
  3. 统计数字问题(Java)
  4. Android开发-AlertDialog,Progress,ProgressDialog,自定义layout
  5. 小程序后端获取openid (php实例)
  6. 类虚拟机软件CrossOver是什么?它的优势在哪里?
  7. C3PO数据库连接池
  8. 记XShell无法连接虚拟机中的Linux,但Linux系统中可以连接外网。
  9. uniapp分包(详尽版)
  10. IntelliJ IDEA 配置《算法》(第四版)