Springboot 之 HandlerMethodArgumentResolver 运用

简介: Springboot 之 HandlerMethodArgumentResolver 运用

介绍

在项目中,如果需要在 Header 中获取请求头,一般使用 RequestHeader 注解。代码案例如下:

@RequestMapping("/normalHeaders")
  public Map<String, Object> normalHeaders(@RequestHeader("user-id")Long userId,
                       @RequestHeader("tenant-id")Long tenantId,
                       @RequestHeader("user-name")String userName){
    Map<String, Object> map = new HashMap<>();
    map.put("userId", userId);
    map.put("tenantId", tenantId);
    map.put("userName", userName);
    return map;
  }

请求curl

curl -X POST \
  http://127.0.0.1:8080/normalHeaders \
  -H 'tenant-id: 12' \
  -H 'user-id: 1' \
  -H 'user-name: buger'

使用 RequestHeader 注解获取请求头,如果获取一两个到不会写很多重复代码,但是如果需要获取很多个请求时,代码会变得重复。

下面介绍一种新的解决方案;不但减少了很多重复的代码,而且使得代码变得跟简洁。

pom.xml 文件引入依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.olive</groupId>
  <artifactId>springmvc-headers</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>springmvc-headers</name>
  <url>http://maven.apache.org</url>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.14</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
</project>

解析请求头,并包装

实现 HandlerMethodArgumentResolver 类;解析请求头,包装成 HeadersWrapperDTO 类

package com.olive.config;
import com.olive.dto.HeadersWrapperDTO;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
public class RequestHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(HeadersWrapperDTO.class);
    }
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
String userId = webRequest.getHeader("user-id");
String tenantId = webRequest.getHeader("tenant-id");
String userName = webRequest.getHeader("user-name");
HeadersWrapperDTO headersWrapperDTO = new HeadersWrapperDTO();
if(StringUtils.hasText(userId)){
            headersWrapperDTO.setUserId(Long.parseLong(userId));
        }
if(StringUtils.hasText(tenantId)){
            headersWrapperDTO.setTenantId(Long.parseLong(tenantId));
        }
        headersWrapperDTO.setUserName(userName);
return headersWrapperDTO;
    }
}

HeadersWrapperDTO POJO类

package com.olive.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class HeadersWrapperDTO implements Serializable {
private Long userId;
private Long tenantId;
private String userName;
}

注册 RequestHandlerMethodArgumentResolver 到 Controller 参数解析器里,即添加自己的参数解析器

package com.olive.config;
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.WebMvcConfigurer;
import java.util.List;
@Configuration
public class MethodArgumentResolverConfig {
@Bean
public WebMvcConfigurer getWebMvcConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
                resolvers.add(new RequestHandlerMethodArgumentResolver());
            }
        };
    }
}

测试

编码 Springboot 启动引导类

package com.olive;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
    }
}

编写测试 Controller

package com.olive.controller;
import java.util.HashMap;
import java.util.Map;
import com.olive.dto.HeadersWrapperDTO;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
  @RequestMapping("/normalHeaders")
  public Map<String, Object> normalHeaders(@RequestHeader("user-id")Long userId,
                       @RequestHeader("tenant-id")Long tenantId,
                       @RequestHeader("user-name")String userName){
    Map<String, Object> map = new HashMap<>();
    map.put("userId", userId);
    map.put("tenantId", tenantId);
    map.put("userName", userName);
    return map;
  }
  @RequestMapping("/wrapperHeaders")
  public Map<String, Object> wrapperHeaders(HeadersWrapperDTO headers){
    Map<String, Object> map = new HashMap<>();
    map.put("userId", headers.getUserId());
    map.put("tenantId", headers.getTenantId());
    map.put("userName", headers.getUserName());
    return map;
  }
}

测试curl

curl -X POST \
  http://127.0.0.1:8080/wrapperHeaders \
  -H 'tenant-id: 12' \
  -H 'user-id: 1' \
  -H 'user-name: buger'

通过 RequestHandlerMethodArgumentResolver 可以对请求头进行解析并封装到 HeadersWrapperDTO 类中,这样减少了在 Controller 使用大量的 RequestHeader 注解获取请求头。

相关文章
|
存储 前端开发 Java
Springboot使用参数解析器HandlerMethodArgumentResolver,解析请求头里的数据
HandlerMethodArgumentResolver 是 Spring MVC 中的一个接口,它允许你自定义方法参数的解析过程。当处理请求时,Spring MVC 需要将请求中的信息映射到控制器方法的参数上,而 HandlerMethodArgumentResolver 允许你在这个过程中进行自定义操作。
690 2
|
数据格式 JSON Java
springboot自定义参数解析HandlerMethodArgumentResolver
自定义解析器需要实现HandlerMethodArgumentResolver接口,HandlerMethodArgumentResolver接口包含两个接口函数: public interface HandlerMethodArgumentResol...
4499 0
|
6月前
|
JavaScript Java 关系型数据库
基于springboot的项目管理系统
本文探讨项目管理系统在现代企业中的应用与实现,分析其研究背景、意义及现状,阐述基于SSM、Java、MySQL和Vue等技术构建系统的关键方法,展现其在提升管理效率、协同水平与风险管控方面的价值。
|
6月前
|
搜索推荐 JavaScript Java
基于springboot的儿童家长教育能力提升学习系统
本系统聚焦儿童家长教育能力提升,针对家庭教育中理念混乱、时间不足、个性化服务缺失等问题,构建科学、系统、个性化的在线学习平台。融合Spring Boot、Vue等先进技术,整合优质教育资源,提供高效便捷的学习路径,助力家长掌握科学育儿方法,促进儿童全面健康发展,推动家庭和谐与社会进步。
|
6月前
|
JavaScript Java 关系型数据库
基于springboot的古树名木保护管理系统
本研究针对古树保护面临的严峻挑战,构建基于Java、Vue、MySQL与Spring Boot技术的信息化管理系统,实现古树资源的动态监测、数据管理与科学保护,推动生态、文化与经济可持续发展。
|
6月前
|
监控 安全 JavaScript
2025基于springboot的校车预定全流程管理系统
针对传统校车管理效率低、信息不透明等问题,本研究设计并实现了一套校车预定全流程管理系统。系统采用Spring Boot、Java、Vue和MySQL等技术,实现校车信息管理、在线预定、实时监控等功能,提升学校管理效率,保障学生出行安全,推动教育信息化发展。
|
6月前
|
人工智能 Java 关系型数据库
基于springboot的画品交流系统
本项目构建基于Java+Vue+SpringBoot+MySQL的画品交流系统,旨在解决传统艺术交易信息不透明、流通受限等问题,融合区块链与AI技术,实现画品展示、交易、鉴赏与社交一体化,推动艺术数字化转型与文化传播。
|
6月前
|
JavaScript Java 关系型数据库
基于springboot的高校运动会系统
本系统基于Spring Boot、Vue与MySQL,实现高校运动会报名、赛程安排及成绩管理的全流程信息化,提升组织效率,杜绝信息错漏与冒名顶替,推动体育赛事智能化发展。