SpringBoot RequestMapping

RequestMapping#produces,consumes

    @RequestMapping(value = "/hi",
            consumes = "application/*;charset=UTF-8",
            produces = "application/json;charset=UTF-8")
    public String hi(@RequestParam(required = false) String msg) {
        return "Hello -~" + msg;
    }
  • produces(输出)

    • 标注后影响最终传输的ContentType的类型
  • consumes(输入)

    • 过滤请求头ContentType,限定允许的ContentType的类型

若编码不同则返回415

内容协商-反序列化

  • Controller
    @PostMapping(value = "/props",
            consumes = "text/properties;charset=UTF-8",
            produces = "text/properties;charset=UTF-8")
    public Properties prop(@RequestBody Properties prop) {
        return prop;
    }
  • 工具类
package com.example.springbootrest.utils;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractGenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Properties;

public class PropertiesHttpMsgConvert extends AbstractGenericHttpMessageConverter<Properties> {

    public PropertiesHttpMsgConvert() {
        //设置支持的MediaType
        super(new MediaType("text", "properties"));
    }

    @Override
    protected void writeInternal(Properties properties, Type type, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {

        //获取请求头的ContentType的编码
        HttpHeaders httpHeaders = httpOutputMessage.getHeaders();
        MediaType mediaType = httpHeaders.getContentType();
        Charset charset = null == mediaType.getCharset() ? Charset.forName("UTF-8") : mediaType.getCharset();

        OutputStream outputStream = httpOutputMessage.getBody();
        Writer writer = new OutputStreamWriter(outputStream, charset);

        //properties写入到字符输出流
        properties.store(writer,"From PropertiesHttpMsgConvert#writeInternal");

    }

    @Override
    protected Properties readInternal(Class<? extends Properties> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {


        //获取请求头的ContentType的编码
        HttpHeaders httpHeaders = httpInputMessage.getHeaders();
        MediaType mediaType = httpHeaders.getContentType();
        Charset charset = null == mediaType.getCharset() ? Charset.forName("UTF-8") : mediaType.getCharset();

        // 获取字符流
        InputStream inputStream = httpInputMessage.getBody();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset);

        Properties properties = new Properties();
        properties.load(inputStreamReader);
        return properties;
    }

    @Override
    public Properties read(Type type, Class<?> aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {
        return readInternal(null, httpInputMessage);
    }
}

  • 配置类
package com.example.springbootrest.config;

import com.example.springbootrest.utils.PropertiesHttpMsgConvert;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class RestWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    // 加在第一位,而非最后
        converters.set(0,new PropertiesHttpMsgConvert());
    }
}

  • 实体类
public class User {
    private String id;
    private  String name;

    // get/set 省略
}
  • test


自定义方法参数处理

不依赖@RequestBody,实现传入Properties类型,并解析

  • controller
    @PostMapping(value = "/propwithout",
            consumes = "text/properties;charset=UTF-8")
    public Properties propWithout(Properties prop) {
        return prop;
    }
  • 工具类
package com.example.springbootrest.utils;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Properties;

public class PropertiesHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    // 是否解析
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return Properties.class.equals(methodParameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
       // NativeWebRequest-->HttpServletRequest
        ServletWebRequest servletWebRequest = (ServletWebRequest) nativeWebRequest;
        HttpServletRequest httpServletRequest = servletWebRequest.getRequest();


        // 获取到Charset
        String contentType = httpServletRequest.getHeader("Content-Type");
        MediaType mediaType = MediaType.parseMediaType(contentType);
        Charset charset = mediaType.getCharset();
        charset = null == charset ? Charset.forName("UTF-8") : charset;

        //从httpServletRequest中得到InputStreamReader
        InputStream inputStream = httpServletRequest.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset);


        // 加载字符输入流weiProperties
        Properties properties = new Properties();
        properties.load(inputStreamReader);
        return properties;
    }
}

  • 配置类
@Configuration
public class RestWebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

    //    由于built-in在自定义之前,
    @PostConstruct
    public void init() {
        // 获取所有的ArgumentResolvers
        List<HandlerMethodArgumentResolver> resolvers = requestMappingHandlerAdapter.getArgumentResolvers();
        List<HandlerMethodArgumentResolver> curResolvers = new ArrayList<>(resolvers.size() + 1);
        // 放在首位
        curResolvers.add(new PropertiesHandlerMethodArgumentResolver());
        curResolvers.addAll(resolvers);
        // 重新设置Resolver集合
        requestMappingHandlerAdapter.setArgumentResolvers(curResolvers);

    }

    /**
     * Add resolvers to support custom controller method argument types.
     * <p>This does not override the built-in support for resolving handler
     * method arguments. To customize the built-in support for argument
     * resolution, configure {@link RequestMappingHandlerAdapter} directly.
     *
     * @param resolvers initially an empty list
     */
     *@Override
     *public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
     *}
     */
}

自定义方法返回处理

不依赖于@ResponseBody

  • controller
//@RestController
@Controller
@RequestMapping("/rest")
public class HelloController {
    @PostMapping(value = "/propwithout",
            consumes = "text/properties;charset=UTF-8")
    public Properties propWithout(Properties prop) {
        return prop;
    }
}
  • 工具类
package com.example.springbootrest.utils;

import org.springframework.core.MethodParameter;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Properties;

public class PropertiesHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
    @Override
    public boolean supportsReturnType(MethodParameter methodParameter) {
        return Properties.class.equals(methodParameter.getMethod().getReturnType());
    }

    @Override
    public void handleReturnValue(Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {

        Properties properties = (Properties) o;

        // NativeWebRequest-->HttpServletRequest
        ServletWebRequest servletWebRequest = (ServletWebRequest) nativeWebRequest;
        HttpServletRequest httpServletRequest = servletWebRequest.getRequest();


        // 获取到MediaType
        String contentType = httpServletRequest.getHeader("Content-Type");
        MediaType mediaType = MediaType.parseMediaType(contentType);


        HttpServletResponse httpServletResponse = servletWebRequest.getNativeResponse(HttpServletResponse.class);
        HttpOutputMessage httpOutputMessage = new ServletServerHttpResponse(httpServletResponse);

        PropertiesHttpMsgConvert propertiesHttpMsgConvert = new PropertiesHttpMsgConvert();

        propertiesHttpMsgConvert.write(properties, mediaType, httpOutputMessage);

        // 通知Web WVC当前请求已经处理完毕
        modelAndViewContainer.setRequestHandled(true);
    }
}

  • 配置类
@Configuration
public class RestWebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    @PostConstruct
    public void init() {
        List<HandlerMethodReturnValueHandler> handlers = requestMappingHandlerAdapter.getReturnValueHandlers();

        List<HandlerMethodReturnValueHandler> curHandlers = new ArrayList<>(handlers.size()+1);
        curHandlers.add(new PropertiesHandlerMethodReturnValueHandler());
        curHandlers.addAll(handlers);
        requestMappingHandlerAdapter.setReturnValueHandlers(curHandlers);

    }
}

源码已上传至git:https://github.com/zhaimiya/springboot
菜鸟一小小只,欢迎批评指导

posted @ 2020-04-21 14:56  VVII  阅读(774)  评论(0)    收藏  举报