There is a lot of code on the web that is generic CVS. Believe me, if you read this article carefully, you will be able to fully grasp this point. This article is not suitable for CVS directly, be sure to understand it first.

The PHP interface is compatible with both POST JSON and form forms, and even form-data is compatible with the PHP interface. Because PHP requests are written with lax receiver code. See more here.

In Java, an interface supports only one Content-Type. Json uses @requestBody, form uses @requestParam or no writing, and form-data uses MultipartFile.

Compatible versions

If you want to incorporate all three in one interface, the clumsy approach is to get HttpServletRequest and then write your own method parsing. Similar to the following:

private Map<String, Object> getParams(HttpServletRequest request) {

    String contentType = request.getContentType();
    if (contentType.contains("application/json")) {
        // json parsing...
        return null;
    } else if (contentType.contains("application/x-www-form-urlencoded")) {
        // form parsing...
        return null;
    } else if (contentType.contains("multipart")) {
        // File stream parsing
        return null;
    } else {
         throw new BizException("Unsupported Content-Type"); }}Copy the code

But there’s a downside to this

  1. The code is ugly, and the parsing code is stinky and long
  2. You can only return the fixed map or reassemble the parameter classes yourself
  3. Can’t use@ValidChecking parameters, like I have to check dozens of parameters is a disaster

Elegant version

There are forms and JSON compatible versions on the Internet, but not form-data compatible versions. Here I add something.

1. Custom annotations

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GamePHP {
}
Copy the code

2. Custom annotation parsing

public class GamePHPMethodProcessor implements HandlerMethodArgumentResolver {

    private GameFormMethodArgumentResolver formResolver;
    private GameJsonMethodArgumentResolver jsonResolver;

    public GamePHPMethodProcessor(a) { List<HttpMessageConverter<? >> messageConverters =new ArrayList<>();
        PHPMessageConverter PHPMessageConverter = new PHPMessageConverter();
        messageConverters.add(PHPMessageConverter);

        jsonResolver = new GameJsonMethodArgumentResolver(messageConverters);
        formResolver = new GameFormMethodArgumentResolver();
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        GamePHP ann = parameter.getParameterAnnotation(GamePHP.class);
        return(ann ! =null);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        ServletRequest servletRequest = nativeWebRequest.getNativeRequest(ServletRequest.class);
        String contentType = servletRequest.getContentType();
        if (contentType == null) {
            throw new IllegalArgumentException("ContentType not supported");
        }

        if (contentType.contains("application/json")) {
            return jsonResolver.resolveArgument(methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory);
        }

        if (contentType.contains("application/x-www-form-urlencoded")) {
            return formResolver.resolveArgument(methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory);
        }

        if (contentType.contains("multipart")) {
            return formResolver.resolveArgument(methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory);
        }

        throw new IllegalArgumentException("ContentType not supported"); }}Copy the code

3. Add it to Spring Configuration


    @Bean
    public MyMvcConfigurer mvcConfigurer(a) {
        return new MyMvcConfigurer();
    }

    public static class MyMvcConfigurer implements WebMvcConfigurer {
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
            resolvers.add(newGamePHPMethodProcessor()); }}Copy the code

4. Special processing of form-data

The introduction of the jar package

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
Copy the code

New Parse bean

@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver(a){
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setDefaultEncoding("UTF-8");
    resolver.setResolveLazily(true);The resolveLazily property is enabled to defer file parsing in order to catch file size exceptions in UploadAction
    resolver.setMaxInMemorySize(40960);
    resolver.setMaxUploadSize(50*1024*1024);// Upload file size 50M 50 x 1024 x 1024
    return resolver;
}
Copy the code

Special instructions, GameJsonMethodArgumentResolver and GameFormMethodArgumentResolver is our custom json and analytical form, if you don’t have a custom, Using spring default ServletModelAttributeMethodProcessor and RequestResponseBodyMethodProcessor can also.

Simply change the @RequestParam annotation to @gamephp and the interface is compatible with all three Content-Types at once.

When Spring starts, MyMvcConfigurer calls addArgumentResolvers to inject GamePHPMethodProcessor. The supportsParameter method determines whether to use the resolver. If true, the resolveArgument method is used.

At this point we can conclude that PHP is the most garbage language in the world. Writing code, maintaining a crematorium.