SpringBoot接口传递自定义参数,参数解析器

news2024/9/24 18:22:37

Hi I’m Shendi



SpringBoot接口传递自定义参数,参数解析器


简介

我的需求:编写了一个日志微服务,使用方式是 创建日志对象 - 日志流程 - 完成日志对象,这样的方式使用时就需要在每个接口都去创建和完成一下,多出了一点代码。

在 SpringBoot 中,我们接收接口的参数都是直接写在函数参数上,例如传递了一个name

@GetMapping("/test")
public String test(String name) {
	return name;
}

于是就想到能不能像上面这种方式将创建和完成封装起来,就开始寻找解决方案。

之前一直使用的是过滤器,但我的需求过滤器是没有办法实现的,过滤器可以给请求注入字符串,但不能注入对象

例如 User 类,想要的效果如下

@GetMapping("/test")
public String test(User user) {
	return user.toString();
}

后面学了下拦截器,发现拦截器也不行…


后面发现可以使用addArgumentResolvers来实现接口增加参数,自定义参数解析器



编写实现类

可以继承以下两个接口

  • WebArgumentResolver
  • HandlerMethodArgumentResolver

这两个接口都是用来处理控制器方法参数的接口。不同之处在于:

  1. HandlerMethodArgumentResolver是在Spring 3.1之后引入的,用于处理注解控制器方法参数。它是一个更加灵活、更加强大的解决方案,可以处理更多的操作,例如类型转换、注入依赖、权限验证等等。它可以用于处理@RequestParam、@PathVariable、@RequestBody、@RequestHeader等注解。
  2. WebArgumentResolver是在Spring 3.0和3.1版本中都有,但在3.1版本中已经被HandlerMethodArgumentResolver所取代。它主要用于处理旧版的控制器方法参数,例如Servlet API中的HttpServletRequest和HttpServletResponse对象。但是它缺乏HandlerMethodArgumentResolver的灵活性,不能处理更为复杂的场景。

对于新项目而言,应该优先使用HandlerMethodArgumentResolver,可以获得更加灵活、强大、可扩展的参数处理能力。


本文就使用 HandlerMethodArgumentResolver 来实现给所有接口注入参数


实现HandlerMethodArgumentResolver接口,需要实现两个函数

public class TestResolve implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

}

supportsParameter方法用于判断参数是否符合特定的类型,符合则执行resolveArgument

而resolveArgument方法则用于将从请求中获取的参数值转换为特定的参数类型,从而将其作为参数传递给方法。(返回什么对象那么接口中使用的就是什么对象,所以需要先判断对象类型再做操作,类型不同则报错)


在配置类注册

编写一个类实现 WebMvcConfigurer,这个在使用拦截器时也是用这个配置

WebMvcConfigurer是一个Spring框架中的配置接口,用于配置Spring MVC的默认行为和定制化处理程序。它定义了多个方法,包括添加资源处理器、拦截器和视图控制器等。


import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import shendi.resolve.TestResolve;

@Configuration
public class WebConfig implements WebMvcConfigurer {
	
	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
		resolvers.add(new TestResolve());
	}
	
}


测试使用

给Resolver类改一下,输出类型

public class TestResolve implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		System.out.println("supportsParameter:" + parameter.getParameterType());
		return true;
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		System.out.println(parameter.getParameterType());
		return null;
	}

}

可以看到 supportsParameter 返回 true,那么就会执行 resolveArgument

随便写个接口,函数接收两个参数(类型需要是当前项目的类,不然无效或者报错)

例如测试接口如下

public static class User {
    public String account;
    public String pwd;
    public String name;
}

@GetMapping("/")
    public String get(String test, User user) {
    System.out.println("接口执行");
    return "test";
}

函数有两个参数,一个String一个User,运行,请求接口,控制台输出如下

在这里插入图片描述


supportsParameter 返回值改为 false,测试结果如下

在这里插入图片描述

可以很明显的看到区别。



参数注入

根据上面的部分,已经实现了参数的注入了,只不过注入的是null

我们可以在 supportsParameter 判断是否是我们需要注入的类,是则返回 true,否则false

@Override
public boolean supportsParameter(MethodParameter parameter) {
    // 判断相等可以直接用equals或者==,不过isAssignableFrom是本地(native)函数,可以判断是否有继承关系
    return parameter.getParameterType().isAssignableFrom(User.class);
}

然后在 resolveArgument 创建实例返回

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
    NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

    // 如果当前有多个类支持的话,就需要用if判断是哪个类,没有则可直接创建对象返回
    if (parameter.getParameterType().isAssignableFrom(User.class)) {
        User user = new User();
        user.account = "shendi";
        return user;
    }

    return null;
}

这样,可以在接口直接使用 user 对象了

@GetMapping("/")
public String get(String test, User user) {
    System.out.println("接口执行: " + user.account);
    return "test";
}

在这里插入图片描述



配合过滤器实现我的需求

在这里再说下我的需求

我的需求:编写了一个日志微服务,使用方式是 创建日志对象 - 日志流程 - 完成日志对象,这样的方式使用时就需要在每个接口都去创建和完成一下,多出了一点代码。



根据上面那部分,已经可以给接口注入参数了,因为我的需求是日志使用,在过滤器中也需要使用,所以配合过滤器

我的理解,过滤器 - 接口,接口中解析参数时才用参数解析器,于是直接将对象放入请求的attribute,然后在解析器拿到返回就可以了

代码如下

@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws IOException, ServletException {
    OLog olog = null;
    try {
        String id = ReqUtil.getUserIdStr(req);
        if (id == null) {
            olog = new OLog("接口", uri);
        } else {
            olog = new OLog("接口", uri, Integer.parseInt(id));
        }

        req.setAttribute("olog", olog);

        chain.doFilter(req, resp);

        olog.finish();
    } catch (Exception e) {
        e.printStackTrace();
        if (olog != null) olog.finish(OLog.RESULT_NOOK);
    }
}

public class ArgumentResolve implements HandlerMethodArgumentResolver {

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.getParameterType().isAssignableFrom(OLog.class);
	}

	@Override
	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
		
		// 如果当前有多个类支持的话,就需要判断是哪个类
		if (parameter.getParameterType().isAssignableFrom(OLog.class)) {
			return webRequest.getAttribute("olog", NativeWebRequest.SCOPE_REQUEST);
		}
		
		return null;
	}

}



END

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

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

相关文章

查看 AndroidManifest.xml 文件内容,解决全是二进制代码问题

想查看打包后apk的AndroidManifest.xml文件内容&#xff0c;之前都是将后缀apk改为zip&#xff0c;直接解压查看&#xff0c;有时会遇到都是二进制代码&#xff0c;给出集中查看明文的方法&#xff1a; 方法一、通过android studio自带的Analyze apk 功能 通过 studio Build …

9.7 字符串的指针和指向字符串的指针变量

9.7 字符串的指针和指向字符串的指针变量 一.字符串表示形式二.字符串指针做函数参数1.数组名做函数参数2.数组指针做函数参数 三.字符指针变量与字符数组&#xff08;1&#xff09;字符数组是由若干个元素组成&#xff0c;每个元素中存放一个字符。&#xff08;2&#xff09;赋…

优化配置Little Snitch for Mac的规则和设置

Little Snitch for Mac是一款专业的macOS防火墙软件&#xff0c;它可以帮助你控制应用程序是否访问网络或者磁盘&#xff0c;并对系统不可信的进程和信息进行监控。如果你想保护你的Mac的网络安全&#xff0c;那么你需要了解如何配置和优化Little Snitch for Mac的规则和设置。…

证件照换底色,快试试这3种方法,方便还快捷

由于我们不论是在生活还是学习中&#xff0c;有时候总会要上传一些证件照&#xff0c;而当你手上有证件照准备上传时&#xff0c;发现底色不对&#xff0c;是不是很抓狂&#xff0c;电子证件照片换底色怎么弄&#xff1f;很多小伙伴还在因为证件照底色不对而重新拍&#xff1f;…

PureComponent和React.memo()区别

文章目录 前言一、区别二、用法 前言 本篇文章主要讲解了&#xff0c;PureComponent和React.memo()区别及用法。 一、区别 PureComponent 和 React.memo() 都是 React 中优化组件性能的方式。 PureComponent 是一个类组件&#xff0c;而 React.memo() 是一个高阶函数。 Reac…

什么蓝牙耳机适合学生党?学生党蓝牙耳机性价比排行

现如今&#xff0c;市场上有各种各样的品牌和蓝牙耳机&#xff0c;让人在选择时不免眼花缭乱。作为学生党&#xff0c;在选择一样东西的时候&#xff0c;性价比无疑会成为其选择的重要参考因素。下面&#xff0c;我来给大家分享几款适合学生党的高性价比蓝牙耳机&#xff0c;一…

SpringBoot拦截器的使用

Hi I’m Shendi SpringBoot拦截器的使用 简介 最近要实现一个全局对象的传递&#xff0c;在接口中直接通过增加函数参数来直接使用的这种方式 之前一直使用的是过滤器&#xff0c;但这种需求过滤器是没有办法实现的&#xff0c;过滤器可以给请求注入字符串&#xff0c;但不能…

【Spring】Spring的数据库开发

目录 1.Spring JDBC1.1 Spring JdbcTemplate的解析1.2 Spring JDBC的配置 2 Spring JdbcTemplate的常用方法2.1 execute()——执行SQL语句2.2 update()——更新数据2.3 query()——查询数据 1.Spring JDBC 1.1 Spring JdbcTemplate的解析 针对数据库的操作&#xff0c;Spring…

FreeRTOS - 二值信号量

一.信号量定义 信号量&#xff08;semaphore&#xff09;&#xff0c;多任务环境下使用的一种设施&#xff0c;负责协调多个任务&#xff0c;以保证任务能够正确&#xff0c;合理的使用公共资源。 二.二值信号量应用函数 函数原型#include “FreeRTOS.h”#include “semphr.h”…

我国纯电动汽车行业开始从“政策导向”向“消费导向”转变 未来机遇挑战并存

1、纯电动汽车概念及其优缺点情况 新能源汽车以能源供给方式主要可以分为纯电动汽车、混合动力汽车以及燃料电池汽车。其中&#xff0c;纯电动汽车则是指完全由可充电电池&#xff08;如铅酸电池、镍镉电池、镍氢电池或锂离子电池&#xff09;提供动力源&#xff0c;用电机驱动…

华纳云:Pycharm无法正常安装第三方库怎么解决?

这篇文章主要介绍“Pycharm无法正常安装第三方库怎么解决”的相关知识&#xff0c;小编通过实际案例向大家展示操作过程&#xff0c;操作方法简单快捷&#xff0c;实用性强&#xff0c;希望这篇“Pycharm无法正常安装第三方库怎么解决”文章能帮助大家解决问题。 1.首先检查自…

MongoDB常用语句(CURD)

文章目录 一、数据库操作二、集合操作三、文档操作3.1 插入文档3.2 查询文档3.3 更新文档3.4 删除文档 四、安全认证4.1 创建管理员账号4.2 创建应用数据库用户4.3 启动和连接 (校验方式) 提示&#xff1a;以下是本篇文章正文内容&#xff0c;MongoDB 系列学习将会持续更新 一…

【达摩院OpenVI】视频目标渐进式Transformer跟踪器ProContEXT

论文&代码 论文链接&#xff1a;[arxiv]代码&应用&#xff1a; 开源代码&#xff1a;[github code]开源应用&#xff1a;[modelscope] 背景介绍 视频目标跟踪&#xff08;Video Object Tracking, VOT&#xff09;任务以一段视频和第一帧中待跟踪目标的位置信息&…

为什么使用了索引,查询还是慢?

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;为什么使用了索引&#xff0c;查询还是慢&#xff1f; ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&…

一、适配各大数据库之前言

一、适配各大数据库之前言 简介 本系列主要记录基于【用户权限服务】(一个SpringBoot服务的名称,不重要,只要是web项目都可以,为了方便描述,以下就简称 “用户中心”),适配各大数据库的过程,其中包括SQL Server、Oracle、PostgreSql、达梦、金仓、MYSQL等等,其次还记…

Docker容器---docker-compose

docker容器---compose容器集群的快速编排 一、Docker-compose简介二、yml文件格式及编写注意事项1、yml文件格式2、yml文件格式注意事项 三、编写docker-compose&#xff08; nginxtomcat 实例&#xff09;1、dockerfile撰写 nginx 镜像2、dockerfile撰写 tomcat 镜像3、将所需…

基于html+css的图片展示32

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

java 7大设计原则

一、设计模式七大原则 设计模式的目的 代码重用性 (即&#xff1a;相同功能的代码&#xff0c;不用多次编写)可读性 (即&#xff1a;编程规范性, 便于其他程序员的阅读和理解)可扩展性 (即&#xff1a;当需要增加新的功能时&#xff0c;非常的方便&#xff0c;称为可维护)可靠…

关于今年五一调休。。

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,YOLO,活动领域博主爱笑的男孩。擅长深度学习,YOLO,活动,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typecollect个人…

Spring5学习总结(三)JdbcTemplate实现数据库增删改查操作JdbcTemplate实现批量增删改操作

Spring5学习总结&#xff08;三&#xff09;JdbcTemplate实现数据库增删改查操作/JdbcTemplate实现批量增删改操作 一、JdbcTemplate概述 什么是 JdbcTemplate&#xff1f; JdbcTemplate是Spring 框架对 JDBC 进行的封装&#xff0c;使用它可以更方便实现对数据库的操作。 二…