天天看點

手寫Struts架構之miniMVC

學習架構的開頭曲:miniMVC

1.目錄結構

手寫Struts架構之miniMVC

core.web中的filter包中ActionFilter 的代碼

package com.mxl.core.web.filter;

import com.mxl.core.web.ActionConfig;
import com.mxl.core.web.ActionContext;
import com.mxl.core.web.ResultConfig;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class ActionFilter implements Filter {
    //key存儲action元素的name屬性
    //value用來存儲action元素的封裝類actionConfig對象
    private Map<String, ActionConfig> actionConfigMap = new HashMap<>();
    public void init(FilterConfig config) throws ServletException {
        Document document = this.getDocument();
        //擷取actions.xml中所有的action元素,每一個action元素應該封裝成一個ActionConfig對象
        NodeList nodeList = document.getElementsByTagName("action");
        for (int i = 0;i < nodeList.getLength();i++){
            Element actionEl = (Element) nodeList.item(i);//每一個action元素

            String name = actionEl.getAttribute("name");
            String className = actionEl.getAttribute("class");
            String method = actionEl.getAttribute("method");

            ActionConfig actionConfig = new ActionConfig(name, className, method);
            actionConfigMap.put(name,actionConfig);
            //--------------------------------------------------------
            //讀取action元素中的result元素,并封裝成對象
            NodeList resultNodeList = actionEl.getElementsByTagName("result");
            for (int j = 0;j < resultNodeList.getLength();j++){
                Element resultEl = (Element) resultNodeList.item(j);//result元素
                String resultName = resultEl.getAttribute("name");
                String type = resultEl.getAttribute("type");
                String path = resultEl.getTextContent();

                ResultConfig resultConfig = new ResultConfig(resultName, type, path);

                actionConfig.getResultMap().put(resultName, resultConfig);
            }
            System.out.println(actionConfigMap);
        }
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        //-------------------------------------------------------------
        ActionContext ctx = new ActionContext(req, resp);
        ActionContext.setContext(ctx);
        //-------------------------------------------------------------

//        System.out.println("通用的操作");
        //擷取請求的資源名稱
        String requestUri = req.getRequestURI().substring(1);
        ActionConfig actionConfig = actionConfigMap.get(requestUri);
        if (actionConfig==null){
            chain.doFilter(req, resp);
            return;
        }
        String className = actionConfig.getClassName();//Action類全限定名
        String method = actionConfig.getMethod();//Action類的處理請求的方法

        try {
            Class actionClass = Class.forName(className);
            Object actionObj = actionClass.newInstance();
            Method actionClassMethod = actionClass.getMethod(method);

            //使用反射調用action方法,傳回邏輯視圖的名稱
            Object ret = actionClassMethod.invoke(actionObj);
            if (ret!=null){
                String viewName = ret.toString();
                //根據邏輯視圖名,取出對應的resultConfig對象
                ResultConfig resultConfig = actionConfig.getResultMap().get(viewName);
                if (resultConfig!=null){
                    //跳轉方式
                    String type = resultConfig.getType();
                    //實體路徑
                    String path = resultConfig.getPath();
                    //跳轉方式
                    if ("dispatcher".equals(type)){
                        req.getRequestDispatcher(path).forward(req, resp);
                    }else if ("redirect".equals(type)){
                        resp.sendRedirect(req.getContextPath()+path);
                    }
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
    public Document getDocument(){
        InputStream in = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("actions.xml");
        try {
            return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public void destroy() {
    }
}
           

core.web中的ActionConfig

package com.mxl.core.web;

import java.util.HashMap;
import java.util.Map;

//封裝action元素中的所有資訊
//    <action name="employee" class="com.mxl.crm.web.adtion.EmployeeAction" method="excute"></action>
public class ActionConfig {
    private String name;//action元素的name屬性
    private String className;//action元素的class屬性
    private String method;//action元素的method屬性

    //action元素中具有多個result元素
    private Map<String,ResultConfig> resultMap = new HashMap<>();

    public ActionConfig(String name, String className, String method) {
        this.name = name;
        this.className = className;
        this.method = method;
    }

    public String getName() {
        return name;
    }

    public String getClassName() {
        return className;
    }

    public String getMethod() {
        return method;
    }

    public Map<String, ResultConfig> getResultMap() {
        return resultMap;
    }

    @Override
    public String toString() {
        return "ActionConfig{" +
                "name='" + name + '\'' +
                ", className='" + className + '\'' +
                ", method='" + method + '\'' +
                ", resultMap=" + resultMap +
                '}';
    }
}

           

core.web中的ActionContext

package com.mxl.core.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//Action的環境
//封裝了請求和響應對象
public class ActionContext {
    private HttpServletRequest request;
    private HttpServletResponse response;

    //為每一個線程都配置設定一個ActionContext對象的副本,這就安全了
    private static ThreadLocal<ActionContext> threadLocal = new ThreadLocal<>();


    public static ActionContext getContext() {
        return threadLocal.get();
    }

    public static void setContext(ActionContext context) {
        threadLocal.set(context);
    }

    public ActionContext(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpServletResponse getResponse() {
        return response;
    }
}

           

core.web中的ResultConfig

package com.mxl.core.web;
//封裝了result元素的資訊
public class ResultConfig {

    private String name;//result的name
    private String type;//result的type
    private String path;//result的文本内容

    public ResultConfig(String name, String type, String path) {
        this.name = name;
        this.type = type;
        this.path = path;
    }

    public String getName() {
        return name;
    }

    public String getType() {
        return type;
    }

    public String getPath() {
        return path;
    }

    public String toString() {
        return "ResultConfig{" + "name='" + name + '\'' + ", type='" + type + '\'' + ", path='" + path + '\'' + '}';
    }
}

           

com.mxl.crm.web.adtion中的DepartmentAction

package com.mxl.crm.web.adtion;

import com.mxl.core.web.ActionContext;

import javax.servlet.ServletException;
import java.io.IOException;

public class DepartmentAction {
    //傳回邏輯視圖名稱
    public String excute() throws ServletException, IOException {
        System.out.println("department.........");
        return "list";
    }
}

           

com.mxl.crm.web.adtion中的EmployeeAction

package com.mxl.crm.web.adtion;

import com.mxl.core.web.ActionContext;

import javax.servlet.ServletException;
import java.io.IOException;

public class EmployeeAction {

    public String excute() throws ServletException, IOException {
        System.out.println("employee.........");
        return "input";
    }
}

           

actions.xml的内容

<?xml version="1.0" encoding="UTF-8"?>
<actions>
    <!--每一個action元素-->
    <!--
    action元素:表示每一個Action元素
    name屬性:請求action對象的資源名稱
    class屬性:表示該Action對象的全限定名稱
    method屬性:目前請求action類中的某一個方法
    -->
    <action name="department" class="com.mxl.crm.web.adtion.DepartmentAction" method="excute">
        <!--結果視圖-->
        <!--result元素表示action請求之後的結果視圖
        name屬性:action方法傳回的結果試圖
        type屬性:視圖跳轉方式,請求轉發/url重定向
        文本内容:結果視圖的實體路徑
        -->
        <result name="list" type="dispatcher">/WEB-INF/views/department/list.jsp</result>
        <result name="input" type="redirect">/WEB-INF/views/department/input.jsp</result>
    </action>


    <action name="employee" class="com.mxl.crm.web.adtion.EmployeeAction" method="excute">
        <result name="list" type="dispatcher">/WEB-INF/views/employee/list.jsp</result>
        <result name="input" type="redirect">/WEB-INF/views/employee/input.jsp</result>
    </action>
</actions>
           

web.xml中filter配置

<filter>
        <filter-name>ActionFilter</filter-name>
        <filter-class>com.mxl.core.web.filter.ActionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ActionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
           

學習架構的第一天,好飯不怕晚,加油!

繼續閱讀