傳智:自己簡單實現一個struts2框架的demo
阿新 • • 發佈:2017-08-06
throws for request 運行 本地化 color ray run main
struts2的結構圖:
代碼實現:
組織結構:
主要代碼:
package cn.itcast.config; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; importjava.util.List; import java.util.Map; /** * Created by zhen on 2017-08-04. * 讀取struts.xml配置信息 */ public class ConfigurationManager { private static final Logger logger = Logger.getLogger(ConfigurationManager.class); //讀取Interceptor public static List<String> getInterceptors(){ List<String> interceptors = null; SAXReader saxReader = new SAXReader(); InputStream inputStream = ConfigurationManager.class.getResourceAsStream("/struts.xml"); Document document = null; try { document = saxReader.read(inputStream); } catch (DocumentException e) { logger.error(e.getMessage());throw new RuntimeException("配置文件解析異常" ,e); } String xpath = "//interceptor"; List<Element> list = document.selectNodes(xpath); if(list != null && list.size() > 0){ interceptors = new ArrayList<String>(); for(Element ele: list){ String className = ele.attributeValue("class"); interceptors.add(className); } } return interceptors; } //讀取Constant public static String getConstant(String name){ String value = null; SAXReader saxReader = new SAXReader(); InputStream is = ConfigurationManager.class.getResourceAsStream("/struts.xml"); Document document = null; try { document = saxReader.read(is); } catch (DocumentException e) { logger.error(e.getMessage()); throw new RuntimeException("配置文件解析異常" ,e); } String xPath = "//constant[@name=‘" + name + "‘]"; List<Element> ele = document.selectNodes(xPath); if(ele != null && ele.size() > 0){ value = ele.get(0).attributeValue("value"); } return value; } //讀取Action public static Map<String, ActionConfig> getActions(){ Map<String, ActionConfig> actions = null; SAXReader saxReader = new SAXReader(); InputStream is = ConfigurationManager.class.getResourceAsStream("/struts.xml"); Document document = null; try { document = saxReader.read(is); } catch (DocumentException e) { logger.error(e.getMessage()); throw new RuntimeException("配置文件解析異常" ,e); } String xPath = "//action"; List<Element> list = document.selectNodes(xPath); if(list != null && list.size() > 0){ actions = new HashMap<String, ActionConfig>(); for(Element element : list){ ActionConfig actionConfig = new ActionConfig(); String name = element.attributeValue("name"); String method = element.attributeValue("method"); String className = element.attributeValue("class"); Map<String, String> results = null; List<Element> resultElements = element.elements("result"); if(resultElements != null && resultElements.size() > 0){ results = new HashMap(); for(Element ele: resultElements){ String resultName = ele.attributeValue("name"); String resultValue = ele.getTextTrim(); results.put(resultName, resultValue); } } actionConfig.setName(name); actionConfig.setMethod(method == null || method.trim().equals("") ? "execute" : method.trim()); actionConfig.setClassName(className); actionConfig.setResults(results); actions.put(name, actionConfig); } } return actions; } }
package cn.itcast.invocation; import cn.itcast.config.ActionConfig; import cn.itcast.context.ActionContext; import cn.itcast.interceptor.Interceptor; import org.apache.log4j.Logger; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Created by zhen on 2017-08-06. */ public class ActionInvocation { private static final Logger logger = Logger.getLogger(ActionInvocation.class); private Iterator<Interceptor> interceptors; private Object action; private ActionConfig actionConfig; private ActionContext actionContext; private String resultUrl; public ActionContext getActionContext() { return actionContext; } public ActionInvocation(List<String> classNames, ActionConfig actionConfig, HttpServletRequest request, HttpServletResponse response){ //裝載Interceptor鏈 if(classNames != null && classNames.size() > 0){ List<Interceptor> interceptorList = new ArrayList<Interceptor>(); for(String className : classNames){ try { Interceptor interceptor = (Interceptor) Class.forName(className).newInstance(); interceptor.init(); interceptorList.add(interceptor); } catch (Exception e) { logger.error(e.getMessage()); throw new RuntimeException("創建Interceptor失敗,Interceptor Name:" + className ,e); } } interceptors = interceptorList.iterator(); } //準備action實例 this.actionConfig = actionConfig; try { action = Class.forName(actionConfig.getClassName()).newInstance(); } catch (Exception e) { logger.error(e.getMessage()); throw new RuntimeException("創建Action實例失敗!" + actionConfig.getClass(), e); } //準備數據中心 actionContext = new ActionContext(request, response, action); } public String invoke(){ if(interceptors != null && interceptors.hasNext() && resultUrl == null){ Interceptor interceptor = interceptors.next(); resultUrl = interceptor.invoke(this); }else{ try{ Method executeMethod = Class.forName(actionConfig.getClassName()).getMethod(actionConfig.getMethod()); resultUrl = (String) executeMethod.invoke(action); }catch(Exception ex){ logger.error(ex.getMessage()); throw new RuntimeException("您配置的action方法不存在" + actionConfig.getClassName()); } } return resultUrl; } }
package cn.itcast.filter; import cn.itcast.config.ActionConfig; import cn.itcast.config.ConfigurationManager; import cn.itcast.context.ActionContext; import cn.itcast.invocation.ActionInvocation; import org.apache.log4j.Logger; import org.junit.Test; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; import java.util.Map; /** * Created by zhen on 2017-08-06. */ public class StrutsPrepareAndExecuteFilter implements Filter { private static final Logger logger = Logger.getLogger(StrutsPrepareAndExecuteFilter.class); private List<String> interceptorClassNames; private String extension; private Map<String, ActionConfig> actionConfigs; public void init(FilterConfig filterConfig) throws ServletException { //裝載配置信息 interceptorClassNames = ConfigurationManager.getInterceptors(); extension = ConfigurationManager.getConstant("struts.action.extension"); actionConfigs = ConfigurationManager.getActions(); } public static void main(String[] args){ Logger logger = Logger.getLogger(StrutsPrepareAndExecuteFilter.class); } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //執行 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String urlPath = request.getRequestURI(); if(!urlPath.endsWith(extension)){ filterChain.doFilter(request, response); return; } String actionName = urlPath.substring(urlPath.lastIndexOf("/") + 1).replace("." + extension, ""); ActionConfig actionConfig = actionConfigs.get(actionName); if(actionConfig == null){ throw new RuntimeException("找不到對應的action!" + actionName); } ActionInvocation actionInvocation = new ActionInvocation(interceptorClassNames, actionConfig, request, response); String result = actionInvocation.invoke(); String dispatcherPath = actionConfig.getResults().get(result); if(dispatcherPath == null || "".equals(dispatcherPath)){ throw new RuntimeException("找不到對應的返回路徑!"); } request.getRequestDispatcher(dispatcherPath).forward(request, response); ActionContext.tl.remove(); } public void destroy() { } }
寫後感想:
struts2模擬 1、關註點分離思想。類似java中的解耦合,插拔。將功能拆分成各個攔截器實現。攔截器運行過程中拼接出想要的功能。 2、MVC思想。 filter-C Action-M jsp_url-V 需要掌握知識: XML解析,Xpath表達式(dom4j) Servlet技術 java內省(BeanUtils) ThreadLocal線程本地化類 遞歸調用 需要補充的知識: dom4j解析 xpath語法 獲取資源文件路徑 理解: 對於值棧的模擬不要拘泥於數組,也可以使用現有的類進行封裝,比如使用ArrayList模擬。 經常遞歸調用使用的局部變量可以放在循環外或者說是方法外。
項目路徑:
https://github.com/gzdx/MyStruts2.git
傳智:自己簡單實現一個struts2框架的demo