Servlet规范系列 之 HttpServletRequestWrapper源码分析

欢迎大家关注本博,同时欢迎大家评论交流,可以给个赞哦!!!

  实际应用场景中,有时可能会有这样的需求:需要在请求进入应用之前,对请求进行统一处理,增加或减少到达应用的数据量,或者变换应用使用的HttpServletRequest的API,这时就可以创建一个类继承HttpServletRequestWrapper,它可以对HttpServletRequest进行再封装,然后之后的请求都会经过这个类,应用接收到的请求对象也会是这个类。

  HttpServletRequestWrapper集成了ServletRequestWrapper,ServletRequestWrapper是对ServletRequest的包装,HttpServletRequestWrapper是对HttpServletRequest的包装,其实查看源码后会发现,ServletRequestWrapper和HttpServletRequestWrapper提供的API完全调用的ServletRequest和HttpServletRequest的API进行实现。在我们进行应用时,使用HttpServletRequestWrapper即可,它同时拥有ServletRequestWrapper和HttpServletRequestWrapper的功能。

  ServletRequestWrapper

package javax.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

/**
 * ServletRequestWrapper提供了一个简便实现类,在对ServletRequest有改动需求的时,可以重写此类,之后Request的操作都会经过重写的类.
 */
public class ServletRequestWrapper implements ServletRequest {
    
    
    
    /**
     * ServletRequestWrapper持有ServletRequest的实例.
     */
    private ServletRequest request;

    /**
     * 构建ServletRequestWrapper,传入ServletRequest的值.
     */
    public ServletRequestWrapper(ServletRequest request) {
    
    
        if (request == null) {
    
    
            throw new IllegalArgumentException("Request cannot be null");
        }
        this.request = request;
    }

    /**
     * 获取ServletRequest实例.
     */
    public ServletRequest getRequest() {
    
    
        return this.request;
    }

    /**
     * 设置ServletRequest实例.
     * @param request ServletRequest.
     */
    public void setRequest(ServletRequest request) {
    
    
        if (request == null) {
    
    
            throw new IllegalArgumentException("Request cannot be null");
        }
        this.request = request;
    }

    /**
     * 获取Servlet的属性.
     */
    public Object getAttribute(String name) {
    
    
        return this.request.getAttribute(name);
    }

    /**
     * 获取所有属性枚举格式.
     */
    public Enumeration getAttributeNames() {
    
    
        return this.request.getAttributeNames();
    }

    /**
     * 返回请求中输入内容的字符编码类型,如果没有定义字符编码类型就返回空值.
     * @return 字符编码.
     */
    public String getCharacterEncoding() {
    
    
        return this.request.getCharacterEncoding();
    }

    /**
     * 设置输入内容的字符编码类型.
     * @param env 字符编码类型.
     * @throws java.io.UnsupportedEncodingException .
     */
    public void setCharacterEncoding(String enc) throws java.io.UnsupportedEncodingException {
    
    
        this.request.setCharacterEncoding(enc);
    }

    /**
     * 请求内容的长度,如果长度未知就返回-1.
     * @return 请求内容长度.
     */
    public int getContentLength() {
    
    
        return this.request.getContentLength();
    }

    /**
     * 返回请求数据体的MIME类型CONTENT-TYPE,如果类型未知返回空值.
     * @return
     */
    public String getContentType() {
    
    
        return this.request.getContentType();
    }

    /**
     * 返回一个输入流,使用该输入流以二进制方式读取请求正文的内容.
     * javax.servlet.ServletInputStream是一个抽象类,继承自InputStream.
     * @return .
     * @throws IOException .
     */
    public ServletInputStream getInputStream() throws IOException {
    
    
        return this.request.getInputStream();
    }

    /**
     * 根据指定参数名获取参数值.
     * @param name 参数名.
     * @return 参数值.
     */
    public String getParameter(String name) {
    
    
        return this.request.getParameter(name);
    }

    /**
     * 获取参数的Map形式,包括所有参数.
     * @return 参数Map.
     */
    public Map getParameterMap() {
    
    
        return this.request.getParameterMap();
    }

    /**
     * 获取所有参数名的枚举.
     * @return 参数名枚举.
     */
    public Enumeration getParameterNames() {
    
    
        return this.request.getParameterNames();
    }

    /**
     * 根据指定属性名获取参数值数组.
     * @param name 参数名.
     * @return 参数值数组.
     */
    public String[] getParameterValues(String name) {
    
    
        return this.request.getParameterValues(name);
    }

    /**
     * 返回请求使用的协议信息.格式为:协议/主版本号.次版本号.例如:http/1.0.
     * @return
     */
    public String getProtocol() {
    
    
        return this.request.getProtocol();
    }

    /**
     * 返回请求所使用的URL的模式.若http、https等.
     * @return 模式.
     */
    public String getScheme() {
    
    
        return this.request.getScheme();
    }

    /**
     * 返回请求发送到的服务器的主机名.
     * @return 主机名.
     */
    public String getServerName() {
    
    
        return this.request.getServerName();
    }

    /**
     * 返回请求发送到的服务器的端口号.
     * @return 端口号.
     */
    public int getServerPort() {
    
    
        return this.request.getServerPort();
    }

    /**
     * 返回BufferedReader对象,以字节数据方式读取请求正文.
     * @return .
     * @throws IOException .
     */
    public BufferedReader getReader() throws IOException {
    
    
        return this.request.getReader();
    }

    /**
     * 返回发送请求的客户端或最后一个代理服务器的IP地址.
     * @return IP地址.
     */
    public String getRemoteAddr() {
    
    
        return this.request.getRemoteAddr();
    }

    /**
     * 返回发送请求的客户端或最后一个代理服务器的主机名.
     * @return 主机名.
     */
    public String getRemoteHost() {
    
    
        return this.request.getRemoteHost();
    }

    /**
     * 根据传递的属性名和属性值设置Request属性.
     * @param name 属性名.
     * @param o 属性值.
     */
    public void setAttribute(String name, Object o) {
    
    
        this.request.setAttribute(name, o);
    }

    /**
     * 从Request中删除指定的属性名对应的值.一般使用此方法.
     * @param name 属性名.
     */
    public void removeAttribute(String name) {
    
    
        this.request.removeAttribute(name);
    }

    /**
     * 根据客户端传递的Accept-Language对应的区域设置.
     * 若客户端未指定Accept-Language,则返回服务器默认语言环境.
     * @return
     */
    public Locale getLocale() {
    
    
        return this.request.getLocale();
    }

    /**
     * 返回Locale对象的枚举,从首选区域开始按降序返回基于Accept-Language头的客户端可接受的区域.
     * 如果客户机请求不提供Accept-Language头,此方法返回包含一个Locale的枚举,即是服务器默认语言环境对应的Locale.
     * @return
     */
    public Enumeration getLocales() {
    
    
        return this.request.getLocales();
    }

    /**
     * 指示是否使用安全通道(如HTTPS)发出此请求.
     */
    public boolean isSecure() {
    
    
        return this.request.isSecure();
    }

    /**
     * 返回RequestDispatcher对象,作为path所定位的资源的封装.
     * RequestDispatcher用于服务器请求转发.
     * @param path 相对路径或绝对路径.
     * @return RequestDispatcher.
     */
    public RequestDispatcher getRequestDispatcher(String path) {
    
    
        return this.request.getRequestDispatcher(path);
    }

    /**
     * @deprecated
     * Servlet API 2.1开始已不推荐使用此API.
     * 取得文件在服务器上的绝对路径.
     * @param path 相对路径.
     * @return 绝对路径.
     */
    public String getRealPath(String path) {
    
    
        return this.request.getRealPath(path);
    }

    /**
     * 返回发送请求的客户端或者最后一个代理服务器的IP源端口, 这个方法是在Servlet 2.4规范中新增的方法.
     * @return 端口号.
     */
    public int getRemotePort() {
    
    
        return this.request.getRemotePort();
    }

    /**
     * 返回接收到请求的IP接口的主机名,这个方法是在Servlet 2.4规范中新增的方法.
     * @return 主机名.
     */
    public String getLocalName() {
    
    
        return this.request.getLocalName();
    }

    /**
     * 返回接收到请求的网络接口的IP地址,这个方法是在Servlet 2.4规范中新增的方法.
     * @return IP地址.
     */
    public String getLocalAddr() {
    
    
        return this.request.getLocalAddr();
    }

    /**
     * 返回接收到请求的网络接口的IP端口号,这个方法是在Servlet 2.4规范中新增的方法.
     * @return 端口号.
     */
    public int getLocalPort() {
    
    
        return this.request.getLocalPort();
    }

}

  HttpServletRequestWrapper

package javax.servlet.http;

import javax.servlet.ServletRequestWrapper;
import java.util.Enumeration;

/**
 * HttpServletRequestWrapper提供了一个简便实现不了,在对HttpServletRequest有改动需求的时,可以重写此类,之后Request的操作都会经过重写的类.
 */
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest {
    
    

    /**
     * Constructs.
     */
    public HttpServletRequestWrapper(HttpServletRequest request) {
    
    
        super(request);
    }
    
    /**
     * 获取HttpServletRequest.
     * @return HttpServletRequest.
     */
    private HttpServletRequest _getHttpServletRequest() {
    
    
        return (HttpServletRequest) super.getRequest();
    }

    /**
     * 返回认证类型.
     * 所有Servlet容器都支持basic、form、client_cert,digest不一定支持.
     * 若不支持,则返回null.
     */
    public String getAuthType() {
    
    
        return this._getHttpServletRequest().getAuthType();
    }

    /**
     * 获取请求中带有的Cookie信息.
     */
    public Cookie[] getCookies() {
    
    
        return this._getHttpServletRequest().getCookies();
    }

    /**
     * 以长整数形式返回一个特定的请求头,该长整数代表一个Date对象. 
     * 该方法可以用在包含时间信息的header中,如:If-Modified-Since.
     * @param name 头名称.
     * @return 头值.
     */
    public long getDateHeader(String name) {
    
    
        return this._getHttpServletRequest().getDateHeader(name);
    }

    /**
     * 根据指定的头名称获取头的值.
     * 若存在多个,则返回第一个.
     * @param name 头名称.
     * @return 头值.
     */
    public String getHeader(String name) {
    
    
        return this._getHttpServletRequest().getHeader(name);
    }

    /**
     * 根据指定的头名称获取头值的枚举.
     * 若没有找到,则返回空的枚举.
     * @param name 头名称.
     * @return 头值.
     */
    public Enumeration getHeaders(String name) {
    
    
        return this._getHttpServletRequest().getHeaders(name);
    }

    /**
     * 获取所有的头的枚举.
     * @return 头的枚举.
     */
    public Enumeration getHeaderNames() {
    
    
        return this._getHttpServletRequest().getHeaderNames();
    }

    /**
     * 根据指定头名称获取int类型的值.若未找到则返回-1,如不是int类型,则会抛出NumberFormatException异常.
     * @param name 头名称.
     * @return 头值.
     */
    public int getIntHeader(String name) {
    
    
        return this._getHttpServletRequest().getIntHeader(name);
    }

    /**
     * 获取HTTP方法,如:GET、POST、PUT等.
     * @return 方法名.
     */
    public String getMethod() {
    
    
        return this._getHttpServletRequest().getMethod();
    }

    /**
     * 官网解释:
     *  返回与客户端发出此请求时发送的URL相关联的任何额外路径信息.
     *  额外的路径信息跟随servlet路径,但位于查询字符串之前,并以"/"字符开头.
     * 例如:url-pattern配置为/demo/*,请求URL为http://localhost/Pro/demo/htm/index.html,则pathInfo为/htm/index.html.
     * @return
     */
    public String getPathInfo() {
    
    
        return this._getHttpServletRequest().getPathInfo();
    }

    /**
     * 返回servlet名称之后、
     *      查询字符串之前的任何额外路径信息,并将其转换为实际路径. 
     *      与转换的CGI变量PATH U的值相同
     * @return
     */
    public String getPathTranslated() {
    
    
        return this._getHttpServletRequest().getPathTranslated();
    }

    /**
     * 返回项目根路径.
     * 例如:url-pattern配置为/demo/*,请求URL为http://localhost/Pro/demo/htm/index.html,则contextPath为/demo.
     * @return 项目根路径.
     */
    public String getContextPath() {
    
    
        return this._getHttpServletRequest().getContextPath();
    }

    /**
     * 获得请求中的查询字符串,例如a=1&b=2这样的格式.
     * @return 查询字符串.
     */
    public String getQueryString() {
    
    
        return this._getHttpServletRequest().getQueryString();
    }

    /**
     * 如果用户已经过验证,则返回发出此请求的用户的登录信息,如果用户未经过验证,则返回 null.
     * 用户名是否随每个后续请求发送取决于浏览器和验证类型,返回的值与 CGI变量REMOTE_USER的值相同.
     * @return 用户信息.
     */
    public String getRemoteUser() {
    
    
        return this._getHttpServletRequest().getRemoteUser();
    }

    /**
     * 返回一个 boolean值,指示指定的逻辑"角色"中是否包含经过验证的用户.
     * 角色和角色成员关系可使用部署描述符定义.
     * 如果用户没有经过验证,则该方法返回 false.
     * @param role 角色.
     * @return 已验证用户是否属于某种角色.
     */
    public boolean isUserInRole(String role) {
    
    
        return this._getHttpServletRequest().isUserInRole(role);
    }

    /**
     * 返回包含当前已经过验证的用户的名称的 java.security.Principal对象.
     * 如果用户没有经过验证,则该方法返回 null.
     * @return java.security.Principal或null.
     */
    public java.security.Principal getUserPrincipal() {
    
    
        return this._getHttpServletRequest().getUserPrincipal();
    }

    /**
     * 获取请求对应的sessionId.
     * @return sessionId.会话ID.
     */
    public String getRequestedSessionId() {
    
    
        return this._getHttpServletRequest().getRequestedSessionId();
    }

    /**
     * 请求URL的相对地址,包括服务器路径,不包括查询参数.
     * @return 请求URL的相对地址.
     */
    public String getRequestURI() {
    
    
        return this._getHttpServletRequest().getRequestURI();
    }

    /**
     * 请求的URL地址,包含协议、主机名、端口和服务器路径,但是不包括查询参数.
     * @return 请求URL地址.
     */
    public StringBuffer getRequestURL() {
    
    
        return this._getHttpServletRequest().getRequestURL();
    }

    /**
     * 官方解释:
     *  返回此请求的URL中调用servlet的部分.
     *  此路径以"/"字符开头,包含servlet名称或到servlet的路径,但不包含任何额外的路径信息或查询字符串.
     *  与CGI变量SCRIPT_NAME的值相同.
     * 其实真是的意思就是,在配置webx.xml或编程式配置时,配置了url-pattern,请求的URL与url-pattern的有效部分重合部分就是servletPath,
     * 也可以理解为url-pattern的有效部分就是servletPath.
     * 例如:url-pattern配置为/demo/*,请求URL为http://localhost/Pro/demo/htm/index.html,则servletPath为/demo.
     * @return
     */
    public String getServletPath() {
    
    
        return this._getHttpServletRequest().getServletPath();
    }

    /**
     * 获得请求对应的当前sesson.
     * 在没有session的情况下:
     *  若create=true,则新创建一个session.
     *  若create=false,则不创建session,返回null.
     * @param create session失效的情况下,是否创建session.
     * @return HttpSession实例.
     */
    public HttpSession getSession(boolean create) {
    
    
        return this._getHttpServletRequest().getSession(create);
    }

    /**
     * 获得请求对应的当前sesson.
     * 若没有session,则创建一个session.
     * @return HttpSession实例.
     */
    public HttpSession getSession() {
    
    
        return this._getHttpServletRequest().getSession();
    }

    /**
     * 返回session是否有效.
     * @return session是否有效.
     */
    public boolean isRequestedSessionIdValid() {
    
    
        return this._getHttpServletRequest().isRequestedSessionIdValid();
    }

    /**
     * sessionId是否从Cookie中获得.
     * @return 若是从Cookie中获得,返回true,否则返回false.
     */
    public boolean isRequestedSessionIdFromCookie() {
    
    
        return this._getHttpServletRequest().isRequestedSessionIdFromCookie();
    }

    /**
     * sessionId是否从URL中获得.
     * @return 若是从URL中获得,返回true,否则返回false.
     */
    public boolean isRequestedSessionIdFromURL() {
    
    
        return this._getHttpServletRequest().isRequestedSessionIdFromURL();
    }

    /**
     * @deprecated
     * sessionId是否从URL中获得.
     * @return 若是从URL中获得,返回true,否则返回false.
     */
    public boolean isRequestedSessionIdFromUrl() {
    
    
        return this._getHttpServletRequest().isRequestedSessionIdFromUrl();
    }

}

  若文中存在错误和不足,欢迎指正!

本博微信公众号“超哥说码”,欢迎大家订阅,公众号正在完善中,会及时将更优质的博文推送于您!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/securitit/article/details/108046153
今日推荐