一直想寫Struts2的底層實現,醞釀了兩個星期,今天把它實現。
首先,我們在運用的時候都會使用action,實現跳轉,下面我們寫一個UserAction:
public class UserAction { public String toAddUser(){ return "success"; } public String addUser(){ return "adduser"; }}
我們在使用Struts2的時候,一個很重要的設定檔是:struts.xml,因此我們需要讀取它,知道他裡面的內容,java解析xml我寫過了一篇文章,可以去看看。
下面我們寫一個設定檔:
<?xml version="1.0" encoding="UTF-8"?><struts> <package name="user" namespace="/user" > <action name="userAction" class="actions.UserAction" > <result name="success">/success.jsp</result> <result name="adduser">/addUser.jsp</result> </action> </package></struts>
之後我們就需要去讀取這個設定檔,但是之前我們需要我們需要建立幾個實體類去儲存這些元素,由外到內排列:
1.package的實體類
import java.util.List;public class PackageEntity { private String name; private String namespace; private List<ActionEntity> actions; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNamespace() { return namespace; } public void setNamespace(String namespace) { this.namespace = namespace; } public List<ActionEntity> getActions() { return actions; } public void setActions(List<ActionEntity> actions) { this.actions = actions; }}
private List<ActionEntity> actions;是吧action實體類的內容放到package中。
2.action的實體類
import java.util.List;public class ActionEntity { private String name; private String classname; private List<ResultEntity> results; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassname() { return classname; } public void setClassname(String classname) { this.classname = classname; } public List<ResultEntity> getResults() { return results; } public void setResults(List<ResultEntity> results) { this.results = results; }}
private List<ResultEntity> results;是把result的實體類放到action中。
3.result的實體類
public class ResultEntity { private String name; private String page; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPage() { return page; } public void setPage(String page) { this.page = page; }}
page是指後面的jsp。
經過兩個list就把設定檔中所有的元素集中到package中,便於下面的跳轉。
下面寫一個配置的工具類:
public class ConfigUtils {//new一個package的對象,便於調用元素 public static PackageEntity pe=new PackageEntity(); public static void config(){ SAXReader reader=new SAXReader(); try { //讀取struts.xml Document doc=reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("struts.xml")); //讀取根項目 Element root=doc.getRootElement(); //得到根項目下的節點元素 Element packageElement=root.element("package"); List<ActionEntity> actions=new ArrayList<ActionEntity>(); pe.setName(packageElement.attributeValue("name")); pe.setNamespace(packageElement.attributeValue("namespace")); //得到根項目下的節點元素 List<Element> listActions=packageElement.elements("action"); for(Element actionElement:listActions){ ActionEntity ae=new ActionEntity(); //得到子節點 ae.setName(actionElement.attributeValue("name")); ae.setClassname(actionElement.attributeValue("class")); //得到根項目下的節點元素 List<Element> resultElements=actionElement.elements("result"); List<ResultEntity> results=new ArrayList<ResultEntity>(); for(Element resultEle:resultElements){ ResultEntity re=new ResultEntity(); //得到子節點 re.setName(resultEle.attributeValue("name")); re.setPage(resultEle.getText()); results.add(re); } ae.setResults(results); actions.add(ae); } pe.setActions(actions); } catch (DocumentException e) { e.printStackTrace(); } }}
寫一個index.jsp,為了寫跳轉連結進行驗證:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>首頁</title> </head> <body> <a href="<%=path%>/user/userAction!toAddUser.action">跳轉</a> <br/> <a href="<%=path%>/user/userAction!addUser.action">添加使用者</a> </body></html>
跳轉是跳到到success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'success.jsp' starting page</title> </head> <body> This is my JSP page. <br> 成功了 </body></html>
添加使用者是跳到adduser.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <title>My JSP 'addUser.jsp' starting page</title> </head> <body> This is my JSP page. <br> 添加使用者了 </body></html>
寫好了jsp之後我們就要過濾這些串連,進行跳轉,寫一個struts2的過濾器:
public class StrutsFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)req; String path=request.getServletPath(); System.out.println(path); String[] pathArr=path.split("/"); String namespace=pathArr[1]; String actionString=pathArr[2]; String actionname=actionString.split("!")[0]; String methodname=actionString.split("!")[1].split("\\.")[0]; System.out.println(actionname+":"+methodname); PackageEntity pe=ConfigUtils.pe; List<ActionEntity> actions=pe.getActions(); ActionEntity doAction=null; for(ActionEntity ae:actions){ if(ae.getName().equals(actionname)){ doAction=ae; break; } } try { Class actioncls=Class.forName(doAction.getClassname()); Object actionObj=actioncls.newInstance(); Class cls=actionObj.getClass(); Method actionMethod=cls.getDeclaredMethod(methodname); String resultValue=(String)actionMethod.invoke(actionObj,null); List<ResultEntity> results=doAction.getResults(); ResultEntity re=null; for(ResultEntity result:results){ if(resultValue.equals(result.getName())){ re=result; break; } } request.getRequestDispatcher(re.getPage()).forward(request, res); } catch (Exception e) { e.printStackTrace(); } } @Override public void init(FilterConfig filterConfig) throws ServletException { ConfigUtils.config(); }}
下面建立一個web的過濾器測試一下:
import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request=(HttpServletRequest)req; HttpServletResponse response=(HttpServletResponse)res; request.getRequestDispatcher("/success.jsp").forward(request,response); } @Overridepublic void init(FilterConfig filterConfig) throws ServletException { }}
建立一個web的servlet測試一下:
import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TestServlet extends HttpServlet {public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{request.getRequestDispatcher("/success.jsp").forward(request, response); }}
別忘了把解析xml的包導進去。
希望對你們理解架構有協助!!!
本文出自 “java專題” 部落格,請務必保留此出處http://7915791.blog.51cto.com/7905791/1350348