手写Struts框架之miniMVC

学习框架的开头曲:miniMVC
1.目录结构
在这里插入图片描述

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>

学习框架的第一天,好饭不怕晚,加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值