Java 如何在Spring mvc中为请求参数设置别名?

Java 如何在Spring mvc中为请求参数设置别名?,java,spring,spring-mvc,Java,Spring,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

在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。举个例子:

@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}% 
更新

如果你处理连字符命名的参数,事情会变得有点棘手

基本上你可以:

  • 制作一个过滤器,它将规范化连字符参数名,这样spring就可以成功地绑定它们
  • 在控制器中将所有请求参数作为原始映射接收,
    规范化
    键,然后自己用所有类型转换内容填充对象
  • 带有筛选器的选项可能如下所示:

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

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

    见Bozhos的回答:

    在使用Spring4时,可以按如下方式添加自定义解析器

    @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;
    }
    
    @Bean
    public CaseInsensitiveRequestFilter caseInsensitiveFilter() {
        return new CaseInsensitiveRequestFilter();
    }
    

    请求参数由setter绑定。可以使用原始参数名称添加额外的setter。比如:

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

    注意:仅当您的参数是类似于
    differentName=abc
    的驼峰大小写时,它才起作用。与Sergiy Dakhniy/Bohdan Levchenko注释类似,将不适用于
    different name=abc

    。请求参数由setter绑定。您可以从传入请求中添加一个具有参数名称的额外setter。比如:

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

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

    你看过这篇文章了吗?不是开箱即用的。但是如果我重命名setter,我还可以完全重命名属性+getter+setter。但那不是我想要的。假设输入参数应该作为“MY-input”发送。像
    myinput=test
    这样的setter是无效的变量名。虽然我想提供一个可以使用此类参数的特性。是的,您也可以重命名字段和getter,但您不必这样做。一个属性可以有任意多个setter。至于hypen分离的参数名称,我已经更新了答案。
    @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;
      }
    }