`

如何在Java Filter 中注入 Service

    博客分类:
  • JAVA
阅读更多

在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null。如下所示:

复制代码
public class WeiXinFilter implements Filter{
    
    @Autowired
    private UsersService usersService;

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse resp = (HttpServletResponse)response;
     Users users = this.usersService.queryByOpenid(openid);
}
复制代码

上面的 usersService 会报空指针异常。

解决方法一

复制代码
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse resp = (HttpServletResponse)response;
        ServletContext sc = req.getSession().getServletContext();
        XmlWebApplicationContext cxt = (XmlWebApplicationContext)WebApplicationContextUtils.getWebApplicationContext(sc);
        
        if(cxt != null && cxt.getBean("usersService") != null && usersService == null)
            usersService = (UsersService) cxt.getBean("usersService");
        
        Users users = this.usersService.queryByOpenid(openid);
复制代码

这样就行了。

方法二

复制代码
public class WeiXinFilter implements Filter{
    
    private UsersService usersService;
    
    public void init(FilterConfig fConfig) throws ServletException {
        ServletContext sc = fConfig.getServletContext(); 
        XmlWebApplicationContext cxt = (XmlWebApplicationContext)WebApplicationContextUtils.getWebApplicationContext(sc);
        
        if(cxt != null && cxt.getBean("usersService") != null && usersService == null)
            usersService = (UsersService) cxt.getBean("usersService");        
    }
复制代码

相关原理

1. 如何获取 ServletContext

1)在javax.servlet.Filter中直接获取 
ServletContext context = config.getServletContext(); 

2)在HttpServlet中直接获取 
this.getServletContext() 

3)在其他方法中,通过HttpServletRequest获得 
request.getSession().getServletContext();

2. WebApplicationContext 与 ServletContext (转自:http://blessht.iteye.com/blog/2121845):

Spring的 ContextLoaderListener是一个实现了ServletContextListener接口的监听器,在启动项目时会触发contextInitialized方法(该方法主要完成ApplicationContext对象的创建),在关闭项目时会触发contextDestroyed方法(该方法会执行ApplicationContext清理操作)。

ConextLoaderListener加载Spring上下文的过程

①启动项目时触发contextInitialized方法,该方法就做一件事:通过父类contextLoader的initWebApplicationContext方法创建Spring上下文对象。

②initWebApplicationContext方法做了三件事:创建 WebApplicationContext;加载对应的Spring文件创建里面的Bean实例;将WebApplicationContext放入 ServletContext(就是Java Web的全局变量)中

③createWebApplicationContext创建上下文对象,支持用户自定义的上下文对象,但必须继承自ConfigurableWebApplicationContext,而Spring MVC默认使用ConfigurableWebApplicationContext作为ApplicationContext(它仅仅是一个接口)的实 现。

④configureAndRefreshWebApplicationContext方法用 于封装ApplicationContext数据并且初始化所有相关Bean对象。它会从web.xml中读取名为 contextConfigLocation的配置,这就是spring xml数据源设置,然后放到ApplicationContext中,最后调用传说中的refresh方法执行所有Java对象的创建。

⑤完成ApplicationContext创建之后就是将其放入ServletContext中,注意它存储的key值常量。

方法三

直接使用spring mvc中的HandlerInterceptor或者HandlerInterceptorAdapter 来替换Filter:

复制代码
public class WeiXinInterceptor implements HandlerInterceptor {
    @Autowired
    private UsersService usersService;   
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // TODO Auto-generated method stub
        
    }
}
复制代码

配置拦截路径:

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="net.xxxx.interceptor.WeiXinInterceptor" />
        </mvc:interceptor>     
    </mvc:interceptors>

 

Filter 中注入 Service 的示例:

复制代码
public class WeiXinFilter implements Filter{    
    private UsersService usersService;    
    public void init(FilterConfig fConfig) throws ServletException {}
    public WeiXinFilter() {}
    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest)request;
        HttpServletResponse resp = (HttpServletResponse)response;
        
        String userAgent = req.getHeader("user-agent");
        if(userAgent != null && userAgent.toLowerCase().indexOf("micromessenger") != -1){    // 微信浏览器
            String servletPath = req.getServletPath();
            String requestURL = req.getRequestURL().toString();
            String queryString = req.getQueryString();
 
            if(queryString != null){
                if(requestURL.indexOf("mtzs.html") !=-1 && queryString.indexOf("LLFlag")!=-1){
                    req.getSession().setAttribute("LLFlag", "1");
                    chain.doFilter(request, response);
                    return;
                }
            }
            
            String openidDES = CookieUtil.getValueByName("openid", req);
            String openid = null;
            if(StringUtils.isNotBlank(openidDES)){
                try {
                    openid = DesUtil.decrypt(openidDES, "rxxxxxxxxxde");    // 解密获得openid
                } catch (Exception e) {
                    e.printStackTrace();
                }    
            }
            // ... ...
            String[] pathArray = {"/weixin/enterAppFromWeiXin.json", "/weixin/getWeiXinUserInfo.json",
                                    "/weixin/getAccessTokenAndOpenid.json", "/sendRegCode.json", "/register.json", 
                                    "/login.json", "/logon.json", "/dump.json", "/queryInfo.json"};
            List<String> pathList = Arrays.asList(pathArray);
            
            String loginSuccessUrl = req.getParameter("path");
            String fullLoginSuccessUrl = "http://www.axxxxxxx.cn/pc/";
            if(requestURL.indexOf("weixin_gate.html") != -1){
                req.getSession().setAttribute("loginSuccessUrl", loginSuccessUrl);
          // ... ...
            }
            ServletContext sc = req.getSession().getServletContext();
XmlWebApplicationContext cxt = (XmlWebApplicationContext)WebApplicationContextUtils.getWebApplicationContext(sc);
        
            if(cxt != null && cxt.getBean("usersService") != null && usersService == null)
               usersService = (UsersService) cxt.getBean("usersService");
        
            Users users = this.usersService.queryByOpenid(openid);
            // ... ...
            if(pathList.contains(servletPath)){    // pathList 中的访问路径直接 pass 
                chain.doFilter(request, response);
                return;
            }else{
                if(req.getSession().getAttribute(CommonConstants.SESSION_KEY_USER) == null){ // 未登录
                    String llFlag = (String) req.getSession().getAttribute("LLFlag");
                    if(llFlag != null && llFlag.equals("1")){    // 处理游客浏览
                        chain.doFilter(request, response);
                        return;
                    }                  
                    // ... ...// 3. 从腾讯服务器去获得微信的 openid ,
                    req.getRequestDispatcher("/weixin_gate.html").forward(request, response);
                    return;
                }else{    // 已经登录
                    // 4. 已经登录时的处理                    
                    chain.doFilter(request, response); 
                    return;
                }
            }            
        }else{    // 非微信浏览器
            chain.doFilter(request, response);
        }
    }

}
复制代码
分享到:
评论

相关推荐

    特殊情况(ActionForm,Servlet, Filter, Listener)下Spring如何注入对象

    然而,在特定场景如ActionForm、Servlet、Filter、Listener等中,传统的注入方式可能无法正常工作,需要采用特殊的注入手段。 在标题和描述中提到的特殊情况主要涉及ActionForm。ActionForm是Struts1.x的一个概念,...

    Java EE 6 规范手册中英文 chm

    9. **Filter 和 Listener**:在Java EE 6中,Filter和Listener是两个重要的工具,它们可以拦截请求、响应,或监听应用程序的事件,实现诸如日志记录、权限控制等功能。 10. **Annotations**:Java EE 6大力推广使用...

    精通Java EE:精通Java EE 整合应用案例\源代码第五章

    9. **Filter与Listener**:这两者是Java EE中的重要概念,Filter用于在请求到达目标之前或之后执行预处理或后处理,Listener则监听特定的事件。学习者将理解它们如何增强应用程序的功能和性能。 10. **容器管理的...

    java ee教程(电子教案)

    10. **Filter与Listener**:在Java EE中,Filter用于拦截请求并处理,而Listener则监听特定事件,如会话的创建和销毁。 这份Java EE教程将深入讲解这些技术,从基础概念到实际应用,通过实例演示如何使用它们来构建...

    Java Web 整合开发 完全自学手册 源代码

    8. **Filter与Listener**:在Java Web中,Filter用于拦截请求和响应,实现数据过滤、登录检查等功能;Listener则监听Web应用的特定事件,如session的创建、销毁等。掌握这两者的配置和实现。 9. **Web Services**:...

    通过AccessibilityService实现系统按键监听功能

    在Android系统中, AccessibilityService 是一个非常重要的服务,它允许应用程序获取并响应用户与系统交互的事件,包括触摸屏幕、导航键操作等。这为开发者提供了深入用户界面交互的能力,例如辅助功能应用或者一些...

    Java EE 实验室练习代码实操 Java学习资料

    9. **Filter和Listener**:在Java EE中,Filter用于拦截和处理HTTP请求和响应,而Listener监听特定的事件,如会话创建或销毁,用于实现高级功能。 在"java-ee-experiment-master"这个项目中,你可能会找到上述技术...

    java ee5 document

    在Java EE 5中,主要的知识点包括: 1. **JSF (JavaServer Faces) 1.2**:这是Java EE 5中的用户界面组件模型,提供了创建交互式Web界面的框架。JSF 1.2引入了更多的内置组件,支持Ajax功能,以及对Faces Config...

    Java Web从入门到精通_PPT

    4. **MVC模式**:Model-View-Controller模式在Java Web开发中广泛使用,用于分离业务逻辑、数据模型和用户界面。 5. **Java EE组件**:如EJB(Enterprise JavaBeans)、JMS(Java Message Service)、JTA(Java ...

    Java EE 基础代码 Java学习资料

    9. **过滤器(Filter)和监听器(Listener)**:在Java EE中,过滤器可以拦截请求和响应,实现预处理或后处理功能,如登录检查、数据格式转换等。监听器则用于监听Web应用中特定事件的发生,如会话创建、销毁等。 ...

    java EE水果管理系统 Java学习资料

    9. **过滤器(Filter)和监听器(Listener)**:在Java EE中,这两个概念用于增强应用程序的功能,比如登录验证、字符编码转换等。 10. **安全性**:Java EE提供了一系列的安全特性,如角色基础的访问控制(RBAC)...

    java ee api 帮助文档

    6. **JMS(Java Message Service)**:JMS定义了在Java应用程序间交换消息的API,支持点对点和发布/订阅两种消息模式,常用于异步通信和解耦系统组件。 7. **JSF(JavaServer Faces)**:JSF是一个用于构建用户界面...

    Java EE API 中英文对照

    在Java EE API中,你可以找到以下核心组件和接口的详细说明: 1. **Servlet**:Servlet是Java EE中的基础组件,用于处理HTTP请求。Servlet API提供了Servlet和Filter接口,它们分别用于处理请求和实现过滤逻辑。...

    Java Web开发实践教程 课件

    6. **过滤器(Filter)**: 过滤器在Java Web应用中用于拦截请求和响应,实现预处理或后处理功能,比如登录验证、字符编码转换等。学习过滤器涉及理解Filter接口和过滤链。 7. **监听器(Listener)**: 监听器是用来...

    java导购代码

    接口在Java中是定义行为的蓝图,它不包含具体实现,但规定了类或对象必须遵循的方法。在导购应用中,可能会有如`IGoodsRecommendation`这样的接口,其中定义了`recommendProducts()`方法,用于根据用户的浏览历史、...

    JAVA_EE_api_中英文对照版

    以上每个部分在Java EE API文档中都会有详细的接口定义、方法说明、示例代码以及最佳实践指导。无论是初学者还是经验丰富的开发者,都能从中受益匪浅。通过深入学习和理解这些API,开发者可以更好地掌握Java EE平台...

    spring根据controller中接收请求参数不同走不同service的实现方法

    在Controller中,注入`serviceProviders`列表。当收到请求时,遍历这个列表,调用每个Service的`support`方法来判断是否处理当前请求。如果支持,就调用`execute`方法执行业务逻辑。这个过程可以通过Java 8的Stream...

    Java Web 大作业.zip

    9. **Filter和Listener**:在Java Web中,Filter用于拦截请求和响应,实现如登录验证、日志记录等功能;Listener监听各种Web事件,如会话创建、销毁等。 10. **Spring框架**:Spring是Java Web开发中的主流框架,...

    《Java.Web开发详解》的源代码

    《Java.Web开发详解》是一本深入探讨Java在Web开发中的应用的专业书籍,其源代码提供了丰富的实例和练习,帮助读者更好地理解和实践所学知识。在本文中,我们将深入解析这些源代码,探讨其中的关键知识点,旨在提升...

    spring MVC所需jar包和filter的配置

    在Spring MVC中,常见的Filter包括字符编码Filter、登录验证Filter等。 - `CharacterEncodingFilter`:确保请求和响应的字符编码一致,防止乱码问题。配置示例: ```xml &lt;filter&gt; &lt;filter-name&gt;...

Global site tag (gtag.js) - Google Analytics