如何在Spring-mvc中为请求参数设置别名?
在spring中有一个用于请求参数的bean对象:是否有一种方法可以为bean属性定义一个别名?如何在Spring-mvc中为请求参数设置别名?
@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
不起作用,但是有没有类似的注释可以使用?
您可以使用setters。鉴于您的例子:
@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}%
更新
好吧,如果你要处理的连字符命名参数事情变得有点棘手。
基本上你可以:
- 让这将
normalize
带有分隔符的参数名称,以便弹簧能够成功地约束他们的过滤器。 - 接收所有请求参数作为您的控制器中的原始地图,
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}%
好吧,但如果我重命名setter,我完全可以重命名属性+ getter + setter。但那不是我想要的。想象一下,输入参数应该作为“MY-INPUT”发送。像'my-input = test'这样的setter是一个无效的变量名。虽然我想提供一个功能,这些参数是可能的。 – membersound
是的,你可以重命名字段和getter,但你不必。您可以根据需要为一个属性设置多个setter。至于hypen-separated参数名称 - 我已经更新了一个答案。 –
用以下方法也可以使用设置自定义名称注释:
请参阅Bozhos回答: How to customize parameter names when binding spring mvc command objects
因为我使用spring 4,所以可以按如下方式添加自定义解析器。
@Configuration
public class AdapterConfig extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
super.addArgumentResolvers(argumentResolvers);
argumentResolvers.add(new AnnotationServletModelAttributeResolver(false));
}
}
然后,它可以在GET查询豆用来如下:
@SupportsCustomizedBinding
public class MyReq {
@CommandParameter("different-name") //this is valid now!
private String name;
}
此外,由于我也喜欢搭配GET查询参数不区分大小写的,我用下面的类:
它可以是有线的,如下所示:
@Bean
public CaseInsensitiveRequestFilter caseInsensitiveFilter() {
return new CaseInsensitiveRequestFilter();
}
您是否看过这篇文章? https://dzone.com/articles/customizing-parameter-names –
不是开箱即用的。 –