美文网首页SpringFrameworkSpring Boot
springmvc 自定义参数处理器

springmvc 自定义参数处理器

作者: lialzm | 来源:发表于2017-03-22 10:43 被阅读1574次

上一篇介绍了springmvc参数绑定的原理
现在让我们尝试自己定义一个参数转换器

先定义一个比较简单的处理器,在写接口的时候,经常需要对分页参数进行处理,比如下面这样

String offset =request.getParameter("offset");
String size = request.getParameter("pageSize");
//拼装成bean或者直接使用

这样会导致很多重复代码,参数处理器可以很好的解决这个问题
首先先定义一个分页参数的bean

public class Pageable implements Serializable {

    private Integer offset; // 起始行号
    private Integer size; // 每页大小

    public Pageable() {
    }

    public Pageable(Integer offset, Integer size) {
        this.offset = offset;
        this.size = size;
    }
//省略get,set
}

定义参数转换器

public class PageableMethodArgumentResolver implements HandlerMethodArgumentResolver {

    private final String DEFAULT_OFFSET = "0";
    private final String DEFAULT_SIZE = "10";

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

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();
        String offset = request.getParameter("offset");
        String size = request.getParameter("pageSize");
        if (offset.isEmpty()||size.isEmpty()) {
            offset = DEFAULT_OFFSET;
            size = DEFAULT_SIZE;
        }
        return new Pageable(Integer.valueOf(offset), Integer.valueOf(size));
    }
}

最后在配置文件注册该处理器(这是spring4.0以下的注册方式,4.0以上注册方式参考下面的)

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="customArgumentResolvers">
            <list>
                <bean class="com.catfish.PageableMethodArgumentResolver"/>
            </list>
        </property>
        <property name="order" value="-1"/>
    </bean>

下面是定义一个比较复杂的转换器


需求:将json格式的请求在参数中获取值,类似于

json格式的请求在参数中获取值.png

用到的jar包除了spring的还有jsonpath原来解析json

<dependency>
 <groupId>com.jayway.jsonpath</groupId>
 <artifactId>json-path</artifactId>
 <version>2.2.0</version>
 </dependency>

因为是json格式的报文,所有我们只需要模仿@RequestBody注解的处理,查看源码可知@RequestBody注解对应的处理器为RequestResponseBodyMethodProcessor,
对json处理核心方法将json转换为bean
readWithMessageConverters方法,
该方法是由其父类AbstractMessageConverterMethodArgumentResolver实现,对应uml图

uml.png

所以我们只允许继承AbstractMessageConverterMethodArgumentResolver并重写supportsParameter,readWithMessageConverters方法即可实现我们需要的功能

分析结束,现在开始写具体的实现,首先我们需要一个注解用来标注参数,对注解不了解的可以看java注解笔记

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Documented
public @interface JsonRequest {
    String value() default "";
    boolean required() default true;
}

然后写对应的参数转换器,这边只写核心的方法,具体的查看github,地址在文章末尾

protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter param, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
        try {
            inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);
            InputStream inputStream = inputMessage.getBody();
            String json;
            if (inputStream == null) {
                json = threadLocal.get();
            } else {
                json = StreamUtils.copyToString(inputStream, Charset.defaultCharset());
                threadLocal.set(json);
            }
            JsonRequest jsonRequest = param.getParameterAnnotation(JsonRequest.class);
            return JsonPath.read(json, jsonRequest.value());
        } catch (PathNotFoundException ex) {
            return null;
        }
    }

在配置文件添加配置

<mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="com.lialzm.spring.support.JsonRequestMethodArgumentResolver">
                <constructor-arg>
                    <list>
  <!--只是用来防止报错,目前并没有使用到消息转换器-->
  <ref bean="byteArrayHttpMessageConverter"/>
                    </list>
                </constructor-arg>
            </bean>
        </mvc:argument-resolvers>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

添加一个controller

 @RequestMapping("/getUserByJson2")
 @ResponseBody
 public String getUserByJson2(@JsonRequest("$.id") String id, @JsonRequest("$.name") String name) {
        return id + "," + name;
    }

测试发送参数

{
    "id":"1",
    "name":"qqq"
}

返回
"1,qqq"
验证成功
这时将参数id类型改成Long类型发现报错

Request processing failed; nested exception is java.lang.IllegalStateException: argument type mismatch

参数类型不匹配,因为resolveArgument返回的类型和请求的参数类型是相同的,发送的是string类型用Long类型承接自然就报错了,查看AbstractNamedValueMethodArgumentResolver的源码,里面有个binder.convertIfNecessary方法,就是原来处理类型转换的,这个类型转换下一篇再写

源码地址:
https://github.com/lialzmChina/javaeeLearn.git
spring002

相关文章

  • springmvc 自定义参数处理器

    上一篇介绍了springmvc参数绑定的原理现在让我们尝试自己定义一个参数转换器 先定义一个比较简单的处理器,在写...

  • 异常处理器

    springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻...

  • SpringMVC异常处理器

    SpringMVC在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻...

  • springMVC源码分析--HttpMessageConver

    这章我们介绍一下springMVC在获取参数和返回结果值方面的处理。虽然在之前已经分别介绍了参数处理器和返回值处理...

  • SpringMVC之拦截器

    十、拦截器 目录:简述、自定义拦截器、认证用户 1.简述 SpringMVC的处理器拦截器类似于Servlet开发...

  • Java-springmvc注解开发之自定义类型绑定

    自定义参数绑定实现日期类型绑定 注意:需要向处理器适配器中注入自定义的参数绑定组件.因为这里是注解开发,所以向sp...

  • 深入分析 SpringMVC 参数解析器

    前面和大家聊了自定义 SpringMVC 参数解析器,同时我们也分析了几个比较简单的参数解析器,相信大家对于 Sp...

  • springMVC---基础

    什么是springMVC springMVC框架原理 前端控制器、处理器映射器、处理器适配器、试图解析器 spri...

  • SpringMVC架构原理分析

    springmvc框架原理(掌握)前端控制器、处理器映射器、处理器适配器、视图解析器springmvc入门程序目的...

  • 1、springmvc Converter内置转换器

    springmvc 内置的转换器。再进行参数传递时,转换器会你的参数进行处理。如果有个性化的转换需求,可以自定义转...

网友评论

    本文标题:springmvc 自定义参数处理器

    本文链接:https://www.haomeiwen.com/subject/xcxonttx.html