Cet article présente principalement les informations pertinentes de l'exemple mvc simple de struts1. Les amis qui en ont besoin peuvent s'y référer
Regardez d'abord l'organigramme du modèle MVC (en fait, le modèle de conception MVC est le modèle2. en java.):
Tout comme la couche C identifiée dans l'image est principalement la couche Servlet contrôlant les sauts de page, la couche M est la logique de traitement métier spécifique, et JSP est ce qu'on appelle la couche V. MVC est différent de ce que nous appelons les trois couches. Les trois couches que nous appelons habituellement sont la couche UI, la couche BLL et la couche DAL. Les différences spécifiques sont les suivantes :
.Comme le montre la figure, JSP et Servlet constituent la couche UI, et la couche Modèle est divisée en couche BLL et couche DAL (c'est-à-dire la couche de logique métier et de persistance des données).
Après avoir théoriquement compris le modèle de conception MVC, commençons à taper un exemple de code du modèle de conception MVC :
Page d'index 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>
Code de logique métier UserManager :
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; } }
Code de contrôle du servlet :
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); }
La fonction principale de ce code de servlet est de déterminer quelle page demande au serveur d'effectuer ces opérations, puis appelle la logique métier pour implémenter les opérations métier correspondantes.
Configurer le servlet :
<?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>
Résultat de sortie :
Via le ci-dessus L'exemple a une compréhension préliminaire du modèle de conception MVC. En fait, cet exemple est la base de l'apprentissage du cadre Struts. Ce n'est qu'en comprenant cet exemple que nous pouvons comprendre le principe de mise en œuvre du cadre Struts et l'utilisation du cadre Struts.
Alors, comment pouvons-nous présenter le framework Struts à travers cet exemple ? Ce problème commence avec IF-Eles.
Tout d'abord, nous avons vu qu'il y a beaucoup d'instructions if-else dans TestServlet. C'est très instable. Un tel programme est très rigide. S'il y a des changements dans le futur, la maintenance sera. très mauvais ; De plus, nous avons un grand nombre de chaînes dans if-else, ce qui provoquera des erreurs d'écriture lors du codage, ce qui entraînera des problèmes de débogage. Par conséquent, supprimer if-else est devenu la première étape de notre reconstruction et la première étape de notre apprentissage du framework Struts. Étant donné que le bloc d'instructions If-Else apparaît dans TestServlet, le programme devient moins flexible et maladroit lorsqu'il répond aux changements d'exigences. Je vais donc continuer l'article précédent pour reconstruire le code de TestServlet, en utilisant principalement le polymorphisme d'héritage pour reconstruire davantage le TestServlet.
Ce qui suit entre dans la phase de reconstruction :
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); } }
Nous voyons d'abord que l'affectation à transmettre apparaît dans chaque bloc d'instructions, qui est en fait Attribuer une valeur au chemin de saut de page et attribuer un chemin de saut en fonction de chaque jugement de chemin de requête. De plus, il existe des processus métier dans chaque bloc d'instructions IF-Else. Nous devons regrouper ces processus métier en classes pour rendre les responsabilités plus unifiées, ce qui est plus conforme à l'idée orientée objet.
À partir de là, nous commençons à reconstruire, nous pouvons encapsuler ce chemin de saut et cette logique métier.
Puisqu'elle est encapsulée, nous allons faire abstraction d'une excuse et principalement compléter une méthode. La fonction principale de cette méthode est de terminer l'encapsulation de la logique métier et le retour du saut de chemin. Ensuite, quatre classes sont établies pour implémenter principalement le traitement métier correspondant des ajouts, suppressions, modifications et requêtes ainsi que le retour du chemin de saut après le traitement.
Le code est le suivant :
Action d'interface :
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; }
Ajouter une classe d'implémentation utilisateur :
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"; } }
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"; } }
package com.bjpowernode.servlet; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class QueryUserAction implements Action { @Override public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String username=request.getParameter("username"); UserManager userManager=new UserManager(); List userList=userManager.queryUser(username); request.setAttribute("userList", userList); return "/query_success.jsp"; } }
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); } }
这样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框架的雏形,
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!