请求接口同时支持表单、json

java请求接口同时支持json、form-data、表单格式

自定义注解

1
2
3
4
5
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MultiFormat {
}

自定义注解解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class MultiFormatMethodProcessor implements HandlerMethodArgumentResolver {

private ServletModelAttributeMethodProcessor formResolver;
private RequestResponseBodyMethodProcessor jsonResolver;

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

jsonResolver = new JsonMethodArgumentResolver(messageConverters);
formResolver = new FormMethodArgumentResolver();
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
MultiFormat ann = parameter.getParameterAnnotation(MultiFormat.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");
}

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");
}
}

添加到Spring Confirguration

1
2
3
4
5
6
7
8
9
10
 @Bean
public MyMvcConfigurer mvcConfigurer() {
return new MyMvcConfigurer();
}

public static class MyMvcConfigurer implements WebMvcConfigurer {
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new GamePHPMethodProcessor());
}
}

form-data特殊处理

引入jar包
1
2
3
4
5
6
7
8
9
10
<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>
新增解析 bean
1
2
3
4
5
6
7
8
9
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setDefaultEncoding("UTF-8");
resolver.setResolveLazily(true);//resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常
resolver.setMaxInMemorySize(40960);
resolver.setMaxUploadSize(50*1024*1024);//上传文件大小 50M 50*1024*1024
return resolver;
}

只需将@RequestParam 注解改为 @MultiFormat,接口即可同时兼容三种 content-type。

流程为,spring 启动的时候,MyMvcConfigurer 调用 addArgumentResolvers 方法将 MultiFormatMethodProcessor注入,接到请求时,supportsParameter 方法判断是否使用此 resolver,如果为 true,则进入 resolveArgument 方法执行。