自己写一个简单的Struts框架(3)

本文介绍了一种基于Java的简易Struts框架实现方法,重点在于如何利用DOM解析XML配置文件来实现请求分发和拦截器功能。通过创建ActionBean和InterceptorBean类,实现了对请求的处理和拦截。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上一篇自己写一个简单的Struts框架(2)

拦截器Interceptor

在上节所做的简单控制器的基础上,插入拦截器功能,通过读取解析xml文件中的标签配置,分发请求给特定的拦截器处理类进行处理。

SimpleController工程

SimpleController工程目录:

这里写图片描述

ActionBean以及InterceptorBean是抽象出的两个普通java类,分别对应action以及Interceptor以便于以后扩展功能。

ActionBean.java

ActionBean中定义了一个action的内容,例如action的name,action请求的处理类,方法,结果等。当有一个请求过来时,会生成一个对应的ActionBean对象。代码如下:

package sc.ustc.bean;

import java.util.List;
import java.util.Map;

public class ActionBean {

    private String actionName;
    private String actionClass;
    private String actionMethod;
    private Map<String, List<String>> actionResults;
    private Map<String, List<String>> actionInterceptors;

    public ActionBean(String actionName, String actionClass, String actionMethod, Map<String, List<String>> actionResults,
            Map<String, List<String>> actionInterceptors) {
        this.actionName = actionName;
        this.actionClass = actionClass;
        this.actionMethod = actionMethod;
        this.actionResults = actionResults;
        this.actionInterceptors = actionInterceptors; 
    }

    //属性的get set方法就不贴出来了

}

InterceptorBean.java

同样的有InterceptorBean。代码如下:

package sc.ustc.bean;

public class InterceptorBean {

    private String interceptorName;
    private String interceptorClass;
    private String interceptorPredo;
    private String interceptorAfterdo;

    public InterceptorBean(String interceptorName, String interceptorClass, String interceptorPredo, String interceptorAfterdo) {
        this.interceptorName = interceptorName;
        this.interceptorClass = interceptorClass;
        this.interceptorPredo = interceptorPredo;
        this.interceptorAfterdo = interceptorAfterdo;
    }
    //属性的get set方法就不贴出来了
}

MyTools.java

与上一节不同,这里xml文件的解析采取了DOM方式,上一节的解析方式针对性比较强,xml文件的内容必须按照设计好的格式写,DOM方式是java提供的一种基础的解析XML文件的API,用起来很方便,但是由整个文件都需要载入内存所以对内存的消耗较大。

package sc.ustc.tool;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import sc.ustc.bean.ActionBean;

public class MyTools {

    public ActionBean readXml_dom(String actionName, String path) {

        try {
            // controller.xml解析(DOM)
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder buillder = dbf.newDocumentBuilder();
            Document doc = buillder.parse(new File(path));
            // 解析interceptor节点
            NodeList interceptorsLi = doc.getElementsByTagName("interceptor");
            Map<String, List<String>> InterceptorMap = new HashMap<String, List<String>>();
            for (int i = 0; i < interceptorsLi.getLength(); i++) {
                List<String> interDirts = new ArrayList<String>();
                Element interceptor = (Element) interceptorsLi.item(i);
                interDirts.add(interceptor.getAttribute("name"));
                interDirts.add(interceptor.getAttribute("class"));
                interDirts.add(interceptor.getAttribute("predo"));
                interDirts.add(interceptor.getAttribute("afterdo"));
                InterceptorMap.put(interceptor.getAttribute("name"), interDirts);
            }
            // 解析action节点
            NodeList actions = doc.getElementsByTagName("action");
            for (int i = 0; i < actions.getLength(); i++) {
                Element action = (Element) actions.item(i);
                if (action.getAttribute("name").equals(actionName)) {
                    // 获取result节点
                    Map<String, List<String>> actionResultMap = new HashMap<String, List<String>>();
                    NodeList results = action.getElementsByTagName("result");
                    for (int j = 0; j < results.getLength(); j++) {
                        Element childNode = (Element) results.item(j);
                        List<String> resultList = new ArrayList<String>();
                        resultList.add(childNode.getAttribute("name"));
                        resultList.add(childNode.getAttribute("type"));
                        resultList.add(childNode.getAttribute("value"));
                        actionResultMap.put("result" + childNode.getAttribute("name"), resultList);

                    }
                    // 获取interceptor节点
                    Map<String, List<String>> actionInterceptors = new HashMap<String, List<String>>();
                    NodeList interceptors = action.getElementsByTagName("interceptro-ref");
                    for (int j = 0; j < interceptors.getLength(); j++) {
                        Element childNode = (Element) interceptors.item(j);
                        actionInterceptors.put(String.valueOf(j), InterceptorMap.get(childNode.getAttribute("name")));
                    }
                    return new ActionBean(actionName, action.getAttribute("class"), action.getAttribute("method"), actionResultMap, actionInterceptors);
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

SimpleController.java

SimpleController接收到所有的action,解析name,class,method,通过java反射机制调用相应的类进行处理。同样的,会先判断是否有Interceptor,若有则先处理一层层的Interceptor。

package sc.ustc.controller;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sc.ustc.bean.ActionBean;
import sc.ustc.tool.CglibProxy;
import sc.ustc.tool.MyTools;

public class SimpleController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @SuppressWarnings("unchecked")
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html,charset=utf-8");
        response.setCharacterEncoding("utf-8");
        request.setCharacterEncoding("utf-8");

        String actionName = request.getServletPath().toString();
        String[] actionUrl = actionName.split("/");
        actionName = actionUrl[actionUrl.length - 1];
        String path = this.getServletContext().getRealPath("WEB-INF/classes/controller.xml");
        MyTools mt = new MyTools();
        ActionBean actionBean = mt.readXml_dom(actionName.substring(0, actionName.indexOf(".")), path);
        if (actionBean != null) {

            String actionClass = actionBean.getActionClass();
            String actionMethod = actionBean.getActionMethod();

            try {
                // 反射机制获得action类名及方法
                Class cl = Class.forName(actionClass);
                Method m = cl.getMethod(actionMethod, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class);
                String result = null;

                /*
                 * 判断action是否有interceptor
                 * 
                 * 待扩展,此处默认只有一个拦截器
                 */
                if (actionBean.getActionInterceptor() != null && !actionBean.getActionInterceptor().isEmpty()) {
                    // 创建代理实例
                    Object clc = CglibProxy.getProxy(cl);
                    // 调用代理方法
                    result = (String) m.invoke(clc, request, response, actionBean);
                } else {
                    result = (String) m.invoke(cl, request, response, actionBean);
                }
                String resT = actionBean.getActionResults().get("result" + result).get(1);
                String resV = actionBean.getActionResults().get("result" + result).get(2);

                if (resT.equals("foward")) {
                    request.getRequestDispatcher(resV).forward(request, response);
                } else if (resT.equals("redirect")) {
                    response.sendRedirect(resV);
                }

            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        } else {
            response.sendRedirect("/UseSC/jsp/Login.jsp");
        }
    }

}

CglibProxy.java

Cglib实现对业务处理类的代理,即进行拦截操作

package sc.ustc.tool;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import sc.ustc.bean.ActionBean;

public class CglibProxy {
    public static Object getProxy(Class<?> clazz) {

        CglibProxyX proxy = new CglibProxyX();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(proxy);
        return enhancer.create();
    }
}

class CglibProxyX implements MethodInterceptor {

    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {

        ActionBean actionBean = (ActionBean) args[2];
        String classN = actionBean.getActionInterceptor().get("0").get(1);
        String predo = actionBean.getActionInterceptor().get("0").get(2);
        String afterdo = actionBean.getActionInterceptor().get("0").get(3);
        Class<?> cl = Class.forName(classN);
        Method preMethod = cl.getMethod(predo, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class);
        Method afterMethod = cl.getMethod(afterdo, HttpServletRequest.class, HttpServletResponse.class, ActionBean.class, String.class);

        preMethod.invoke(cl.newInstance(), (HttpServletRequest) args[0], (HttpServletResponse) args[1], actionBean);
        String result = (String) proxy.invokeSuper(object, args);
        afterMethod.invoke(cl.newInstance(), (HttpServletRequest) args[0], (HttpServletResponse) args[1], actionBean, result);
        return result;
    }
}

对应的配置文件示例

<?xml version="1.0" encoding="UTF-8"?>
<sc-configuration>
    <interceptor name="log" class="water.ustc.interceptor.LogInterceptor"
        predo="preAction" afterdo="afterAction">
    </interceptor>
    <controller>
        <action name="login" class="water.ustc.action.LoginAction"
            method="handleLogin">
            <interceptro-ref name="log"></interceptro-ref>
            <result name="success" type="foward" value="success_view.xml"></result>
            <result name="failure" type="redirect" value="Login.jsp"></result>
        </action>
        <action name="regist" class="water.ustc.action.RegisterAction"
            method="handleRegist">
            <interceptro-ref name="log"></interceptro-ref>
            <result name="success" type="foward" value="Welcome.jsp"></result>
            <result name="failure" type="redirect" value="Regist.jsp"></result>
        </action>
    </controller>
</sc-configuration>

相应的UseSC工程部分的测试代码就不再详述了,与上一节类似

至此,写一个功能及其简陋的Struts框架系列完结

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值