简短的问题描述
我无法将 ...?name=John&sports[]=Volleyball&sports[]=Volleyball
之类的 url 参数转换为 Spring MVC 中的以下 Java 类。
class PersonFilter {
String name;
List<String> sports;
}
我需要在 sports[] 参数名称中使用括号。
长问题描述
我使用 DataTables 框架和 Spring MVC。 我需要向数据表 ajax 请求添加一些复杂的过滤器属性,如下所示:
$('#table').DataTable({
serverSide: true,
ajax: {
url: "https://server/some/path",
data: function (data) {
data.name = "John",
data.sports = ["Football", "Volleyball"]
}
}
});
创建了具有排序功能的 DataTables 请求(参数 order
和 columns
)和自定义过滤器(参数 name
和 sports[]
)看起来像:
https://server/some/path?name=John&sports[]=Volleyball&sports[]=Football&columns[0][name]=name&order[0][column]=0&order[0][dir]=asc
我需要将 URL 参数绑定(bind)到包含 java.util.List
的 PersonFilter 类。
class PersonFilter {
String name;
List<String> sports;
}
Controller 看起来像:
@Controller
class PersonController {
@RequestMapping(path = "/search")
public List<Person> search(PersonFilter personFilter) {
...
}
}
Spring 允许使用以下语法进行列表绑定(bind) ( http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#beans-beans-conventions ):
1) sports=Volleyball&sports=Football -> OK
2) sports[0]=Volleyball&sports[1]=Football -> OK
但是 Spring 无法将名为 sports[]
的属性转换为 List。
sports[]=Volleyball&sports[]=Football -> FAILs (expects index in brackets)
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_121]
at java.lang.Integer.parseInt(Integer.java:592) ~[na:1.8.0_121]
at java.lang.Integer.parseInt(Integer.java:615) ~[na:1.8.0_121]
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:354) ~[spring-beans-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:280) ~[spring-beans-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95) ~[spring-beans-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:859) ~[spring-context-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.validation.DataBinder.doBind(DataBinder.java:755) ~[spring-context-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:192) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:106) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.bindRequestParameters(ServletModelAttributeMethodProcessor.java:150) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:114) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:160) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.6.jar:8.5.6]
我尝试过的:
使用 JQuery ajax 设置 jQuery.ajaxSettings.traditional = true
。
但在这种情况下,用于排序(顺序、列)的 DataTables 参数会导致 [Object]
,因此我无法解析排序参数。
https://server/some/path?name=John&sports=Volleyball&sports=Football&columns=[object Object]&order=[object Object]
谢谢您的建议!
最佳答案
最后我决定修改过滤器中请求的参数。
我创建了HttpServletRequestWrapper它从请求参数中删除括号 []
。
public class JQueryArrayParameterRequestWrapper extends HttpServletRequestWrapper {
public static final String BRACKETS_SUFFIX = "[]";
private Map<String, String[]> _parameterMap;
public JQueryArrayParameterRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public Map<String, String[]> getParameterMap() {
if (_parameterMap == null) {
_parameterMap = modifyParameterMap(super.getParameterMap());
}
return _parameterMap;
}
@Override
public Enumeration<String> getParameterNames() {
return Collections.enumeration(getParameterMap().keySet());
}
@Override
public String[] getParameterValues(String name) {
return getParameterMap().get(name);
}
@Override
public String getParameter(String name) {
return getParameterValues(name) != null && getParameterValues(name).length > 0 ? getParameterValues(name)[0] : null;
}
private Map<String, String[]> modifyParameterMap(Map<String, String[]> oldParameterMap) {
Map<String, String[]> newParameterMap = new HashMap<>(oldParameterMap.size());
for (Map.Entry<String, String[]> entry : oldParameterMap.entrySet()) {
String key = entry.getKey();
if (key.endsWith(BRACKETS_SUFFIX)) {
// remove brackets from parameter name
String newKey = key.substring(0, key.length() - BRACKETS_SUFFIX.length());
newParameterMap.put(newKey, entry.getValue());
} else {
// leave parameter unmodified
newParameterMap.put(key, entry.getValue());
}
}
return newParameterMap;
}
}
然后我创建了过滤器:
public class JQueryArrayParameterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
/* empty */
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new JQueryArrayParameterRequestWrapper((HttpServletRequest) request), response);
}
@Override
public void destroy() {
/* empty */
}
}
最后,我为 DataTables 请求注册了过滤器。
@Configuration
public class AppConfiguration {
@Bean
public JQueryArrayParameterFilter jQueryArrayParameterFilter() {
return new JQueryArrayParameterFilter();
}
@Bean
public FilterRegistrationBean filterRegistrationBean(JQueryArrayParameterFilter filter) {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.addUrlPatterns( "/datatables/*");
return filterRegistrationBean;
}
}
关于java - Spring MVC + 数据表 : bind array[] parameter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41883647/