spring-mvc 非 controller 层获取HttpServletRequest

来源:互联网 发布:cf2016年刷枪软件 编辑:程序博客网 时间:2024/05/20 05:23
spring-mvc HttpServletRequest RequestContextListener RequestContextHolder

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*
 * 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配置

?
1
2
3
<listener>
  <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 </listener>


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

?
1
2
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
    }
// ...
}
0 0
原创粉丝点击