spring-mvc 非 controller 层获取HttpServletRequest

在项目中记录操作日志,是一种很常见的需求。

有时我们在service或者dao层记录日志,需要同时保存访问ip、登录用户名等。如果从controller层把HttpServletRequest 对象传过去会显得很麻烦。HttpSession可以通过HttpServletRequest 间接获取。

需要注意的是RequestContextListener实现了javax.servlet.ServletRequestListener,这是servlet2.4之后才有的,一些比较老的容器使用这一功能会报空指针异常。

/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the "License").  You may not use this file except
 * in compliance with the License.
 *
 * You can obtain a copy of the license at
 * glassfish/bootstrap/legal/CDDLv1.0.txt or
 * https://glassfish.dev.java.net/public/CDDLv1.0.html.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * HEADER in each file and include the License file at
 * glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable,
 * add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your
 * own identifying information: Portions Copyright [yyyy]
 * [name of copyright owner]
 *
 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
 *
 * Portions Copyright Apache Software Foundation.
 */

package javax.servlet;

import java.util.EventListener;

    /**
     * A ServletRequestListener can be implemented by the developer
     * interested in being notified of requests coming in and out of
     * scope in a web component. A request is defined as coming into
     * scope when it is about to enter the first servlet or filter
     * in each web application, as going out of scope when it exits
     * the last servlet or the first filter in the chain.
     *
     * @since Servlet 2.4
     */


public interface ServletRequestListener extends EventListener {

    /** The request is about to go out of scope of the web application. */
    public void requestDestroyed ( ServletRequestEvent sre );

    /** The request is about to come into scope of the web application. */
    public void requestInitialized ( ServletRequestEvent sre );
}


在web.xml配置

<listener>
  <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 </listener>


在service或者dao中获取HttpServletRequest 的代码如下

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();

为了方便,可以如上代码提取到一个工具方法中,避免重复。

他的原理就是使用ThreadLocal,RequestContextListener监听器将HttpServletRequest绑定到当前线程。以下是部分源码

public class RequestContextListener implements ServletRequestListener {

    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
            RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";


    public void requestInitialized(ServletRequestEvent requestEvent) {
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes);
    }
// ...
}




你可能感兴趣的:(spring-mvc 非 controller 层获取HttpServletRequest)