在项目中遇到一个问题,在 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等中,传统的注入方式可能无法正常工作,需要采用特殊的注入手段。 在标题和描述中提到的特殊情况主要涉及ActionForm。ActionForm是Struts1.x的一个概念,...
9. **Filter 和 Listener**:在Java EE 6中,Filter和Listener是两个重要的工具,它们可以拦截请求、响应,或监听应用程序的事件,实现诸如日志记录、权限控制等功能。 10. **Annotations**:Java EE 6大力推广使用...
在Android系统中, AccessibilityService 是一个非常重要的服务,它允许应用程序获取并响应用户与系统交互的事件,包括触摸屏幕、导航键操作等。这为开发者提供了深入用户界面交互的能力,例如辅助功能应用或者一些...
9. **Filter与Listener**:这两者是Java EE中的重要概念,Filter用于在请求到达目标之前或之后执行预处理或后处理,Listener则监听特定的事件。学习者将理解它们如何增强应用程序的功能和性能。 10. **容器管理的...
10. **Filter与Listener**:在Java EE中,Filter用于拦截请求并处理,而Listener则监听特定事件,如会话的创建和销毁。 这份Java EE教程将深入讲解这些技术,从基础概念到实际应用,通过实例演示如何使用它们来构建...
8. **Filter与Listener**:在Java Web中,Filter用于拦截请求和响应,实现数据过滤、登录检查等功能;Listener则监听Web应用的特定事件,如session的创建、销毁等。掌握这两者的配置和实现。 9. **Web Services**:...
9. **Filter和Listener**:在Java EE中,Filter用于拦截和处理HTTP请求和响应,而Listener监听特定的事件,如会话创建或销毁,用于实现高级功能。 在"java-ee-experiment-master"这个项目中,你可能会找到上述技术...
在Java EE 5中,主要的知识点包括: 1. **JSF (JavaServer Faces) 1.2**:这是Java EE 5中的用户界面组件模型,提供了创建交互式Web界面的框架。JSF 1.2引入了更多的内置组件,支持Ajax功能,以及对Faces Config...
4. **MVC模式**:Model-View-Controller模式在Java Web开发中广泛使用,用于分离业务逻辑、数据模型和用户界面。 5. **Java EE组件**:如EJB(Enterprise JavaBeans)、JMS(Java Message Service)、JTA(Java ...
9. **过滤器(Filter)和监听器(Listener)**:在Java EE中,过滤器可以拦截请求和响应,实现预处理或后处理功能,如登录检查、数据格式转换等。监听器则用于监听Web应用中特定事件的发生,如会话创建、销毁等。 ...
9. **过滤器(Filter)和监听器(Listener)**:在Java EE中,这两个概念用于增强应用程序的功能,比如登录验证、字符编码转换等。 10. **安全性**:Java EE提供了一系列的安全特性,如角色基础的访问控制(RBAC)...
6. **JMS(Java Message Service)**:JMS定义了在Java应用程序间交换消息的API,支持点对点和发布/订阅两种消息模式,常用于异步通信和解耦系统组件。 7. **JSF(JavaServer Faces)**:JSF是一个用于构建用户界面...
在Java EE API中,你可以找到以下核心组件和接口的详细说明: 1. **Servlet**:Servlet是Java EE中的基础组件,用于处理HTTP请求。Servlet API提供了Servlet和Filter接口,它们分别用于处理请求和实现过滤逻辑。...
6. **过滤器(Filter)**: 过滤器在Java Web应用中用于拦截请求和响应,实现预处理或后处理功能,比如登录验证、字符编码转换等。学习过滤器涉及理解Filter接口和过滤链。 7. **监听器(Listener)**: 监听器是用来...
在Controller中,注入`serviceProviders`列表。当收到请求时,遍历这个列表,调用每个Service的`support`方法来判断是否处理当前请求。如果支持,就调用`execute`方法执行业务逻辑。这个过程可以通过Java 8的Stream...
接口在Java中是定义行为的蓝图,它不包含具体实现,但规定了类或对象必须遵循的方法。在导购应用中,可能会有如`IGoodsRecommendation`这样的接口,其中定义了`recommendProducts()`方法,用于根据用户的浏览历史、...
以上每个部分在Java EE API文档中都会有详细的接口定义、方法说明、示例代码以及最佳实践指导。无论是初学者还是经验丰富的开发者,都能从中受益匪浅。通过深入学习和理解这些API,开发者可以更好地掌握Java EE平台...
9. **Filter和Listener**:在Java Web中,Filter用于拦截请求和响应,实现如登录验证、日志记录等功能;Listener监听各种Web事件,如会话创建、销毁等。 10. **Spring框架**:Spring是Java Web开发中的主流框架,...
《Java.Web开发详解》是一本深入探讨Java在Web开发中的应用的专业书籍,其源代码提供了丰富的实例和练习,帮助读者更好地理解和实践所学知识。在本文中,我们将深入解析这些源代码,探讨其中的关键知识点,旨在提升...
在Spring MVC中,常见的Filter包括字符编码Filter、登录验证Filter等。 - `CharacterEncodingFilter`:确保请求和响应的字符编码一致,防止乱码问题。配置示例: ```xml <filter> <filter-name>...