Spring自定义参数解析器

在这篇文章中,我们认识了参数解析器和消息转换器,今天我们来自定义一个参数解析器。

自定义参数解析器

实现HandlerMethodArgumentResolver的类,并注册到Spring容器。

@Component//注册到Spring
public class UserArgResolver implements HandlerMethodArgumentResolver {@Overridepublic boolean supportsParameter(MethodParameter parameter) {// 如果参数上有@User注解,并且参数类型是User或者其子类,则可以使用这个参数解析器return parameter.hasParameterAnnotation(User.class) && parameter.getParameterType().isAssignableFrom(UserInfo.class);}@Overridepublic Object resolveArgument(MethodParameter parameter,ModelAndViewContainer mavContainer,NativeWebRequest webRequest,WebDataBinderFactory binderFactory) throws Exception {final HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();final String userName = request.getHeader("userName");if (userName == null) {throw new RuntimeException("请求头中缺少用户信息");}final UserInfo user = new UserInfo();user.setName(userName);//返回值直接给Controller了return user;}
}

Spring Boot直接把解析器定义为Bean即可,如果是SpringMVC则需要这样注册

@Configuration
public class Config implements WebMvcConfigurer {@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(new UserArgResolver());}
}

定义接口

    @GetMapping("/test2")@ResponseBodypublic String test2(@User UserInfo userInfo) {System.out.println(userInfo.getName());return "ok";}

UserInfo

public class UserInfo {private String name;// get and set
}

注解

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;@Target({PARAMETER})
@Retention(RUNTIME)
@Documented
public @interface User {
}

我们的参数解析器是从请求头中解析信息,请求头中要有userName属性,不然会抛异常。请求方式如下:
在这里插入图片描述
此时Controller中的接口上可以成功接收参数解析器中解析到的UserInfo参数。

值得注意的是Spring Boot的参数解析是否生效和添加顺序也有关系,下面是RequestMappingHandlerAdapter中默认的添加顺序

private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(30);// 基于注解resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));resolvers.add(new RequestParamMapMethodArgumentResolver());resolvers.add(new PathVariableMethodArgumentResolver());resolvers.add(new PathVariableMapMethodArgumentResolver());resolvers.add(new MatrixVariableMethodArgumentResolver());resolvers.add(new MatrixVariableMapMethodArgumentResolver());resolvers.add(new ServletModelAttributeMethodProcessor(false));resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));resolvers.add(new RequestHeaderMapMethodArgumentResolver());resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));resolvers.add(new SessionAttributeMethodArgumentResolver());resolvers.add(new RequestAttributeMethodArgumentResolver());// 基于参数类型resolvers.add(new ServletRequestMethodArgumentResolver());resolvers.add(new ServletResponseMethodArgumentResolver());resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));resolvers.add(new RedirectAttributesMethodArgumentResolver());resolvers.add(new ModelMethodProcessor());resolvers.add(new MapMethodProcessor());resolvers.add(new ErrorsMethodArgumentResolver());resolvers.add(new SessionStatusMethodArgumentResolver());resolvers.add(new UriComponentsBuilderMethodArgumentResolver());if (KotlinDetector.isKotlinPresent()) {resolvers.add(new ContinuationHandlerMethodArgumentResolver());}// 自定义if (getCustomArgumentResolvers() != null) {resolvers.addAll(getCustomArgumentResolvers());}// 兜底resolvers.add(new PrincipalMethodArgumentResolver());resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));resolvers.add(new ServletModelAttributeMethodProcessor(true));return resolvers;}

可以看到有两个RequestParamMethodArgumentResolver,第一个必须明确使用@RequestParam才会起作用,第二个优先级在自定义之后.

请求头参数

    @GetMapping("/test3")@ResponseBodypublic String test3(@RequestHeader("name") String headerName) {System.out.println(headerName);return "ok";}@GetMapping("/test3")@ResponseBodypublic String test3(HttpHeaders headers) {System.out.println(headers.get("name"));return "ok";}

上面连中获取请求头的写法中,第一种使用注解方式是正确的,第二种写法使用的是MapMethodProcessor,是获取不到完整的请求头的。我们自定义一个基于类型的请求头参数解析器也没用,因为MapMethodProcessor优先级高于自定义的优先级。此时可以对RequestMappingHandlerAdapter的argumentResolvers

@Configuration
public class Config implements WebMvcConfigurer {@Beanpublic RequestMappingHandlerAdapter adapter(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {//设置参数解析器final List<HandlerMethodArgumentResolver> argumentResolvers = requestMappingHandlerAdapter.getArgumentResolvers();List<HandlerMethodArgumentResolver> list1 = new ArrayList<>(argumentResolvers.size() + 1);// 自定义解析器添加到第一个位置list1.add(0, new UserArgResolver());list1.addAll(argumentResolvers);requestMappingHandlerAdapter.setArgumentResolvers(list1);return requestMappingHandlerAdapter;}
}

不过一般没必要这样,我们可以通过其他方式获取请求头,比如从请求对象中获取

    @GetMapping("/name3")@ResponseBodypublic String name3(HttpServletRequest request) {request.getHeader("name");return "ok";}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146092.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java集合必知必会:热门面试题汇编与核心源码(ArrayList、HashMap)剖析

写在前面 &#x1f525;我把后端Java面试题做了一个汇总&#xff0c;有兴趣大家可以看看&#xff01;这里&#x1f449; ⭐️在无数次的复习巩固中&#xff0c;我逐渐意识到一个问题&#xff1a;面对同样的面试题目&#xff0c;不同的资料来源往往给出了五花八门的解释&#…

【Linux进程控制】自主Shell

目录 自主shell实现 获取基本变量 实现命令行 获取用户命令字符串 命令行字符串分割 内建命令CD() chdir getcwd putenv 检查是否为内建命令 检查是否为重定向 执行命令 主函数设置 测试用例 项目代码 自主shell实现 根据之前学的内容&#xff0c;我们已经可以模…

【学习笔记】SSL/TLS安全机制之CAA

1、概念界定 CAA全称Certificate Authority Authorization&#xff0c;即证书颁发机构授权&#xff0c;每个CA都能给任何网站签发证书。 2、CAA要解决的问题 例如&#xff0c;蓝色网站有一张橙色CA颁发的证书&#xff0c;我们也知道还有许多其他的CA&#xff1b;中间人可以说服…

网址链接能做成二维码吗?在线网址二维码生成的操作技巧

现在用二维码能够展示很多的内容&#xff0c;将内容放入二维码后&#xff0c;通过扫码的方式获取内容会更加的方便快捷&#xff0c;简化获取内容的流程。比如在分享网上内容时&#xff0c;可以将链接生成二维码的方式来让用户扫码访问网页&#xff0c;那么网址转二维码具体该怎…

【BetterBench博士】2024年中国研究生数学建模竞赛 E题:高速公路应急车道紧急启用模型 问题分析

2024年中国研究生数学建模竞赛 E题&#xff1a;高速公路应急车道紧急启用模型 问题分析 更新进展 【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析 【BetterBench博士】2024年中国研究生数学建模竞赛 E题&#xff1a;高速公路应急车道紧急启用…

【垃圾识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目选题+TensorFlow+图像识别

一、介绍 垃圾识别分类系统。本系统采用Python作为主要编程语言&#xff0c;通过收集了5种常见的垃圾数据集&#xff08;‘塑料’, ‘玻璃’, ‘纸张’, ‘纸板’, ‘金属’&#xff09;&#xff0c;然后基于TensorFlow搭建卷积神经网络算法模型&#xff0c;通过对图像数据集进…

Qt窗口——对话框

文章目录 对话框自定义对话框对话框分类消息对话框QMessageBox使用示例自定义按钮快速构造对话框 颜色对话框QColorDialog文件对话框QFileDialog字体对话框QFontDialog输入对话框QInputDialog 对话框 对话框可以理解成一个弹窗&#xff0c;用于短期任务或者简洁的用户交互 Qt…

2024华为杯研赛D题分析

2024华为杯研究生数学建模D题分析如下&#xff0c;完整版本在文末名片

【HTTP】请求“报头”,Referer 和 Cookie

Referer 描述了当前这个页面是从哪里来的&#xff08;从哪个页面跳转过来的&#xff09; 浏览器中&#xff0c;直接输入 URL/点击收藏夹打开的网页&#xff0c;此时是没有 referer。当你在 sogou 页面进行搜索时&#xff0c;新进入的网页就会有 referer 有一个非常典型的用…

扎克伯格的未来愿景:用智能眼镜引领数字社交新时代

Meta Connect 2024大会前夕&#xff0c;创始人马克扎克伯格的90分钟播客访谈&#xff0c;为我们描绘了Meta未来的蓝图。这场访谈&#xff0c;不仅是大会的热身&#xff0c;更是对科技未来的一次深刻洞察。 人工智能 - Ai工具集 - 未来办公人的智能办公生活导航网 扎克伯格的未…

nacos适配人大金仓的数据库

前言 在微服务架构中&#xff0c;服务发现和配置管理是关键组件。Nacos作为一个动态服务发现和配置管理平台&#xff0c;支持多种数据库作为其后端存储。本文将探讨如何在Nacos中适配人大金仓数据库&#xff0c;以及在此过程中的最佳实践。 Nacos简介 Nacos&#xff08;Nami…

二分查找算法(1) _二分查找_模板

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 二分查找算法(1) _二分查找模板 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 1. 二…

Redis——持久化策略

Redis持久化 Redis的读写操作都是在内存上&#xff0c;所以Redis性能高。 但是当重启的时候&#xff0c;或者因为特殊情况导致Redis崩了&#xff0c;就可能导致数据的丢失。 所以Redis采取了持久化的机制&#xff0c;重启的时候利用之间持久化的文件实现数据的恢复。 Redis提…

[Matplotlib教程] 02 折线图、柱状图、散点图教程

基于MFCC和CNN的语音情感识别 2 折线图、柱状图、散点图2.1 折线图2.1.1 简单折线图2.1.1 线形和Markevery2.1.2 带误差棒的折线图2.1.3 区间填充和透明度 2.2 柱状图2.2.1 分组柱状图2.2.2 堆叠柱状图2.2.3 横向柱状图 2.3 散点图 我们的网站是 菜码编程&#xff0c;我们的q群…

django项目添加测试数据的三种方式

文章目录 自定义终端命令Faker添加模拟数据基于终端脚本来完成数据的添加编写python脚本编写shell脚本执行脚本需要权限使用shell命令来完成测试数据的添加 添加测试数据在工作中一共有三种方式&#xff1a; 可以根据django的manage.py指令进行[自定义终端命令]可以采用第三方…

2024华为杯数学建模研赛F题建模代码思路文章研究生数学建模

截止2024.8.21 12点 已更新F全部小问的建模和问题一的代码 #### https://docs.qq.com/doc/DVVBUREF2SmFhRUl3F题: 问题1&#xff1a;卫星轨道根数与运动学关系的数学模型 从卫星的轨道根数计算出它在特定时刻的三维位置和速度。轨道根数包括&#xff1a; 1.计算卫星的轨道半径…

Android Studio开发发布教程

本文讲解Android Studio如何发布APP。 在Android Studiobuild菜单栏下点击Generate Singed Bundle/APK…打开对话框。 选择APK点击Next 点击Create New...进行创建

【赵渝强老师】K8s的DaemonSets控制器

DaemonSet控制器相当于在节点上启动了一个守护进程。通过使用DaemonSet可以确保一个Pod的副本运行在 Node节点上。如果有新的Node节点加入集群&#xff0c;DaemonSet也会自动给新加入的节点增加一个Pod的副本&#xff1b;反之&#xff0c;当有Node节点从集群中移除时&#xff0…

KMP整理+个人推导+快速上手理解

整理了一下KMP的写法&#xff1a; 这个是我自己写的&#xff08;个人推导&#xff0c;可能在时间复杂度上表现较弱&#xff0c;但是非常帮助初学者进行理解&#xff01;&#xff09; 下面是代码&#xff0c; ne 是next数组。我这个next数组表示的是&#xff1a; ne[i] : 当s…

Spring Boot框架在高校心理辅导中的实践

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…