摘要:現(xiàn)在,我們使用了的話,那么框架內(nèi)部就能幫我們封裝了。每個(gè)中都有和這樣的方法,沒(méi)必要的。我們抽取出來(lái),通過(guò)配置文件來(lái)把這兩個(gè)方法替換掉,那么我們的程序就會(huì)更加優(yōu)雅了。于是乎,就應(yīng)運(yùn)而生了。因此,學(xué)習(xí)的時(shí)候,不了解是沒(méi)有任何關(guān)系的。
前言
這是Strtus的開(kāi)山篇,主要是引入struts框架...為什么要引入struts,引入struts的好處是什么,以及對(duì)Struts2一個(gè)簡(jiǎn)單的入門(mén)....
為什么要引入struts?既然Servlet能夠完成的事,我們?yōu)樯兑每蚣苣兀浚?/p>
框架幫我們封裝了很多常用的功能
把Web帶過(guò)來(lái)的參數(shù)自動(dòng)封裝到JavaBean中[以前,我們剛開(kāi)始學(xué)的時(shí)候是單個(gè)單個(gè)來(lái)獲取參數(shù)的,后來(lái)我們又使用了BeanUtils寫(xiě)工具方法來(lái)幫我們封裝]。現(xiàn)在,我們使用了Struts2的話,那么框架內(nèi)部就能幫我們封裝了。
更加靈活[不用把路徑等信息寫(xiě)死在程序上],對(duì)于路徑我們使用配置文件來(lái)進(jìn)行管理,如果目錄發(fā)生了變化,也不用一個(gè)一個(gè)去修改每個(gè)程序的路徑。
每個(gè)Servlet中都有doGet和doPost這樣的方法,沒(méi)必要的。我們抽取出來(lái),通過(guò)配置文件來(lái)把這兩個(gè)方法替換掉,那么我們的程序就會(huì)更加優(yōu)雅了。
于是乎,struts2就應(yīng)運(yùn)而生了。
自定義struts在正式講解struts之前,我們來(lái)看一下,以我們現(xiàn)在的水平,能夠怎么優(yōu)化它。。
以用戶的登陸注冊(cè)案例來(lái)進(jìn)行說(shuō)明
傳統(tǒng)的用戶登陸注冊(cè)dao
public class UserDao { public User login(User user) { if ("aaa".equals(user.getUsername()) && "123".equals(user.getPsd())) { System.out.println("登陸成功!"); return user; } else { System.out.println("登陸失敗!"); return null; } } public void register(User user) { System.out.println("注冊(cè)成功!" + user.getUsername()); } }
service
public class UserService { private UserDao userDao = new UserDao(); public User longin(User user) { return userDao.login(user); } public void register(User user) { userDao.register(user); } }
loginServlet
@javax.servlet.annotation.WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet") public class LoginServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到用戶帶過(guò)來(lái)的數(shù)據(jù),封裝到Bean對(duì)象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調(diào)用Service方法 UserService userService = new UserService(); userService.longin(user); //登陸成功跳轉(zhuǎn)到首頁(yè) request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); //登陸失敗,跳轉(zhuǎn)到相關(guān)的提示頁(yè)面 request.setAttribute("message","登陸失敗了!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }
registerServlet
@javax.servlet.annotation.WebServlet(name = "RegisterServlet",urlPatterns = "/RegisterServlet") public class RegisterServlet extends javax.servlet.http.HttpServlet { protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到用戶帶過(guò)來(lái)的數(shù)據(jù),封裝到Bean對(duì)象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調(diào)用Service方法 UserService userService = new UserService(); userService.register(user); //注冊(cè)成功跳轉(zhuǎn)到登陸界面 request.getRequestDispatcher("/login.jsp").forward(request, response); //注冊(cè)成功,我也可以跳轉(zhuǎn)到首頁(yè) //request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); //注冊(cè)失敗,跳轉(zhuǎn)到相關(guān)的提示頁(yè)面 request.setAttribute("message","注冊(cè)失敗了!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); } } protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { this.doPost(request, response); } }
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>$Title$
register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>$Title$
上面的代碼已經(jīng)經(jīng)過(guò)了測(cè)試,是可以跑起來(lái)的。
①:跳轉(zhuǎn)頁(yè)面的路徑是寫(xiě)死的。我在注冊(cè)成功了以后,我可以跳轉(zhuǎn)到首頁(yè)上,也可以跳轉(zhuǎn)到登陸的界面上。如果我要選擇其中的一個(gè),就必須修改源代碼...
②:一個(gè)功能對(duì)應(yīng)一個(gè)Servlet,太麻煩了...寫(xiě)了LoginServlet,還要寫(xiě)RegisterServlet....
新型的用戶登陸注冊(cè)我們會(huì)發(fā)現(xiàn),無(wú)論什么Servlet上最終還是跳轉(zhuǎn)到相對(duì)應(yīng)的JSP頁(yè)面的...也就是說(shuō),第一和第二步驟【封裝數(shù)據(jù)、調(diào)用Service】我們可以封裝起來(lái)...只要返回uri給Servlet跳轉(zhuǎn)到JSP頁(yè)面就好了。
LoginAction返回的uri分兩種情況:
如果是轉(zhuǎn)發(fā),那么返回的是RequestDispatcher對(duì)象
如果是重定向,那么返回的是字符串
/** * Created by ozc on 2017/4/26. ** 一個(gè)Action對(duì)應(yīng)一個(gè)Servlet,Action負(fù)責(zé)處理具體的請(qǐng)求 */ public class LoginAction { public Object login(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { Object uri ; //得到用戶帶過(guò)來(lái)的數(shù)據(jù),封裝到Bean對(duì)象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調(diào)用Service方法 UserService userService = new UserService(); userService.longin(user); //登陸成功跳轉(zhuǎn)到首頁(yè) request.getSession().setAttribute("user", user); //跳轉(zhuǎn)到首頁(yè)的時(shí)候需要重定向 //response.sendRedirect(request.getContextPath() + "/index.jsp"); //如果是重定向,那么返回的是字符串 uri = "/index.jsp"; return uri; } catch (Exception e) { e.printStackTrace(); //登陸失敗,跳轉(zhuǎn)到相關(guān)的提示頁(yè)面 request.setAttribute("message","登陸失敗了!!!"); //request.getRequestDispatcher("/message.jsp").forward(request, response); //如果是轉(zhuǎn)發(fā),那么返回的是RequestDispatcher對(duì)象 uri = request.getRequestDispatcher("/message.jsp"); return uri; } } }
LoginServlet就可以寫(xiě)成這樣了:
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到LoginAction對(duì)象 LoginAction loginAction = new LoginAction(); Object uri = loginAction.login(request, response); //是重定向 if (uri instanceof String) { response.sendRedirect(request.getContextPath() + uri); } else { //是轉(zhuǎn)發(fā),強(qiáng)轉(zhuǎn)成是RequestDispatcher對(duì)象 ((RequestDispatcher) uri).forward(request, response); } }RegisterAction
RegisterAction
/** * Created by ozc on 2017/4/26. * * 一個(gè)Action對(duì)應(yīng)一個(gè)Servlet,Action負(fù)責(zé)處理具體的請(qǐng)求 */ public class RegisterAction { public Object register(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { Object uri ; //得到用戶帶過(guò)來(lái)的數(shù)據(jù),封裝到Bean對(duì)象中 String username = request.getParameter("username"); String psd = request.getParameter("psd"); User user = new User(); user.setPsd(psd); user.setUsername(username); try { //調(diào)用Service方法 UserService userService = new UserService(); userService.register(user); //登陸成功跳轉(zhuǎn)到登陸頁(yè)面 uri = request.getRequestDispatcher("/login.jsp"); return uri; } catch (Exception e) { e.printStackTrace(); //注冊(cè)失敗,跳轉(zhuǎn)到相關(guān)的提示頁(yè)面 request.setAttribute("message","注冊(cè)失敗了!!!"); //request.getRequestDispatcher("/message.jsp").forward(request, response); uri = request.getRequestDispatcher("/message.jsp"); return uri; } } }
RegisterServlet
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException { //得到RegisterAction RegisterAction registerAction = new RegisterAction(); Object uri = registerAction.register(request, response); //是重定向 if (uri instanceof String) { response.sendRedirect(request.getContextPath() + uri); } else { //是轉(zhuǎn)發(fā),強(qiáng)轉(zhuǎn)成是RequestDispatcher對(duì)象 ((RequestDispatcher) uri).forward(request, response); } }思考
到目前為止,我們搞了兩個(gè)Action類(lèi)來(lái)封裝Servlet的邏輯代碼,我們?cè)俅慰椿豐ervlet的代碼。
可以很清楚地發(fā)現(xiàn):兩個(gè)實(shí)現(xiàn)不同功能的Servlet僅僅是調(diào)用的Action不同....如果是僅僅調(diào)用的Action不同【通過(guò)反射來(lái)調(diào)用不同的Action】,那么我們應(yīng)該想到使用一個(gè)Servlet來(lái)管理整個(gè)項(xiàng)目,也就是說(shuō):整個(gè)web項(xiàng)目只有一個(gè)核心的控制器
問(wèn)題:
①:我們?cè)谥笆侵苯又该鱏ervlet的映射路徑了,現(xiàn)在要ActionServlet處理所有的請(qǐng)求,我們只要定一個(gè)規(guī)則:只要后綴為.action的,那么都交由核心控制器ActionServlet來(lái)控制....
②:現(xiàn)在全部的請(qǐng)求已經(jīng)交由ActionServlet控制,那怎么知道調(diào)用的是哪個(gè)Action???我們可以通過(guò)請(qǐng)求的uri,比如:http://localhost:8080/login.action,其中l(wèi)ogin就代表的是調(diào)用LoginAction..也就是說(shuō)login=LoginAction,我們可以通過(guò)properties文件來(lái)配置..
③:現(xiàn)在我們已經(jīng)知道了調(diào)用的是哪個(gè)Action了,但是Action可能不僅僅只有一個(gè)方法,我們還要在調(diào)用的時(shí)候,指定的方法名是什么.這很簡(jiǎn)單,一般我們都是職責(zé)分工明確的,method=login....并且,調(diào)用的Action和具體的方法也是有關(guān)系的,不可能是孤立存在的。因此,我們的配置文件是不能使用properties的,需要使用XML
④:在調(diào)用方法的時(shí)候,是返回一個(gè)Object的uri的,uri的類(lèi)型可能是String、也可以能是RequestDispatcher、并且返回的結(jié)果可能有幾種情況的【可能跳轉(zhuǎn)到首頁(yè),也可能跳轉(zhuǎn)到登陸界面】
⑤:Action調(diào)用的方法和返回的uri也是是有關(guān)系的!.....不同的Action調(diào)用不同的方法,返回的uri也是不同的....
⑥:要跳轉(zhuǎn)到哪個(gè)頁(yè)面上,可以通過(guò)標(biāo)識(shí)量來(lái)識(shí)別....比如:success表示成功執(zhí)行,如果要重定向那么多加個(gè)type類(lèi)型,如果不重定向就沒(méi)有type類(lèi)型..路徑使用path來(lái)表示..因此,在具體的Action中,就不需要返回具體的uri,只要返回一個(gè)標(biāo)識(shí)量即可
畫(huà)一張圖來(lái)梳理一下思路:
XML配置我們可以寫(xiě)出這樣的XML配置,當(dāng)ActionServlet初始化的時(shí)候,讀取XML配置文件,就知道調(diào)用的是什么Action,Action中的什么方法,以及跳轉(zhuǎn)到哪個(gè)頁(yè)面上了。
/index.jsp /message.jsp /message.jsp /message.jsp
為了更好地管理這些信息,我們應(yīng)該使用JavaBean來(lái)對(duì)它們封裝
ActionMappingManager-------管理全部的Action
/** * Created by ozc on 2017/4/26. * * 該類(lèi)管理著全部的Action * * 要管理全部的Action,就需要用一個(gè)容器來(lái)裝載這些Action * * 選擇Map集合是最合適的,可以通過(guò)key來(lái)得到Action,key就是中的name屬性 * */ public class ActionMappingManager { private Map map = new HashMap<>(); //注意:外界都是通過(guò)name來(lái)得到對(duì)應(yīng)的Action的,并不會(huì)獲取得到整個(gè)Manager public ActionMapping getActionMapping(String name) { return map.get(name); } }
ActionMapping----表示單個(gè)的Action
public class ActionMapping { //所有的results private Mapresults; //關(guān)鍵字name private String name; //要調(diào)用的Action路徑 private String className; //Action中的方法 private String method; public Map getResults() { return results; } public void setResults(Map results) { this.results = 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 String getMethod() { return method; } public void setMethod(String method) { this.method = method; } }
Results---表示的是結(jié)果視圖
/** * Created by ozc on 2017/4/26. * * 該類(lèi)表示的是結(jié)果視圖 * * * */ public class Results { //方法返回的標(biāo)識(shí) private String name; //要跳轉(zhuǎn)的方式 private String type; //要跳轉(zhuǎn)的頁(yè)面 private String page; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getPage() { return page; } public void setPage(String page) { this.page = page; } }ActionMappingManager讀取配置文件
在ActionMappingManager中,應(yīng)該讀取配置文件,然后把信息全部封裝到里邊去...
/** * Created by ozc on 2017/4/26. * * 該類(lèi)管理著全部的Action * * 要管理全部的Action,就需要用一個(gè)容器來(lái)裝載這些Action * * 選擇Map集合是最合適的,可以通過(guò)key來(lái)得到Action,key就是ActionServlet中的name屬性 * */ public class ActionMappingManager { private Map allAction ; public ActionMappingManager() { this.allAction = new HashMap<>(); //讀取配置文件信息 init(); } public void init() { /********通過(guò)DOM4J讀取配置文件信息*********/ try { //得到解析器 SAXReader saxReader = new SAXReader(); //讀取在類(lèi)目錄下的mystruts.xml文件 InputStream stream = ActionMappingManager.class.getClassLoader().getResourceAsStream("mystruts.xml"); //得到代表XML文件的Document對(duì)象 Document document = saxReader.read(stream); //通過(guò)XPATH直接得到所有的Action節(jié)點(diǎn) List list = document.selectNodes("http://action"); //得到每個(gè)Action節(jié)點(diǎn) for (int i = 0; i < list.size(); i++) { Element action = (Element) list.get(i); //把得到每個(gè)Action的節(jié)點(diǎn)信息封裝到ActionMapping中 ActionMapping actionMapping = new ActionMapping(); String name = action.attributeValue("name"); String method = action.attributeValue("method"); String className = action.attributeValue("className"); actionMapping.setName(name); actionMapping.setMethod(method); actionMapping.setClassName(className); //得到action節(jié)點(diǎn)下的所有result節(jié)點(diǎn) List results = action.elements("result"); //得到每一個(gè)result節(jié)點(diǎn) for (int j = 0; j < results.size(); j++) { Element result = (Element) results.get(j); //把得到每個(gè)result節(jié)點(diǎn)的信息封裝到Results中 Results results1 = new Results(); //得到節(jié)點(diǎn)的信息 String name1 = result.attributeValue("name"); String type = result.attributeValue("type"); String page = result.getText(); results1.setName(name1); results1.setType(type); results1.setPage(page); //把result節(jié)點(diǎn)添加到ActionMapping的集合中 actionMapping.getResults().put(name1, results1); } //最后把得到每個(gè)ActionMapping的信息添加到ActionMappingManager中 allAction.put(name, actionMapping); } } catch (DocumentException e) { new RuntimeException("初始化的時(shí)候出錯(cuò)了!“" + e); } } //注意:外界都是通過(guò)name來(lái)得到對(duì)應(yīng)的Action的,并不會(huì)獲取得到整個(gè)Manager public ActionMapping getActionMapping(String name) { return allAction.get(name); } }
使用init()方法只加載創(chuàng)建一個(gè)ActionManagerMapping對(duì)象,并設(shè)置在Web容器啟動(dòng)了該Servlet就啟動(dòng)
/** * Created by ozc on 2017/4/26. * * * Web容器一啟動(dòng)的時(shí)候,該類(lèi)就應(yīng)該加載了,在web.xml文件中配置onloadStart */ public class ActionServlet extends HttpServlet { //該對(duì)象封裝了所有的XML信息 ActionMappingManager actionMappingManager ; @Override public void init() throws ServletException { //讓ActionMappingManager對(duì)象只有一個(gè)! actionMappingManager = new ActionMappingManager(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //得到用戶的uri String uri = request.getRequestURI(); //截取uri的關(guān)鍵部分-----截完應(yīng)該是login uri = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf(".")); //通過(guò)uri得到配置文件中的action信息 ActionMapping actionMapping = actionMappingManager.getActionMapping(uri); //得到action的類(lèi)名,方法名 String className = actionMapping.getClassName(); String method = actionMapping.getMethod(); //通過(guò)反射創(chuàng)建出Action的對(duì)象,調(diào)用對(duì)應(yīng)的方法 Class t = Class.forName(className); Object o = t.newInstance(); //注意:這里的參數(shù)是接口的class,不是單純的request的class,單純的class是實(shí)現(xiàn)類(lèi) Method m = t.getMethod(method, HttpServletRequest.class, HttpServletResponse.class); //調(diào)用方法,得到標(biāo)記 String returnFlag = (String) m.invoke(o, request, response); //通過(guò)標(biāo)記得到result的具體信息 Results result = actionMapping.getResults().get(returnFlag); String type = result.getType(); String page = result.getPage(); //判斷是重定向還是轉(zhuǎn)發(fā),為空就是轉(zhuǎn)發(fā),反則是重定向 if (type == null) { response.sendRedirect(page); } else { request.getRequestDispatcher(request.getContextPath() + page).forward(request, response); } } catch (Exception e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } }
具體的Action的方法只要返回一個(gè)標(biāo)識(shí)量即可,我們通過(guò)標(biāo)識(shí)量來(lái)得到具體的跳轉(zhuǎn)頁(yè)面url和跳轉(zhuǎn)的方法的。。。
效果: 自定義MyStruts總結(jié):由于傳統(tǒng)web的Controller模塊存在弊端:
一些功能重復(fù)使用,代碼過(guò)于重復(fù)了。
跳轉(zhuǎn)的頁(yè)面寫(xiě)死了。改變需求的時(shí)候需要更改源代碼
本博文主要模擬Struts的開(kāi)發(fā)流程
使用一個(gè)ActionServlet核心控制器來(lái)管理全部的Web請(qǐng)求,寫(xiě)XML配置文件,讀取配置文件。
ActionMapping封裝了Action的基本信息,在XML配置文件中就是讀取Action的基本信息,封裝到JavaBean上,最后使用ActionMapping類(lèi)的集合統(tǒng)一管理起來(lái)。
當(dāng)用戶訪問(wèn)的時(shí)候,我們根據(jù)url也就是Action的名稱(chēng)反射出對(duì)應(yīng)的類(lèi),來(lái)對(duì)其進(jìn)行操作。
再根據(jù)XML文件的配置信息來(lái)確定跳轉(zhuǎn)方法、跳轉(zhuǎn)的url
我們現(xiàn)在學(xué)習(xí)的是Struts2,其實(shí)Struts1和Struts2在技術(shù)上是沒(méi)有很大的關(guān)聯(lián)的。 Struts2其實(shí)基于Web Work框架的,只不過(guò)它的推廣沒(méi)有Struts1好,因此就拿著Struts這個(gè)名氣推出了Struts2框架。
因此,學(xué)習(xí)Struts2的時(shí)候,不了解Struts1是沒(méi)有任何關(guān)系的。
在前面,已經(jīng)說(shuō)明了為什么要引入Struts框架,其實(shí)就是為了提高開(kāi)發(fā)效率...
Struts2框架預(yù)先實(shí)現(xiàn)了一些功能:
請(qǐng)求數(shù)據(jù)自動(dòng)封裝
文件上傳的功能
對(duì)國(guó)際化功能的簡(jiǎn)化
數(shù)據(jù)效驗(yàn)功能.......等等
Struts2開(kāi)發(fā)步驟我們就直接來(lái)講解Struts2的開(kāi)發(fā)步驟是什么吧....在了解它的細(xì)節(jié)之前,先要把配置環(huán)境搭好!
引入jar文件完整的struts中的jar包有80多個(gè),我們?nèi)粘i_(kāi)發(fā)是不需要那么多個(gè)的。一般我們導(dǎo)入的jar包有8個(gè):
commons-fileupload-1.2.2.jar 【文件上傳相關(guān)包】
commons-io-2.0.1.jar【文件上傳相關(guān)包】
struts2-core-2.3.4.1.jar 【struts2核心功能包】
xwork-core-2.3.4.1.jar 【Xwork核心包】
ognl-3.0.5.jar 【Ognl表達(dá)式功能支持表】
commons-lang3-3.1.jar 【struts對(duì)java.lang包的擴(kuò)展】
freemarker-2.3.19.jar 【struts的標(biāo)簽?zāi)0鍘?kù)jar文件】
javassist-3.11.0.GA.jar 【struts對(duì)字節(jié)碼的處理相關(guān)jar】
配置web.xml在web.xml中配置的過(guò)濾器,其實(shí)就是在為struts進(jìn)行初始化工作
值得注意的是:如果該web.xml配置了多個(gè)fileter,那么struts的filter需要在最后面!
開(kāi)發(fā)Actionstruts2 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter struts2 /*
開(kāi)山篇我們已經(jīng)說(shuō)了,Servlet的業(yè)務(wù)代碼,我們都使用Action來(lái)代替...Action類(lèi)一般繼承著ActionSupport
Action類(lèi)也叫動(dòng)作類(lèi),處理請(qǐng)求的類(lèi)。
public class HelloAction extends ActionSupport { @Override public String execute() throws Exception { System.out.println("helloworld"); return "success"; } }
至于execute()方法是什么,我們先不要去管它,為啥要返回一個(gè)String,我們也不要去管它....只要記住開(kāi)發(fā)步驟,并且,我們的Action類(lèi)是要繼承ActionSupport類(lèi)的
配置struts.xml至于配置struts.xml,我們可以在文件中找到相對(duì)應(yīng)的模版代碼的...最終修改成下面這個(gè)樣子就行了:
/index.jsp
看完上面的配置文件,是非常像我們開(kāi)山篇寫(xiě)的struts框架的配置文件的....
效果:在地址欄中直接輸入hello,就跳轉(zhuǎn)到index.jsp頁(yè)面了。并且,execute()中的語(yǔ)句被執(zhí)行了...
Struts2執(zhí)行流程我們來(lái)簡(jiǎn)單地了解一下Struts的執(zhí)行流程,然后再慢慢對(duì)上面的開(kāi)發(fā)步驟的部分進(jìn)行講解....
服務(wù)器啟動(dòng)下邊我說(shuō)的都是struts流程的重點(diǎn):
加載web.xml文件
找到我們配置的filter中的StrutsPrepareAndExecuteFilter
StrutsPrepareAndExecuteFilter在里邊執(zhí)行init()方法
一直到Dispatcher dispatcher = init.initDispatcher(config);,初始化dispatcher
在初始化dispatcher的時(shí)候加載struts-default.xml和我們配置的struts.xml
下面用GIF圖來(lái)看看它的執(zhí)行過(guò)程:
細(xì)心的朋友可能會(huì)發(fā)現(xiàn),我們在struts.xml的package節(jié)點(diǎn)下,extends了struts-default....那struts-default究竟是什么東西呢?
我們找到它的源碼:
我們發(fā)現(xiàn)了一大堆的Bean,interceptor,result-type,interceptor-stack...下邊我來(lái)講解一下它們是干嘛用的...
bean指定了struts在運(yùn)行的時(shí)候需要?jiǎng)?chuàng)建的對(duì)象類(lèi)型
在運(yùn)行struts的時(shí)候,可能需要?jiǎng)?chuàng)建一些對(duì)象,那么就通過(guò)Bean來(lái)指定
interceptor是struts定義的攔截器,一共有32個(gè)
前邊已經(jīng)說(shuō)了,Struts為我們實(shí)現(xiàn)了一些功能,就是通過(guò)攔截器來(lái)實(shí)現(xiàn)的。
result-type是跳轉(zhuǎn)結(jié)果的類(lèi)型
Action業(yè)務(wù)方法中的返回值,我們發(fā)現(xiàn)幾個(gè)實(shí)用的:redirect【重定向】、dispatcher【轉(zhuǎn)發(fā)】、redirectAction【重定向到Action資源】、stream【文件下載的時(shí)候用】...跳轉(zhuǎn)結(jié)果的類(lèi)型也在這里定義了
interceptor-stack是攔截器的棧
攔截器有32個(gè),我們可能會(huì)使用很多的攔截器,不可能一個(gè)一個(gè)來(lái)調(diào)用,于是提供了攔截器棧...其實(shí)可以簡(jiǎn)單看成文件夾和文件之間的關(guān)系
default-interceptor-ref是默認(rèn)執(zhí)行的攔截器棧
default-class-ref class是默認(rèn)的執(zhí)行Action類(lèi)
還要補(bǔ)充的就是:默認(rèn)的攔截器棧有18個(gè)攔截器....
攔截器和過(guò)濾器攔截器和過(guò)濾器都是攔截資源的
攔截器只攔截Action請(qǐng)求,是struts的概念...
過(guò)濾器攔截web的所有資源,是Servlet的概念...
小總結(jié)服務(wù)器啟動(dòng)的時(shí)候,其實(shí)就是加載了web.xml文件,然后調(diào)用init()方法去加載struts.xml和struts-default.xml之類(lèi)的文件.....
注意:此時(shí)的攔截器是還沒(méi)有被調(diào)用的。
訪問(wèn)階段在服務(wù)器啟動(dòng)的階段,僅僅是加載了各種的xml文件...那么當(dāng)我們?cè)L問(wèn)Action的時(shí)候,它的執(zhí)行流程是怎么的呢?
首先,它會(huì)創(chuàng)建我們?cè)趕truts.xml中配置的Action對(duì)象
接著,它會(huì)按照默認(rèn)的順序執(zhí)行18個(gè)攔截器【也就是調(diào)用默認(rèn)攔截器棧】
最后,它會(huì)執(zhí)行Action的業(yè)務(wù)方法【也就是execute(),我們?cè)趕truts.xml文件中配置了什么,就執(zhí)行什么業(yè)務(wù)方法】
值得注意的是:每訪問(wèn)Action一次,它就會(huì)創(chuàng)建一個(gè)對(duì)象...它并不是和Servlet一樣只有一個(gè)對(duì)象...因此它是線程安全的.
深入講解struts.xml這是我們的struts.xml的內(nèi)容,相信現(xiàn)在對(duì)它也不會(huì)太陌生了...
package/index.jsp
package其實(shí)就是包,那包用來(lái)干什么?包就是用來(lái)管理Action
通常來(lái)說(shuō),我們都是一個(gè)業(yè)務(wù)模版對(duì)應(yīng)一個(gè)package
namename是包的名字,值得注意的是,包的名稱(chēng)是不能重復(fù)的。
extendsextends代表的是當(dāng)前包繼承著哪個(gè)包。在struts中,包一定要繼承著struts-default
abstract在package中還有abstract這個(gè)屬性,使用該屬性時(shí):表明當(dāng)前包被其他的包繼承...并且,在package下不能有action,否則會(huì)出錯(cuò)!
namespace在package中還有namespace這個(gè)屬性---名稱(chēng)空間....它是作為路徑的一部分的,默認(rèn)是"/"
actoinaction:配置請(qǐng)求路徑與Action類(lèi)的映射關(guān)系
namename是請(qǐng)求路徑的名字
classclass是處理action類(lèi)的全名
methodmethod是調(diào)用的方法名稱(chēng)
resultresult代表的是Action中業(yè)務(wù)方法返回的值
namename是action處理返回的值
typetype是跳轉(zhuǎn)的類(lèi)型
文本值文本值是跳轉(zhuǎn)的路徑
細(xì)節(jié)前邊已經(jīng)說(shuō)了,一個(gè)package應(yīng)該對(duì)應(yīng)一個(gè)業(yè)務(wù)模塊..目的就是把職能細(xì)分出來(lái)...
struts為了讓我們更好地管理xml文件,它還可以這樣做:在不同的模塊中用不同的xml文件進(jìn)行描述...
最后在struts.xml文件中將其引入即可..
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68730.html
摘要:前言由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫(xiě)的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫(kù)連接池...
摘要:要是使用到日歷的話,我們想到使用這個(gè)日歷類(lèi)上面僅僅是我個(gè)人總結(jié)的要點(diǎn),如果有錯(cuò)誤的地方還請(qǐng)大家給我指正。 納稅服務(wù)系統(tǒng)總結(jié) 納稅服務(wù)系統(tǒng)是我第一個(gè)做得比較大的項(xiàng)目(不同于javaWeb小項(xiàng)目),該項(xiàng)目系統(tǒng)來(lái)源于傳智Java32期,十天的視頻課程(想要視頻的同學(xué)關(guān)注我的公眾號(hào)就可以直接獲取了) 我跟著練習(xí)一步一步完成需求,才發(fā)覺(jué)原來(lái)Java是這樣用來(lái)做網(wǎng)站的,Java有那么多的類(lèi)庫(kù),頁(yè)面...
摘要:性能會(huì)有所降低一點(diǎn)內(nèi)容,刷新整個(gè)頁(yè)面用戶的操作頁(yè)面會(huì)中斷整個(gè)頁(yè)面被刷新了就是能夠做到局部刷新三對(duì)象是中最重要的一個(gè)對(duì)象。頭信息已經(jīng)接收,響應(yīng)數(shù)據(jù)尚未接收。 一、什么是Ajax Ajax(Asynchronous JavaScript and XML) 異步JavaScript和XML Ajax實(shí)際上是下面這幾種技術(shù)的融合: (1)XHTML和CSS的基于標(biāo)準(zhǔn)的表示技術(shù) (2)DOM進(jìn)...
摘要:甲乙交易活動(dòng)不需要雙方見(jiàn)面,避免了雙方的互不信任造成交易失敗的問(wèn)題。這就是的核心思想。統(tǒng)一配置,便于修改。帶參數(shù)的構(gòu)造函數(shù)創(chuàng)建對(duì)象首先,就要提供帶參數(shù)的構(gòu)造函數(shù)接下來(lái),關(guān)鍵是怎么配置文件了。 前言 前面已經(jīng)學(xué)習(xí)了Struts2和Hibernate框架了。接下來(lái)學(xué)習(xí)的是Spring框架...本博文主要是引入Spring框架... Spring介紹 Spring誕生: 創(chuàng)建Spring的...
摘要:前言上一次我們對(duì)的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊。 showImg(https://segmentfault.com/img/remote/1460000020077803?w=1280&h=853); 前言 上一次我們對(duì)Paging的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊WorkManager。 如果你對(duì)Paging還未了解,推薦閱讀這篇文章: Paging在Recy...
閱讀 1629·2019-08-30 15:54
閱讀 2374·2019-08-30 15:52
閱讀 2047·2019-08-29 15:33
閱讀 3042·2019-08-28 17:56
閱讀 3236·2019-08-26 13:54
閱讀 1675·2019-08-26 12:16
閱讀 2449·2019-08-26 11:51
閱讀 1644·2019-08-26 10:26