之前的博客介绍了spring mvc里child WebApplicationContext和root ApplicationContext的关系,以及获取方式。最近我遇到了一个问题:按照之前的博客,无法获取child WebApplicationContext。场景是这样的:spring mvc只拦截特定路径的url,web.xml中配置如下:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/spring-dispatcher.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/mvc/*</url-pattern>
</servlet-mapping>
项目还提供了一个外部的servlet,给别的子系统调用,这个servlet不在spring mvc拦截路径范围内。
<servlet>
<servlet-name>none</servlet-name>
<servlet-class>net.aty.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>none</servlet-name>
<url-pattern>/test.do</url-pattern>
</servlet-mapping>
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = -2931357660081416782L;
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
WebApplicationContext context = (WebApplicationContext) request
.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
System.out.println("context==null: " + (context==null));//true
}
}
我们在这个servlet里面不能获取到spring mvc的WebApplicationContext。我猜测原因是:我们的请求没有经过spring拦截,spring没有将child WebApplicationContext塞入到request对象中。
目前没有想到特别好的解决方式,使用了spring框架的ApplicationContextAware接口,将其存到全局变量中。
@Controller
public class FirstController implements ApplicationContextAware{
@Autowired
private MyService service;
@Autowired
private HttpServletRequest request;
@RequestMapping("/mvc/first/hello.do")
@ResponseBody
public String hello(@RequestParam("userName") String userName) {
return service.process(userName);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
System.out.println("...........");
SpringMvcContextUtils.setApplicationContext(applicationContext);
}
}
public class SpringMvcContextUtils {
private static volatile ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static void setApplicationContext(
ApplicationContext applicationContext) {
SpringMvcContextUtils.applicationContext = applicationContext;
}
}
这样在外部的servlet中就可以拿到child容器了:
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = -2931357660081416782L;
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
ApplicationContext another = SpringMvcContextUtils.getApplicationContext();
}
}