ideat使用struts2之自定義MVC框架
今天我學習了自定義一個簡單的MVC框架,這個我們首先要知道什麽是MVC框架!
MVC框架: MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯聚集到一個部件裏面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。
我們今天自己定義的MVC框架是簡單模仿struts2的
然後我們會用到兩個常用的技能點,一個是使用dom4j解析xml文件,還有一個是java反射機制。
我們先看一下整體架構
我們用的是intellij idea這個工具。我們會創建一個maven項目,然後在pom文件導入我們需要的兩個jar包,一個是dom4j的,一個是javaee的
下面是兩個節點
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <parent> <artifactId>Y2166</artifactId> <groupId>cn.happy</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>CustomMVC</artifactId> <packaging>war</packaging> <name>CustomMVC Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <!--ServletAPI--> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources> </build> </project>
我們要定義自己的配置文件myframe.xml.我們要定義自己的dtd文件約束和配置信息
<?xml version=‘1.0‘ encoding=‘UTF-8‘?> <!DOCTYPE myframe[ <!ELEMENT myframe (actions)> <!ELEMENT actions (action*)> <!ELEMENT action (result*)> <!ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED> <!ELEMENT result (#PCDATA)> <!ATTLIST result name CDATA #IMPLIED redirect (true|false) "false"> ]> <myframe> <actions> <action name="login" class="cn.curry.action.LoginAction"> <result name="success">/success.jsp</result> <result name="login">/login.jsp</result> </action> </actions> </myframe>
然後建好包開始創建我們需要的類和接口。
首先我們定義自己的Action接口,在這個接口裏我們簡單定義了兩個字符串常量,還有一個抽象的execute方法,我們最後看實現。
package cn.curry.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @Auther: Xiao Yu * @Date: Created in 17:53 2018/3/3 */ public interface Action { public static final String SUCCESS="success"; public static final String LOGIN="login"; public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception; }
然後我們定義一個ActionManager管理類,我們通過類名用反射機制獲取對象。
package cn.curry.action; /** * @Auther: Xiao Yu * @Date: Created in 17:53 2018/3/3 */ public class ActionManager { public static Action getActionClass(String className) throws Exception{ Class clazz=null; Action action=null; clazz=Thread.currentThread().getContextClassLoader().loadClass(className); if (clazz==null){ clazz=Class.forName(className); } if (action==null){ action=(Action) clazz.newInstance(); } return action; } }
然後我們再定義一個ActionMapping類,這個類定義了幾個屬性,類似於實體類的作用。
package cn.curry.action; /** * @Auther: Xiao Yu * @Date: Created in 17:54 2018/3/3 */ import java.util.HashMap; import java.util.Map; public class ActionMapping { private String name; private String className; private Map<String,String> map=new HashMap<String, String>(); 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 getValue(String key) { return map.get(key); } public void addToMap(String key,String value) { map.put(key,value); } }
然後我們要做解析XML的類,我們的類ActionMappingManager ,我們通過讀取用jdom4j讀取xml,然後把數據添加到集合中。
package cn.curry.action; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * @Auther: Xiao Yu * @Date: Created in 17:54 2018/3/3 */ public class ActionMappingManager { private Map<String,ActionMapping> map=new HashMap<String, ActionMapping>(); public ActionMapping getValue(String key) { return map.get(key); } public void addToMaps(String key,ActionMapping value) { map.put(key,value); } public ActionMappingManager(String [] files)throws Exception{ for (String item:files){ init(item); } } public void init(String path)throws Exception{ InputStream is=this.getClass().getResourceAsStream("/"+path); Document doc=new SAXReader().read(is); Element root=doc.getRootElement(); Element actions=(Element)root.elements("actions").iterator().next(); for (Iterator<Element> action=actions.elementIterator("action");action.hasNext();){ Element actionnext=action.next(); ActionMapping am=new ActionMapping(); am.setName(actionnext.attributeValue("name")); am.setClassName(actionnext.attributeValue("class")); for (Iterator<Element> result=actionnext.elementIterator("result");result.hasNext();){ Element resultnext=result.next(); String name=resultnext.attributeValue("name"); String value=resultnext.getText(); if (name==null||"".equals(name)){ name="success"; } am.addToMap(name,value); } map.put(am.getName(),am); } } }
定義自己的LoginAction封裝業務邏輯
package cn.curry.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @Auther: Xiao Yu * @Date: Created in 17:54 2018/3/3 */ public class LoginAction implements Action{ public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String name = request.getParameter("name"); if(name.equals("1")){ return "success"; }else { return "login"; } } }
接下來我們要定義一個servlet來獲取請求,LoginServlet.主要通過獲取的請求來找到myframe.xml.
package cn.curry.servlet; import cn.curry.action.Action; import cn.curry.action.ActionManager; import cn.curry.action.ActionMapping; import cn.curry.action.ActionMappingManager; import org.omg.PortableInterceptor.ACTIVE; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @Auther: Xiao Yu * @Date: Created in 17:54 2018/3/3 */ public class LoginServlet extends HttpServlet { private ActionMappingManager manager=null; private String getClassName(HttpServletRequest request){ String uri=request.getRequestURI(); System.out.println(uri+" uri"); String context=request.getContextPath(); System.out.println(context+" context"); String result=uri.substring(context.length()); System.out.println(result+" result"); return result.substring(1,result.lastIndexOf(".")); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String key=getClassName(request); System.out.println(key+" key"); try { ActionMapping actionMapping=manager.getValue(key); System.out.println(actionMapping.getClassName()+" classname"); Action action= ActionManager.getActionClass(actionMapping.getClassName()); String result=action.execute(request,response); System.out.println(result+" result"); String path=actionMapping.getValue(result); System.out.println(path+" path"); request.getRequestDispatcher(path).forward(request,response); } catch (Exception e) { e.printStackTrace(); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } @Override public void init(ServletConfig config) throws ServletException { String fileName=config.getInitParameter("config"); String file[]=null; if(fileName==null){ file=new String[]{"myframe.xml"}; }else { fileName.split(","); } try { manager=new ActionMappingManager(file); } catch (Exception e) { e.printStackTrace(); } } }
最後我們配置一下web.xml,然後就書寫頁面
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>cn.curry.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app>
書寫頁面,我們準備了兩個頁面,一個login.jsp。一個success.jsp。
首先看login.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> <base href="<%=basePath%>"> <title>登陸頁面</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="login.action" method="POST"> <input name="name"><br> <input type="submit" value="登陸"/> </form> </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> <base href="<%=basePath%>"> <title>SUCCESS</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <h2>登錄成功</h2> </body> </html>
最後我們看一下運行效果
登陸成功跳到success.jsp頁面
看一下登陸失敗
登陸失敗重新跳到登陸頁面
ideat使用struts2之自定義MVC框架