1. 程式人生 > >ideat使用struts2之自定義MVC框架

ideat使用struts2之自定義MVC框架

clu src pen mod files 文件導入 exc form over

今天我學習了自定義一個簡單的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框架