この記事では主に struts1 の単純な MVC サンプルの関連情報を紹介します。必要な方は参考にしてください。
まず MVC パターンのフローチャートを見てください (実際、MVC 設計パターンは Java のモデル 2 です):
同様に、図で識別される C 層は主にページジャンプを制御するサーブレット層であり、M 層は特定のビジネス処理ロジックであり、JSP はいわゆる V 層です。 MVC は、通常 UI 層、BLL 層、DAL 層と呼ばれる 3 つの層とは異なります。具体的な違いは次のとおりです。図から、JSP とサーブレットは UI 層を形成し、モデル層は BLL 層と DAL 層 (つまり、ビジネス ロジックとデータ永続化層) に分かれています。 MVC 設計モードを理論的に認識した後、以下の MVC 設計モードのサンプル コードをノックし始めます:
JSP インデックス ページ INDEX.JSP:
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030"> <title>Insert title here</title> </head> <body> <form action="servlet/addUser.action" method="post"> 姓名:<input type="text" name="username" > <input type="submit" value="提交"> </form> </body> </html>
package com.bjpowernode.servlet; import java.util.ArrayList; import java.util.List; public class UserManager { public void addUser(String username){ System.out.println("UserManager.addUsre()--->username:"+username); } public void delUser(String username){ System.out.println("UserManager.delUser()--->username:"+username); } public void modifyUser(String username){ System.out.println("UserManager.modifyUser()--->username"+username); } public List queryUser(String username){ System.out.println("UserManager.queryUser()--->username"+username); List userList=new ArrayList(); userList.add("a"); userList.add("b"); userList.add("c"); return userList; } }
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String username=request.getParameter("username"); UserManager userManager=new UserManager(); //userManager.addUser(username); String forward=""; if("/servlet/delUser".equals(path)){ userManager.delUser(username); forward="/del_success.jsp"; }else if("/servlet/addUser".equals(path)){ userManager.addUser(username); forward="/add_success.jsp"; }else if("/servlet/modifyUser".equals(path)){ userManager.modifyUser(username); forward="/modify_success.jsp"; }else if("/servlet/queryUser".equals(path)){ List userList=userManager.queryUser(username); request.setAttribute("userList", userList); forward="/query_success.jsp"; }else{ throw new RuntimeException("请求失败"); } request.getRequestDispatcher(forward).forward(request, response); }
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>test_Servlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>com.cjq.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
実際、この例は Struts フレームワークの学習の基礎となっています。 Struts フレームワークの実装原理と Struts フレームワークの使用方法を明確にします。
では、この例を通じて Struts フレームワークをどのように導入できるでしょうか?この問題は IF-Eles から始まります。 E まず、TestServlet には if-ogse 文が多数出現していることがわかりました。これは非常に不安定であり、将来的に変更があった場合、非常に不便です。 elseに文字列が大量にあるとコーディング時に書き込みエラーが発生し、デバッグに支障をきたします。したがって、if-else を削除することが、再構築の最初のステップであり、Struts フレームワークの学習の最初のステップとなりました。 If-Else ステートメント ブロックが TestServlet に出現するため、要件の変更に対応する際にプログラムの柔軟性が低下し、扱いにくくなります。そこで、前回の記事に引き続き、TestServlet コードを再構築します。主に継承ポリモーフィズムを使用して、TestServlet をさらに再構築します。以下は再構成段階に入ります:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String username=request.getParameter("username"); UserManager userManager=new UserManager(); //userManager.addUser(username); String forward=""; if("/servlet/delUser".equals(path)){ userManager.delUser(username); forward="/del_success.jsp"; }else if("/servlet/addUser".equals(path)){ userManager.addUser(username); forward="/add_success.jsp"; }else if("/servlet/modifyUser".equals(path)){ userManager.modifyUser(username); forward="/modify_success.jsp"; }else if("/servlet/queryUser".equals(path)){ List userList=userManager.queryUser(username); request.setAttribute("userList", userList); forward="/query_success.jsp"; }else{ throw new RuntimeException("请求失败"); } request.getRequestDispatcher(forward).forward(request, response); } }
ここからリファクタリングを開始し、このジャンプ パスとビジネス ロジックをカプセル化できます。
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public interface Action { public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception; }
- ユーザー実装クラス:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AddUserAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.addUser(username); return "/add_success.jsp"; } }
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DelUserAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.delUser(username); return "/del_success.jsp"; } }
TestServlet クラスは次のようにリファクタリングされます:
package com.bjpowernode.servlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ModifyUserAction implements Action { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); userManager.modifyUser(username); return "/modify_success.jsp"; } }
这样TestServlet类虽然没有彻底去掉If-Else,但是这样的代码变得更加简练,利用多肽实现业务逻辑处理和路径跳转返回。职责更加清晰,让维护变得更加轻松。
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); Action action=null; if("/servlet/delUser".equals(path)){ action=new DelUserAction(); }else if("/servlet/addUser".equals(path)){ action=new AddUserAction(); }else if("/servlet/modifyUser".equals(path)){ action=new ModifyUserAction(); }else if("/servlet/queryUser".equals(path)){ action=new QueryUserAction(); }else{ throw new RuntimeException("请求失败"); } String forward=null; try{ forward=action.execute(request, response); }catch(Exception e){ e.printStackTrace(); } request.getRequestDispatcher(forward).forward(request, response); } }
解决字符串问题,当然就要用到配置文件了,用到配置文件就要有用来读取配置文件的相关的类和方法,这里就用dom4j中的类来读取配置文件,这里的配置文件的书写是有点逻辑上的难度的。
我们来看TestServlet中的代码,我们要在这个testservlet中实现读取配置文件和path比较,还有利用多肽实例化相应的实现类,最后通过实例化的实现类的方法来返回跳转路径,最终跳转到相应的页面。
所以我们的配置文件就要不仅配上testservlet中出现的字符串,还要配置相应的Action接口的实现类(我们可以利用反射来实例化该类的对象,进而使用这个类的所有属性和方法),另外还有跳转路径字符串。这样我们的配置文件就变成了如下代码所示:
<?xml version="1.0" encoding="UTF-8"?> <action-config> <action path="/servlet/delUser" type="com.cjq.servlet.DelUserAction"> <forward name="success">/del_success.jsp</forward> <forward name="error">/del_error.jsp</forward> </action> <action path="/servlet/addUser" type="com.cjq.servlet.AddUserAction"> <forward name="success">/add_success.jsp</forward> <forward name="error">/add_error.jsp</forward> </action> <action path="/servlet/modifyUser" type="com.cjq.servlet.ModifyUserAction"> <forward name="success">/modify_success.jsp</forward> <forward name="error">/modify_error.jsp</forward> </action> <action path="/servlet/queryUser" type="com.cjq.servlet.QueryUserAction"> <forward name="success">/query_success.jsp</forward> <forward name="error">/query_error.jsp</forward> </action> </action-config>
我们有了配置文件之后就要想法通过相关类读取,并且实现相应的功能。所以这里用dom4j来读取完成。其实如果能把这个逻辑捋顺之后就能发现,其实懂我们利用dom4j读取完配置文件的时候,我们是取得的是一个配套的匹配路径字符串、相应业务逻辑类还有处理业务逻辑之后跳转页面路径字符串。这样我们就能直截了当的去掉了if-else。(这里可能逻辑上会出现一些困难,但是看到下面的重构之后的testservlet中的代码和读取配置文件之后的代码就会一目了然)。
现在等待解决的问题就是我们要把从配置文件取得的一整套内容放到那里,当然这是毋庸置疑的要放到类中。所以我们就建立一个ActionMapping类来放我们的那一整套内容。
ActionMapping中的代码如下:
package com.bjpowernode.servlet; import java.util.Map; public class ActionMapping { private String path; private Object type; private Map forwardMap; public String getPath() { return path; } public void setPath(String path) { this.path = path; } public Object getType() { return type; } public void setType(Object type) { this.type = type; } public Map getForwardMap() { return forwardMap; } public void setForwardMap(Map forwardMap) { this.forwardMap = forwardMap; } }
现在ActionMapping类已经有了,剩下的工作就是要利用dom4j来读取配置文件类,具体代码如下:
package com.bjpowernode.servlet; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class XmlConfigReader { private static XmlConfigReader instance=new XmlConfigReader(); ActionMapping actionMapping=new ActionMapping(); private Document doc; private Map actionMap=new HashMap(); private XmlConfigReader(){ try { SAXReader reader=new SAXReader(); InputStream in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml"); doc=reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public ActionMapping getActionMapping(String path){ synchronized(this){ Object type=null; /*if(action.containsKey(path)){ type=action.get(path); }*/ Element eltAction = (Element)doc.selectObject("//action[@path=\"" + path + "\"]"); try{ type=Class.forName(eltAction.attributeValue("type")).newInstance(); }catch(Exception e){ e.printStackTrace(); } Element eltForwards = eltAction.element("forward"); for (Iterator iter = eltForwards.elementIterator(); iter.hasNext();) { Element eltForward = (Element) iter.next(); actionMap.put( eltForward.attributeValue("name"),eltForward.getTextTrim()); } actionMapping.setPath(path); actionMapping.setType(type); actionMapping.setForwardMap(actionMap); return actionMapping; } } public static synchronized XmlConfigReader getInstance(){ return instance; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser"); System.out.println(actionMapping.getPath()); System.out.println(actionMapping.getType()); System.out.println(actionMapping.getForwardMap().toString()); } }
我们通过返回ActionMapping来动态创建出action相应的实现类,进而完成业务逻辑和页面跳转,重构之后的TestServlet代码如下:
package com.bjpowernode.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String requestURI=request.getRequestURI(); System.out.println("request="+requestURI); String path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf(".")); System.out.println("path="+path); String forward=""; ActionMapping actionMapping=XmlConfigReader.getInstance().getActionMapping(path); Action action=(Action)actionMapping.getType(); try { forward=action.execute(request, response); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } request.getRequestDispatcher(forward).forward(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
我们可以清晰的看到if-else已经没有了,字符串也已经没有了。通过这篇文章对if-else还有字符串问题的解决,又一次重构了testservlet代码,程序相对灵活许多。通过这一次的重构,我们已经看到了struts框架的雏形,
以上がstruts1の簡単なmvcグラフィックコード例の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。