如何在 Spring-mvc 中设置请求参数的别名?



>当在 spring 中为请求参数使用bean 对象时:有没有办法为 bean 属性定义别名?

@RestController
public class MyServlet {
@GetMapping
public void test(MyReq req) {
}
}
public class MyReq {
@RequestParam("different-name") //this is invalid
private String name;
private int age;
}

当然@RequestParam不起作用,但是我可以使用类似的注释吗?

请求参数由 setter 绑定。您可以添加具有原始参数名称的额外资源库。像这样:

public class MyReq {
private String name;
private int age;
public void setDifferentName(String differentName) {
this.name=differentName;
}
}

注意:仅当您的参数像differentName=abc一样是驼峰大小写时,它才会起作用。不适用于different-name=abc.

使用以下方法,可以使用注释设置自定义名称:

见博佐斯回答: 绑定弹簧 mvc 命令对象时如何自定义参数名称

由于我使用的是 spring 4,因此可以按如下方式添加自定义解析器。

@Configuration
public class AdapterConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
super.addArgumentResolvers(argumentResolvers);
argumentResolvers.add(new AnnotationServletModelAttributeResolver(false));
}
}

然后可以在 get 查询 Bean 上使用它,如下所示:

@SupportsCustomizedBinding
public class MyReq {
@CommandParameter("different-name") //this is valid now!
private String name;
}

此外,由于我也喜欢匹配不区分大小写的 get 查询参数,因此我使用以下类:

https://github.com/mdeinum/spring-utils/blob/master/src/main/java/biz/deinum/web/filter/CaseInsensitiveRequestFilter.java

它可以按如下方式接线:

@Bean
public CaseInsensitiveRequestFilter caseInsensitiveFilter() {
return new CaseInsensitiveRequestFilter();
}

你可以为此使用二传手。举个例子:

@SpringBootApplication
public class So44390404Application {
public static void main(String[] args) {
SpringApplication.run(So44390404Application.class, args);
}
@RestController
public static class MyServlet {
@GetMapping
public String test(MyReq req) {
return req.toString();
}
}
public static class MyReq {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setDifferent_Name(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "{" + name + age + '}';
}
}
}

调用方可能会使用:

$so44390404 curl -XGET 'http://localhost:8000?name=adam&age=42'          
{adam42}%
$so44390404 curl -XGET 'http://localhost:8000?Different_Name=John&age=23'
{John23}% 

更新

好吧,如果您正在处理以连字符命名的参数,事情就会变得有点棘手。

基本上你可以:

  1. 制作一个过滤器,normalize带连字符的参数名称,以便 spring 可以成功绑定它们。
  2. 在控制器中接收所有请求参数作为原始映射,normalize键,然后自己用所有类型的转换内容填充对象。

带有筛选器的选项可能如下所示:

@Component
public static class CustomRequestParametersFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new RequestParameterNormalizerWrapper(request), response);
}
public static class RequestParameterNormalizerWrapper extends HttpServletRequestWrapper {
public static final String HYPHEN = "-";
private final Map<String, String[]> parameterMap = new HashMap<>();
public RequestParameterNormalizerWrapper(HttpServletRequest request) {
super(request);
for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
if (entry.getKey().contains(HYPHEN)) {
parameterMap.put(normalize(entry.getKey()), entry.getValue());
}
else {
parameterMap.put(entry.getKey(), entry.getValue());
}
}
}
private String normalize(final String key) {
if (key.contains(HYPHEN)) {
return WordUtils.capitalizeFully(key, HYPHEN.charAt(0)).replaceAll(HYPHEN, "");
}
return key;
}
@Override
public Map<String, String[]> getParameterMap() {
return Collections.unmodifiableMap(this.parameterMap);
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(this.parameterMap.keySet());
}
@Override
public String getParameter(String name) {
return super.getParameter(normalize(name));
}
@Override
public String[] getParameterValues(String name) {
return parameterMap.get(normalize(name));
}
}
}

使用前面的示例应该按原样工作。

第二个选项可能是:

@RestController
public static class MyServlet {
@GetMapping
public String test(@RequestParam Map<String, String> pvs) {
final MyReq req = new MyReq();
final BeanWrapper beanWrapper = new HyphenAwareBeanWrapper(req);
beanWrapper.setPropertyValues(pvs);
return req.toString();
}
}

和包装器:

public static class HyphenAwareBeanWrapper extends BeanWrapperImpl {
public static final String HYPHEN = "-";
public HyphenAwareBeanWrapper(Object object) {
super(object);
}
@Override
public void setPropertyValues(Map<?, ?> map) throws BeansException {
final ArrayList<PropertyValue> propertyValueList = new ArrayList<>(map.size());
for (Map.Entry<?, ?> entry : map.entrySet()) {
final String key = entry.getKey().toString().contains(HYPHEN)
? WordUtils.capitalizeFully(entry.getKey().toString(), HYPHEN.charAt(0)).replaceAll(HYPHEN, "")
: entry.getKey().toString();
propertyValueList.add(new PropertyValue(key, entry.getValue()));
}
super.setPropertyValues(new MutablePropertyValues(propertyValueList));
}
}

测试:

$ curl -XGET 'http://localhost:8000?name=John&age=42'
{John42}%
$ curl -XGET 'http://localhost:8000?different-name=John&age=42'
{John42}%

类似于Sergiy Dakhniy/Bohdan Levchenko的评论。 请求参数由资源库绑定。您可以从传入请求中添加一个带有参数名称的额外资源库。像这样:

@GetMapping(value = "/do-something")
public ResponseEntity<String> handleDoSomething(@Valid MyReq myReq) {
...
}
public class MyReq {
private String name;
public void setDifferent_name(String name) {
this.name = name;
}
}

例如:http://www.example.com/do-something?different_name=Joe

最新更新