It took me a while, but I got a refreshable Spring web context to work! It wasn't too hard, but I was hoping it would be easier.
The biggest problem I faced was that the venerable DispatcherServlet initializes member variables based on the ApplicationContext that it creates. I created a hacky subclass to get around this problem:
I then use that dispatcher servlet in a "refreshing" controller:
It's hacky but it works for my needs . I prevously would have to bounce my Web's Fear application context which takes 2-5 minutes. It also saves JSP recompilations which take quite a while in our setup... The DispatcherServlet reloading taks 10 seconds. The top level app context + the DispatcherServlet context takes 30 seconds.
We have a huge system with lots of dependencies and a beast of a development environment. I'll be thinking about modularization and speed ups, including some potentially neat Spring tricks...
来自:http://www.jroller.com/Solomon/entry/reloading_a_spring_web_application
The biggest problem I faced was that the venerable DispatcherServlet initializes member variables based on the ApplicationContext that it creates. I created a hacky subclass to get around this problem:
public class RefreshableDispatcherServlert extends DispatcherServlet {
public static final String SERVLET_ATTRIBUTE_NAME = RefreshableDispatcherServlert.class
.getName()
+ "_SERVLET_ATTRIB";
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache)
throws Exception {
RequestContextHolder.getRequestAttributes().setAttribute(getClass().getName(), this,
RequestAttributes.SCOPE_REQUEST);
return super.getHandler(request, cache);
}
}
I then use that dispatcher servlet in a "refreshing" controller:
public class RefreshingController implements Controller, ApplicationContextAware {
private ApplicationContext applicationContext;
private Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception {
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
refresh(response, request, configurableApplicationContext);
return null;
}
private void refresh(HttpServletResponse response, HttpServletRequest request,
ConfigurableApplicationContext context) throws IOException, ServletException {
long start = System.currentTimeMillis();
log(response, "refreshing context");
refreshParent(response, request, context, start);
refreshServlet();
log(response, "refreshed servlet in " + (System.currentTimeMillis() - start) + " ms.");
}
private void refreshParent(HttpServletResponse response, HttpServletRequest request,
ConfigurableApplicationContext context, long start) throws IOException {
ConfigurableApplicationContext parent = (ConfigurableApplicationContext) context
.getParent();
if (parent != null && "true".equals(request.getParameter("reloadParent"))) {
parent.refresh();
log(response, "refreshed parent in " + (System.currentTimeMillis() - start) + "ms");
}
}
private void refreshServlet() throws ServletException {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
String key = RefreshableDispatcherServlert.SERVLET_ATTRIBUTE_NAME;
DispatcherServlet servlet = (DispatcherServlet) requestAttributes.getAttribute(key,
RequestAttributes.SCOPE_REQUEST);
servlet.init();
}
private void log(HttpServletResponse response, String string) throws IOException {
log(string, response.getWriter());
}
private void log(String string, PrintWriter writer) {
logger.info(string);
writer.write(string);
writer.write("");
writer.flush();
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
It's hacky but it works for my needs . I prevously would have to bounce my Web's Fear application context which takes 2-5 minutes. It also saves JSP recompilations which take quite a while in our setup... The DispatcherServlet reloading taks 10 seconds. The top level app context + the DispatcherServlet context takes 30 seconds.
We have a huge system with lots of dependencies and a beast of a development environment. I'll be thinking about modularization and speed ups, including some potentially neat Spring tricks...
来自:http://www.jroller.com/Solomon/entry/reloading_a_spring_web_application