Spring mvc. case insensitive get parameters mapping

后端 未结 3 613
温柔的废话
温柔的废话 2021-01-11 15:52

according this answer I try to write my code:

pojo:

class MyBean{

    public String getValueName() {
        return valueName;
    }

    public void          


        
相关标签:
3条回答
  • 2021-01-11 15:55

    Actually, you have to change the things in the CaseInsensitiveRequestFilter class as per your bean variable name. In your case the variable is valueName, so for every request it will convert it as per your variable setter method camel case injection and then match as per your request. Just try for your custom requirements:

    package biz.deinum.web.filter;
    
    import java.io.IOException;
    import java.util.Collections;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    import java.util.Set;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.util.LinkedCaseInsensitiveMap;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    public class CaseInsensitiveRequestFilter extends OncePerRequestFilter {
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            filterChain.doFilter(new CaseInsensitiveHttpServletRequestWrapper(request), response);
        }
    
        private static class CaseInsensitiveHttpServletRequestWrapper extends HttpServletRequestWrapper {
    
            private final LinkedCaseInsensitiveMap<String[]> params = new LinkedCaseInsensitiveMap<>();
    
            private CaseInsensitiveHttpServletRequestWrapper(HttpServletRequest request) {
                super(request);
                Map<String, String[]> map = request.getParameterMap();
                Set set = map.entrySet();
                Iterator it = set.iterator();
                Map<String, String[]> tempMap = new HashMap<String, String[]>(); 
                while (it.hasNext()) {
                    Map.Entry<String, String[]> entry = (Entry<String, String[]>) it.next();
                    String key = entry.getKey();
                    // Keep your parameter bean name here in your case it is "valueName"
                    String beanParamaterName = "valueName";
                    if(key.equalsIgnoreCase(beanParamaterName)){
                        tempMap.put(key.toLowerCase(), entry.getValue());
                    }
                }
                params.putAll(tempMap);
            }
    
            @Override
            public String getParameter(String name) {
                String[] values = getParameterValues(name);
                System.out.println(values.toString()+"-");
                if (values == null || values.length == 0) {
                    return null;
                }
                return values[0];
            }
    
            @Override
            public Map<String, String[]> getParameterMap() {
                return Collections.unmodifiableMap(this.params);
            }
    
            @Override
            public Enumeration<String> getParameterNames() {
                return Collections.enumeration(this.params.keySet());
            }
    
            @Override
            public String[] getParameterValues(String name) {
                System.out.println(name);
                return (String[])params.get(name);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-11 16:01

    Your problem, I believe, is @ModelAttribute. You're asking Spring to map the parameters to MyBean object, and the property inside this object is valueName.

    In order Spring to reflect the params to the object, it needs to be in the correct case.

    You have 2 options:

    • change the property name to valuename in your MyBean object, and all property names to lowercase, it should work with help of your solution.
    • remove @ModelAttribute and put @RequestParam for each property. If you have many props, this could be painful.
    0 讨论(0)
  • 2021-01-11 16:16

    Here is what you can do...

    Create the domain(POJO) with all lowercase variables

    public class MyBean{
        private String valuename;
    
        public String getValuename() {
            return valuename;
        }
    
        public void setValuename(String valuename) {
            this.valuename = valuename;
        }
    }
    

    Then create a class which will extend HttpServletRequestWrapper

    public class CustomWrappedRequest extends HttpServletRequestWrapper
    {
        private final Map<String, String[]> modifiableParameters;
        private Map<String, String[]> allParameters = null;
    
        public CustomWrappedRequest(final HttpServletRequest request, 
                                                        final Map<String, String[]> additionalParams)
        {
            super(request);
            modifiableParameters = new TreeMap<String, String[]>();
            modifiableParameters.putAll(additionalParams);
        }
    
        @Override
        public String getParameter(final String name)
        {
            String[] strings = getParameterMap().get(name);
            if (strings != null)
            {
                return strings[0];
            }
            return super.getParameter(name);
        }
    
        @Override
        public Map<String, String[]> getParameterMap()
        {
            if (allParameters == null)
            {
                allParameters = new TreeMap<String, String[]>();
                allParameters.putAll(super.getParameterMap());
                allParameters.putAll(modifiableParameters);
            }
            return Collections.unmodifiableMap(allParameters);
        }
    
        @Override
        public Enumeration<String> getParameterNames()
        {
            return Collections.enumeration(getParameterMap().keySet());
        }
    
        @Override
        public String[] getParameterValues(final String name)
        {
            return getParameterMap().get(name);
        }
    }
    

    Last add a filter with appropriate web.xml config the doFilter() will look like this

    public void doFilter(ServletRequest request, ServletResponse reponse, FilterChain chain)
                throws IOException, ServletException {
            Map<String, String[]> params = request.getParameterMap();
            Map<String, String[]> extraParams = new TreeMap<String, String[]>();
            Iterator<String> i = params.keySet().iterator();
    
            while ( i.hasNext() )
              {
                String key = (String) i.next();
                String value = ((String[]) params.get( key ))[ 0 ];
                extraParams.put(key.toLowerCase(), new String[] {value});
    
              }
            HttpServletRequest wrappedRequest = new CustomWrappedRequest((HttpServletRequest)request, extraParams);
    
            chain.doFilter(wrappedRequest, reponse);
    
        }
    

    Here the filter will convet the params into lowercase and attach it to your custom made request. Then use can use @ModelAttribute in the controller code to get the desired object.

    Hope it helps :)

    0 讨论(0)
提交回复
热议问题