spring-mvc 非 controller 层获取HttpServletRequest

本文介绍如何在Spring MVC项目中记录操作日志,并详细解释了如何通过RequestContextListener和RequestContextHolder获取HttpServletRequest对象,以便记录访问IP和用户名等信息。
摘要由CSDN通过智能技术生成
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);
     }
// ...
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值