在优化搜索请求时遇到问题。我有一个搜索方法,接受url查询中的参数,如:
http://localhost:8080/api?code.<type>=<value>&name=Test
Example: http://localhost:8080/api?code.phone=9999999999&name=Test
SearchDto:定义
public class SearchDto {
String name;
List<Code> code;
}
定义代码类:
public class Code {
String type;
String value;
}
目前我使用Map<String,String>作为方法的传入参数:
@GetMapping("/search")
public ResponseEntity<?> search(final @RequestParam Map<String, String> searchParams) {
return service.search(searchParams);
}
然后手动将searchd的映射值转换为类。有没有可能去掉Map<String,String>并通过SearchDto直接作为参数在控制器方法?
在querystring中传递json实际上是一个不好的做法,因为它降低了安全性并设置了可以发送到端点的参数数量的限制。
从技术上讲,你可以使用DTO作为控制器的参数,然后在将json发送到后端之前对其进行URL编码,从而使一切工作。
在您的情况下,最好的选择是为侦听POST请求的端点提供服务:在执行搜索时使用POST不是错误,也不是坏做法。
您可以自定义HandlerMethodArgumentResolver
来实现它。
但是,如果你想要一个对象接收传入参数。为什么不用POST
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Example {
}
public class ExampleArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
Example requestParam = parameter.getParameterAnnotation(Example.class);
return requestParam != null;
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
ResolvableType resolvableType = ResolvableType.forMethodParameter(parameter);
Map<String, String[]> parameterMap = webRequest.getParameterMap();
Map<String, String> result = CollectionUtils.newLinkedHashMap(parameterMap.size());
parameterMap.forEach((key, values) -> {
if (values.length > 0) {
result.put(key, values[0]);
}
});
//here will return a map object. then you convert map to your object, I don't know how to convert , but you have achieve it.
return o;
}
}
添加到容器
@Configuration
@EnableWebMvc
public class ExampleMvcConfiguration implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new ExampleArgumentResolver());
}
}
使用
@RestController
public class TestCtrl {
@GetMapping("api")
public Object gg(@Example SearchDto searchDto) {
System.out.println(searchDto);
return "1";
}
@Data
public static class SearchDto {
String name;
List<Code> code;
}
@Data
public static class Code {
String type;
String value;
}
}
这是一个演示。