struts2 实现原理解析,这个在网络上面应该很多。本来打算自己看了来写博客,发现自己对源码的研究还是缺一点实力,后来借组网络的笔记把核心的实现看了一下。这里就直接把一篇感觉不错的解析贴出来。感觉这些ssh虽然已经被烂大街但是他们的源码其实不是那么好看懂,最少比那些工具类的源码难一点,可能我接触的源码还不多吧。
struts2 操作 action servlet,是通过在web.xml中配置一个filter实现的
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
而这个Filter FilterDispatcher 实际做了下列工作
public class FilterDispatcher implements StrutsStatics, Filter
public void init(FilterConfig filterConfig) throws ServletException { dispatcher = createDispatcher(filterConfig); ... } protected Dispatcher createDispatcher(FilterConfig filterConfig) { ... return new Dispatcher(filterConfig.getServletContext(), params); }
<span style="background-color: rgb(255, 255, 255); color: rgb(70, 70, 70); font-family: simsun; font-size: 14px; line-height: 21px;"> </span>
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; ServletContext servletContext = getServletContext(); .... dispatcher.serviceAction(request, response, servletContext, mapping); }
Dispatcher对象是Struts2的核心操作对象,它主要实现实现了下面的工作
public class Dispatcher { private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>(); //Store the dispatcher instance for this thread. public static void setInstance(Dispatcher instance) { Dispatcher.instance.set(instance); // Tie the ObjectFactory threadlocal instance to this Dispatcher instance if (instance != null) { Container cont = instance.getContainer(); if (cont != null) { ObjectFactory.setObjectFactory(cont.getInstance(ObjectFactory.class)); } else { LOG.warn("This dispatcher instance doesn't have a container, so the object factory won't be set."); } } else { ObjectFactory.setObjectFactory(null); } } //Provide the dispatcher instance for the current thread. public static Dispatcher getInstance() { return instance.get(); }
private ServletContext servletContext; private Map<String, String> initParams; public Dispatcher(ServletContext servletContext, Map<String, String> initParams) { this.servletContext = servletContext; this.initParams = initParams; }
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping) throws ServletException { Map<String, Object> extraContext = createContextMap(request, response, mapping, context); // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); if (stack != null) { extraContext.put(ActionContext.VALUE_STACK, ValueStackFactory.getFactory().createValueStack(stack)); } try { String namespace = mapping.getNamespace(); String name = mapping.getName(); String method = mapping.getMethod(); Configuration config = configurationManager.getConfiguration(); ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(