【问题标题】:How to set a parameter in a HttpServletRequest?如何在 HttpServletRequest 中设置参数?
【发布时间】:2009-05-21 11:47:11
【问题描述】:

我正在使用 javax.servlet.http.HttpServletRequest 来实现 Web 应用程序。

使用 getParameter 方法获取请求的参数没有问题。但是我不知道如何在我的请求中设置参数。

【问题讨论】:

    标签: java web-applications


    【解决方案1】:

    你不能,不使用标准 API。 HttpServletRequest 表示服务器收到的请求,因此添加新参数不是有效选项(就 API 而言)。

    您原则上可以实现HttpServletRequestWrapper 的子类,它包装原始请求,并拦截getParameter() 方法,并在您转发时传递包装的请求。

    如果您走这条路,您应该使用Filter 将您的HttpServletRequest 替换为HttpServletRequestWrapper

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        if (servletRequest instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            // Check wether the current request needs to be able to support the body to be read multiple times
            if (MULTI_READ_HTTP_METHODS.contains(request.getMethod())) {
                // Override current HttpServletRequest with custom implementation
                filterChain.doFilter(new HttpServletRequestWrapper(request), servletResponse);
                return;
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }
    

    【讨论】:

    • 我假设你从here 得到了这个实现。 MULTI_READ_HTTP_METHODS 有点令人困惑,虽然现在我明白它的用途,但如果完全删除,我要求您删除它。
    【解决方案2】:

    如果您真的想这样做,请创建一个 HttpServletRequestWrapper。

    public class AddableHttpRequest extends HttpServletRequestWrapper {
    
       private HashMap params = new HashMap();
    
       public AddableingHttpRequest(HttpServletRequest request) {
               super(request);
       }
    
       public String getParameter(String name) {
               // if we added one, return that one
               if ( params.get( name ) != null ) {
                     return params.get( name );
               }
               // otherwise return what's in the original request
               HttpServletRequest req = (HttpServletRequest) super.getRequest();
               return validate( name, req.getParameter( name ) );
       }
    
       public void addParameter( String name, String value ) {
               params.put( name, value );
       }
    
    }
    

    【讨论】:

    • 方法 validate 的作用是什么?
    • @Jeff,你能告诉我这个验证方法是什么吗??
    • 只需将其替换为 - return req.getParameter(name);
    【解决方案3】:

    根据您的问题,我认为您要做的是使用 RequestDispatcher() 存储一些东西(一个对象、一个字符串......),然后将其转发到另一个 servlet。 为此,您不需要设置参数,而是使用属性来设置

    void setAttribute(String name, Object o);
    

    然后

    Object getAttribute(String name);
    

    【讨论】:

    • 属性和参数是不可互换的,代表着非常不同的概念。
    • @skaffman 但也许他可以使用属性解决他需要的问题 - 在处理请求的过程中不需要向请求添加新参数
    • 应编辑答案以反映设置属性可能是解决问题的方法,而不是暗示设置属性会在请求中设置参数。
    • 对不起,如果我的问题不够清楚,但我真正想知道的是是否可以设置参数而不是属性,这就是我接受 skaffman 回答的原因。但是,您的回答很好,可能会对其他人有所帮助:-)
    • 没问题...只是出于好奇...为什么需要设置参数?谢谢
    【解决方案4】:

    最受好评的解决方案通常有效,但对于 Spring 和/或 Spring Boot,除非您专门实现了 getParameterValues(),否则这些值不会连接到带有 @RequestParam 注释的控制器方法中的参数。我在这里和this blog 合并了解决方案:

    import java.util.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    public class MutableHttpRequest extends HttpServletRequestWrapper {
    
        private final Map<String, String[]> mutableParams = new HashMap<>();
    
        public MutableHttpRequest(final HttpServletRequest request) {
            super(request);
        }
    
        public MutableHttpRequest addParameter(String name, String value) {
            if (value != null)
                mutableParams.put(name, new String[] { value });
    
            return this;
        }
    
        @Override
        public String getParameter(final String name) {
            String[] values = getParameterMap().get(name);
    
            return Arrays.stream(values)
                    .findFirst()
                    .orElse(super.getParameter(name));
        }
    
        @Override
        public Map<String, String[]> getParameterMap() {
            Map<String, String[]> allParameters = new HashMap<>();
            allParameters.putAll(super.getParameterMap());
            allParameters.putAll(mutableParams);
    
            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);
        }
    }
    
    

    请注意,此代码不是超级优化的,但它可以工作。

    【讨论】:

      【解决方案5】:

      正如之前的帖子中提到的,使用 HttpServletReqestWrapper 是可行的方法,但是这些帖子中遗漏的部分是除了重写方法 getParameter() 之外,您还应该重写其他与参数相关的方法以产生一致的响应.例如自定义请求包装器添加的参数值也应包含在方法 getParameterMap() 返回的参数映射中。这是一个例子:

         public class AddableHttpRequest extends HttpServletRequestWrapper {
      
          /** A map containing additional request params this wrapper adds to the wrapped request */
          private final Map<String, String> params = new HashMap<>();
      
          /**
           * Constructs a request object wrapping the given request.
           * @throws java.lang.IllegalArgumentException if the request is null
           */
          AddableHttpRequest(final HttpServletRequest request) {
              super(request)
          }
      
          @Override
          public String getParameter(final String name) {
              // if we added one with the given name, return that one
              if ( params.get( name ) != null ) {
                  return params.get( name );
              } else {
                  // otherwise return what's in the original request
                  return super.getParameter(name);
              }
          }
      
      
          /**
           * *** OVERRIDE THE METHODS BELOW TO REFLECT PARAMETERS ADDED BY THIS WRAPPER ****
           */
      
          @Override
          public Map<String, String> getParameterMap() {
              // defaulf impl, should be overridden for an approprivate map of request params
              return super.getParameterMap();
          }
      
          @Override
          public Enumeration<String> getParameterNames() {
              // defaulf impl, should be overridden for an approprivate map of request params names
              return super.getParameterNames();
          }
      
          @Override
          public String[] getParameterValues(final String name) {
              // defaulf impl, should be overridden for an approprivate map of request params values
              return super.getParameterValues(name);
          }
      }
      

      【讨论】:

        【解决方案6】:

        丢失的 getParameterMap 覆盖最终对我来说是一个真正的问题。所以这就是我最终的结果:

        import java.util.HashMap;
        import java.util.Map;
        
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletRequestWrapper;
        
        /***
         * Request wrapper enabling the update of a request-parameter.
         * 
         * @author E.K. de Lang
         *
         */
        final class HttpServletRequestReplaceParameterWrapper
            extends HttpServletRequestWrapper
        {
        
            private final Map<String, String[]> keyValues;
        
            @SuppressWarnings("unchecked")
            HttpServletRequestReplaceParameterWrapper(HttpServletRequest request, String key, String value)
            {
                super(request);
        
                keyValues = new HashMap<String, String[]>();
                keyValues.putAll(request.getParameterMap());
                // Can override the values in the request
                keyValues.put(key, new String[] { value });
        
            }
        
            @SuppressWarnings("unchecked")
            HttpServletRequestReplaceParameterWrapper(HttpServletRequest request, Map<String, String> additionalRequestParameters)
            {
                super(request);
                keyValues = new HashMap<String, String[]>();
                keyValues.putAll(request.getParameterMap());
                for (Map.Entry<String, String> entry : additionalRequestParameters.entrySet()) {
                    keyValues.put(entry.getKey(), new String[] { entry.getValue() });
                }
        
            }
        
            @Override
            public String getParameter(String name)
            {
                if (keyValues.containsKey(name)) {
                    String[] strings = keyValues.get(name);
                    if (strings == null || strings.length == 0) {
                        return null;
                    }
                    else {
                        return strings[0];
                    }
                }
                else {
                    // Just in case the request has some tricks of it's own.
                    return super.getParameter(name);
                }
            }
        
            @Override
            public String[] getParameterValues(String name)
            {
                String[] value = this.keyValues.get(name);
                if (value == null) {
                    // Just in case the request has some tricks of it's own.
                    return super.getParameterValues(name);
                }
                else {
                    return value;
                }
            }
        
            @Override
            public Map<String, String[]> getParameterMap()
            {
                return this.keyValues;
            }
        
        }
        

        【讨论】:

          【解决方案7】:

          对不起,为什么不使用以下结构:

          request.getParameterMap().put(parameterName, new String[] {parameterValue});
          

          【讨论】:

          • 因为你得到这个异常:java.lang.IllegalStateException: No modify is allowed to a locked ParameterMap
          猜你喜欢
          • 2021-08-07
          • 2018-09-07
          • 2016-01-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-27
          相关资源
          最近更新 更多