Spring Boot 2.x实战40 - Spring Web MVC 12 - Web MVC配置(控制器方法参数和返回值处理设置-使用HandlerMethodArgumentResolver)

本文介绍了如何在Spring Boot 2.x的Web MVC中配置和处理控制器方法的参数和返回值。通过实现HandlerMethodArgumentResolver接口定制方法参数,以及通过HandlerMethodReturnValueHandler接口处理返回值。示例展示了如何将新建的Bean替换为注入的Bean,以控制参数处理。文章还提及了新书《从企业级开发到云原生微服务:Spring Boot 实战》,涵盖了Spring Boot的广泛知识。
摘要由CSDN通过智能技术生成
3.6 方法参数和返回值处理设置

在控制器方法里,我们可以使用@RequestBodyRequestEntity获得请求体里的数据,使用@ResponseBodyResponseEntity对返回体进行处理。

在Spring MVC中可以通过实现HandlerMethodArgumentResolver接口来实现对控制器方法参数进行处理,通过实现HandlerMethodReturnValueHandler可以对方法的返回值进行处理。

若同时需要对请求参数和返回返回体进行处理的话,则继承AbstractMessageConverterMethodProcessor抽象类,它分别实现了HandlerMethodArgumentResolverHandlerMethodReturnValueHandler

Spring MVC的@RequestBody@ResponseBody就是通过RequestResponseBodyMethodProcessor对请求体和返回体进行处理的;而RequestEntityResponseEntity是通过HttpEntityMethodProcessor起效的。更多如:

  • @RequestParamRequestParamMethodArgumentResolver
  • @PathVariablePathVariableMethodArgumentResolver
  • @RequestPartRequestPartMethodArgumentResolver
  • @RequestHeaderRequestHeaderMethodArgumentResolver
  • ServletRequestServletRequestMethodArgumentResolver
  • ServletResponseServletResponseMethodArgumentResolver

RequestResponseBodyMethodProcessor的构造为:

public RequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters,
      @Nullable List<Object> requestResponseBodyAdvice) {}

这也意味着RequestResponseBodyMethodProcessor负责用HttpMessageConverter将请求体中外部数据转换为Java对象并将Java对象转换成返回体中的外部数据(让@RequestBody@ResponseBody起效),同时请求体数据的先处理RequestBodyAdvice以及返回体的后处理ResponseBodyAdvice也是由他处理的。

3.6.1 示例1

还记得我们在“方法参数”一节:

@GetMapping("/methodArguments")
public void methodArguments(WebRequest request,
                              NativeWebRequest nativeWebRequest,
                              ServletRequest servletRequest,
                              ServletResponse servletResponse,
                              HttpSession httpSession,
                              Locale locale,
                              TimeZone timeZone,
                              ZoneId zoneId,
                              DemoService demoService) throws Exception{
    System.out.println(request);
    System.out.println(nativeWebRequest);
    System.out.println(servletRequest);
    System.out.println(servletResponse);
    System.out.println(httpSession);
    System.out.println(locale);
    System.out.println(timeZone);
    System.out.println(zoneId);
    System.out.println(demoService.sayHello());
}

此处的DemoService demoService不是注入的而是新建的,如果我们想将此效果变成一个注入而非新建,那我们要做的肯定是定制方法参数,即实现HandlerMethodArgumentResolver接口去定制。

我们再定义个控制器方法来检验:

@Controller
@RequestMapping("/demo")
public class DemoController {

    private DemoService demoService;

    public DemoController(DemoService demoService) {
        this.demoService = demoService;
    }


    @GetMapping("/bean-argument")
    public void argument(DemoService demoService){
        System.out.println("this.demoService和方法参数demoService是否相等:" + this.demoService.equals(demoService));
    }



}

此时我们一个注入的demoService,一个新建的DemoService肯定是不相等的,访问http://localhost:8080/demo/bean-argument,控制台显示:
在这里插入图片描述
下面我们通过实现HandlerMethodArgumentResolver接口来定制:

public class BeanArgumentResolver implements HandlerMethodArgumentResolver, BeanFactoryAware {
    private BeanFactory beanFactory;
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory; //1
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(DemoService.class); //2
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return beanFactory.getBean(DemoService.class); //3
    }
}
  1. 通过实现BeanFactoryAware可获得BeanFactory
  2. 当前参数只支持DemoService类;
  3. 获得支持类型的Bean;

本例的演示并不通用,当然我们很容易将它改造通用,大家可以自己尝试。

我们通过WebMvcConfigurer接口的addArgumentResolvers方法来注册:

@Bean
HandlerMethodArgumentResolver beanArgumentResolver(){
    return new BeanArgumentResolver();
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    resolvers.add(beanArgumentResolver());
    resolvers.add(requestResponsePersonMethodProcessor());
}

此时我们再访问:http://localhost:8080/demo/bean-argument,此时控制台显示:
在这里插入图片描述

新书推荐:

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html
在这里插入图片描述

主要包含目录有:

第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和屁股里(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值