• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:SpringBoot自定义控制层参数解析

java 搞代码 4年前 (2022-01-28) 55次浏览 已收录 0个评论
文章目录[隐藏]

一、背景

在Spring的Controller中,咱们通过@RequestParam@RequestBody就能够将申请中的参数映射到管制层具体的参数中,那么这个是怎么实现的呢?如果我当初管制层中的某个参数的值是从Redis中来,那么应该如何实现呢?

二、参数是如何解析的

从上图中能够咱们的参数最终会通过HandlerMethodArgumentResolver来解析,那么晓得了这个后,咱们就能够实现本人的参数解析了。

三、需要

如果咱们管制层办法的参数中存在@Redis标注,那么此参数的值应该从redis中获取,不必从申请参数中获取。

从上图中可知@Redis(key = "redisKey") String redisValue这个参数就须要从Redis中获取。

四、实现

此处咱们不会真的从Redis中获取值,模仿从Redis中获取值即可。

1、编写一个Redis注解

<code class="java">@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Redis {
    
    /**
     * redis中的Key
     */
    String key();
    
}

在管制层的办法上,被此处注解标注的办法参数,都从Redis中获取,都走咱们本人定义的参数解析器。

2、编写参数解析类

<code class="java">package com.huan.study.argument.resolver;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
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;

import javax.servlet.http.HttpServletRequest;
import java.util.Random;

/**
 * 从redis中获取值放入到参数中
 *
 */
public class RedisMethodArgumentResolver implements HandlerMethodArgumentResolver {
    
    private static final Logger log = LoggerFactory.getLogger(RedisMethodArgumentResolver.class);
    
    /**
     * 解决参数上存在@Redis注解的
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Redis.class);
    }
    
    /**
     * 解析参数 
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        // 获取http request
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        log.info("以后申请的门路:[{}]", request.getRequestURI());
        // 获取到这个注解
        Redis redis = parameter.getParameterAnnotation(Redis.class);
        // 获取在redis中的key
        String redisKey = redis.key();
        // 模仿从redis中获取值
        String redisValue = "从redis中获取的值:" + new Random().nextInt(100);
        log.info("从redis中获取到的值为:[{}]", redisValue);
        // 返回值
        return redisValue;
    }
}

1、通过supportsParameter办法判断咱们应该解决哪些参数,此处解决的是参数上存在@Redis注解的。
2、通过resolveArgument办法,获取到参数的具体的值。比方从Redis中获取,代码中没有真的从Redis中获取,只是模仿从Redis中获取。

3、配置到Spring的上下文中

此处咱们最好将咱们本人的参数解析器搁置在第一位,否则可能会有问题。下方提供了2种形式,第一种形式无奈达到咱们的需要、咱们采纳第二种形式来实现

1、通过WebMvcConfigurer实现

<code class="java">@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    /**
     * 这个中央加载的程序是在默认的HandlerMethodArgumentResolver之后的
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new RedisMethodArgumentResolver());
    }
}

从上图可知,咱们本人的参数解析器不是在第一位,这样可能达不到咱们想要的成果,此处不思考这种形式。

2、通过BeanPostProcessor来实现

BeanPostProcessor能够在一个Bean齐全初始化之后来执行一些操作,此处咱们通过这种形式,将咱们本人的参数解析器搁置在第一位。

<code class="java">@Component
static class CustomHandlerMethodArgumentResolverConfig implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof RequestMappingHandlerAdapter) {
            final RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
            final List<HandlerMethodArgumentResolver> argumentResolvers = Optional.ofNullable(adapter.getArgumentResolvers())
                    .orElseGet(ArrayList::new);
            final ArrayList<HandlerMethodArgumentResolver> handlerMethodArgumentResolvers = new ArrayList<>(argumentResolvers);
            // 将咱们本人的参数解析器搁置到第一位
            handlerMethodArgumentResolvers.add(0, new RedisMethodArgumentResolver());
            adapter.setArgumentResolvers(Collections.unmodifiableList(handlerMethodArgumentResolvers));
            return adapter;
        }
        return bean;
    }
}

从上图可知,咱们本人的参数解析器在第一位,这样就达到咱们想要的成果,此处应用这种形式。

4、编写一个简略的管制层

<code class="java">/**
 * @author huan.fu 2021/12/7 - 下午3:36
 */
@RestController
public class RedisArgumentController {
    
    private static final Logger log = LoggerFactory.getLogger(RedisArgumentController.class);
    
    @GetMapping("redisArgumentResolver")
    public void redisArgumentResolver(@RequestParam("hello") String hello,
                                      @Redis(key = "redisKey") String redisValue) {
        log.info("管制层获取到的参数值: hello:[{}],redisValue:[{}]", hello, redisValue);
    }
}

该管制层比较简单,对外提供来一个简略的apihttp://localhost:8080/redisArgumentResolver?hello=123。该api存在2个参数helloredisValue,其中hello参数的值是从申请参数中获取,redisValue的值是从咱们本人定义的参数
解析器中获取。

五、测试

<code class="curl">curl http://localhost:8080/redisArgumentResolver?hello=123

由上图可知咱们本人定义的参数解析器工作了。

六、残缺代码

残缺代码


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:SpringBoot自定义控制层参数解析

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址