传智:自己简单实现一个struts2框架的demo

struts2的结构图:

代码实现:

组织结构:

主要代码:

package cn.itcast.config;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zhen on 2017-08-04.
 * 读取struts.xml配置信息
 */
public class ConfigurationManager {
    private static final Logger logger = Logger.getLogger(ConfigurationManager.class);

    //读取Interceptor
    public static List<String> getInterceptors(){
        List<String> interceptors = null;
        SAXReader saxReader = new SAXReader();
        InputStream inputStream = ConfigurationManager.class.getResourceAsStream("/struts.xml");
        Document document = null;
        try {
            document = saxReader.read(inputStream);
        } catch (DocumentException e) {
            logger.error(e.getMessage());
            throw new RuntimeException("配置文件解析异常" ,e);
        }
        String xpath = "//interceptor";
        List<Element> list = document.selectNodes(xpath);
        if(list != null && list.size() > 0){
            interceptors = new ArrayList<String>();
            for(Element ele: list){
                String className = ele.attributeValue("class");
                interceptors.add(className);
            }
        }
        return interceptors;
    }

    //读取Constant
    public static String getConstant(String name){
        String value = null;
        SAXReader saxReader = new SAXReader();
        InputStream is = ConfigurationManager.class.getResourceAsStream("/struts.xml");
        Document document = null;
        try {
            document = saxReader.read(is);
        } catch (DocumentException e) {
            logger.error(e.getMessage());
            throw new RuntimeException("配置文件解析异常" ,e);
        }
        String xPath = "//constant[@name=‘" + name + "‘]";
        List<Element> ele = document.selectNodes(xPath);
        if(ele != null && ele.size() > 0){
            value = ele.get(0).attributeValue("value");
        }
        return value;
    }

    //读取Action
    public static Map<String, ActionConfig> getActions(){
        Map<String, ActionConfig> actions = null;
        SAXReader saxReader = new SAXReader();
        InputStream is = ConfigurationManager.class.getResourceAsStream("/struts.xml");
        Document document = null;
        try {
            document = saxReader.read(is);
        } catch (DocumentException e) {
            logger.error(e.getMessage());
            throw new RuntimeException("配置文件解析异常" ,e);
        }
        String xPath = "//action";
        List<Element> list = document.selectNodes(xPath);
        if(list != null && list.size() > 0){
            actions = new HashMap<String, ActionConfig>();
            for(Element element : list){
                ActionConfig actionConfig = new ActionConfig();
                String name = element.attributeValue("name");
                String method = element.attributeValue("method");
                String className = element.attributeValue("class");
                Map<String, String> results = null;
                List<Element> resultElements = element.elements("result");
                if(resultElements != null && resultElements.size() > 0){
                    results = new HashMap();
                    for(Element ele: resultElements){
                        String resultName = ele.attributeValue("name");
                        String resultValue = ele.getTextTrim();
                        results.put(resultName, resultValue);
                    }
                }
                actionConfig.setName(name);
                actionConfig.setMethod(method == null || method.trim().equals("") ? "execute" : method.trim());
                actionConfig.setClassName(className);
                actionConfig.setResults(results);
                actions.put(name, actionConfig);
            }
        }
        return actions;
    }

}
package cn.itcast.invocation;

import cn.itcast.config.ActionConfig;
import cn.itcast.context.ActionContext;
import cn.itcast.interceptor.Interceptor;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by zhen on 2017-08-06.
 */
public class ActionInvocation {
    private static final Logger logger = Logger.getLogger(ActionInvocation.class);
    private Iterator<Interceptor> interceptors;
    private Object action;
    private ActionConfig actionConfig;
    private ActionContext actionContext;
    private String resultUrl;

    public ActionContext getActionContext() {
        return actionContext;
    }

    public ActionInvocation(List<String> classNames, ActionConfig actionConfig, HttpServletRequest request, HttpServletResponse response){
        //装载Interceptor链
        if(classNames != null && classNames.size() > 0){
            List<Interceptor> interceptorList = new ArrayList<Interceptor>();
            for(String className : classNames){
                try {
                    Interceptor interceptor = (Interceptor) Class.forName(className).newInstance();
                    interceptor.init();
                    interceptorList.add(interceptor);
                } catch (Exception e) {
                    logger.error(e.getMessage());
                    throw new RuntimeException("创建Interceptor失败,Interceptor Name:" + className ,e);
                }
            }
            interceptors =  interceptorList.iterator();
        }

        //准备action实例
        this.actionConfig = actionConfig;
        try {
            action = Class.forName(actionConfig.getClassName()).newInstance();
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException("创建Action实例失败!" + actionConfig.getClass(), e);
        }

        //准备数据中心
        actionContext = new ActionContext(request, response, action);
    }

    public String invoke(){
       if(interceptors != null && interceptors.hasNext() && resultUrl == null){
           Interceptor interceptor = interceptors.next();
           resultUrl = interceptor.invoke(this);
       }else{
           try{
               Method executeMethod = Class.forName(actionConfig.getClassName()).getMethod(actionConfig.getMethod());
               resultUrl = (String) executeMethod.invoke(action);
           }catch(Exception ex){
               logger.error(ex.getMessage());
               throw new RuntimeException("您配置的action方法不存在" + actionConfig.getClassName());
           }
       }
       return resultUrl;
    }
}
package cn.itcast.filter;

import cn.itcast.config.ActionConfig;
import cn.itcast.config.ConfigurationManager;
import cn.itcast.context.ActionContext;
import cn.itcast.invocation.ActionInvocation;
import org.apache.log4j.Logger;
import org.junit.Test;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created by zhen on 2017-08-06.
 */
public class StrutsPrepareAndExecuteFilter implements Filter {
    private static final Logger logger = Logger.getLogger(StrutsPrepareAndExecuteFilter.class);
    private List<String> interceptorClassNames;
    private  String extension;
    private Map<String, ActionConfig> actionConfigs;

    public void init(FilterConfig filterConfig) throws ServletException {
        //装载配置信息
        interceptorClassNames = ConfigurationManager.getInterceptors();
        extension = ConfigurationManager.getConstant("struts.action.extension");
        actionConfigs = ConfigurationManager.getActions();
    }

    public static void main(String[] args){
        Logger logger = Logger.getLogger(StrutsPrepareAndExecuteFilter.class);
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //执行
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String urlPath = request.getRequestURI();
        if(!urlPath.endsWith(extension)){
            filterChain.doFilter(request, response);
            return;
        }
        String actionName = urlPath.substring(urlPath.lastIndexOf("/") + 1).replace("." + extension, "");
        ActionConfig actionConfig = actionConfigs.get(actionName);
        if(actionConfig == null){
            throw new RuntimeException("找不到对应的action!" + actionName);
        }
        ActionInvocation actionInvocation = new ActionInvocation(interceptorClassNames, actionConfig, request, response);
        String result = actionInvocation.invoke();
        String dispatcherPath = actionConfig.getResults().get(result);
        if(dispatcherPath == null || "".equals(dispatcherPath)){
            throw new RuntimeException("找不到对应的返回路径!");
        }
        request.getRequestDispatcher(dispatcherPath).forward(request, response);
        ActionContext.tl.remove();
    }

    public void destroy() {

    }
}

写后感想:

struts2模拟

1、关注点分离思想。类似java中的解耦合,插拔。将功能拆分成各个拦截器实现。拦截器运行过程中拼接出想要的功能。
2、MVC思想。 filter-C Action-M jsp_url-V

需要掌握知识:
    XML解析,Xpath表达式(dom4j)
    Servlet技术
    java内省(BeanUtils)
    ThreadLocal线程本地化类
    递归调用

需要补充的知识:
    dom4j解析
    xpath语法
    获取资源文件路径

理解:
    对于值栈的模拟不要拘泥于数组,也可以使用现有的类进行封装,比如使用ArrayList模拟。
    经常递归调用使用的局部变量可以放在循环外或者说是方法外。

项目路径:

https://github.com/gzdx/MyStruts2.git

时间: 2024-10-18 07:36:26

传智:自己简单实现一个struts2框架的demo的相关文章

简单实现一个rpc框架

与其说框架不如讲是个小demo,废话不多说直接上代码 package com.tang.rpc; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Pr

第一个struts2框架

编写步骤: 1.导入有关的包. 2.编写web.xml文件 3.写Action类 4.编写jsp 5.编写struts.xml web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/jav

C++传智笔记(5):C++完整demo

MyPoint.h #pragma once class MyPoint { private: double x0, y0; //点坐标 public: void setPoint(double x, double y); double getX0(); double getY0(); }; MyPoint.cpp #include "MyPoint.h" void MyPoint::setPoint(double x, double y) { x0 = x; y0 = y; } do

struts2框架 转载 精华帖

一.Struts2简介 参考<JavaEE 轻量级框架应用与开发-S2SH> Struts框架是流行广泛的一个MVC开源实现,而Struts2是Struts框架的新一代产品,是将Struts1和WebWork两种技术进行兼容.合并的全新的MVC框架.Struts2框架充分发挥了Struts1和WebWork这两种技术的优势,抛弃原来Struts1的缺点,使得Web开发更加容易. Struts1运行原理:  Struts1工作流程: (1)客户端向Web应用发送请求,请求被核心控制器Action

为什么来传智播客

在那么多的培训的结构中传智播客是唯一一个我同学读过的培训结构,经过同学的大概介绍我觉得传智播客是一个可以实现我理想工作的.并且我也是没有找到一个我可以相信的结构,在同学的帮助下我报读了传智播客.来到传智播客的目的是希望自己能找到理想的工作,给自己和家人一个幸福的生活.为了这个目的我一定要好好的学习,努力为我自己的目的好好奋斗! 对未来人生的规划!来到传智播客希望学好技术,以后出去工作能够做到会一些东西.工作以后继续进步不断的学习,不进步就是退步.现在互联网的时代不会一定技术就是不现代了.什么行业

传智的光辉岁月-C#基础篇一编译原理

时间过的真快,不知不觉已经从传智出来,工作一个月了啊,想想当初自己的所有努力和付出都是值得的,当初来传智可以说是走头无路,唯有努力的向前冲,在这里满满的正能量,激烈着我一直努力,胜利就在前面,只要你能坚持坚持~~~对于我这样的一个新手而言,现在最重要的就是技术积累,一入IT深似海,我要学的东西还真的很多很多... 以前一直没时间,现在在工作之余,想把自己以前学的东西整理一套笔记,供.NET爱好者,和自己以后翻阅参考.... 好了直接上代码... using System; namespace H

传智五虎是真相?受影射最重PHP学科,这几月在忙什么..?

传智播客10年的发展,就一直伴随着一些同行的攻击.某些同行为了攻击传智播客,什么手段都使的出来,有的是网上公然的中伤,有的是扮演学生捏造传智老师这么差那么烂(是不是这样,请看:<那些对传智播客的恶意攻击>,<软件培训机构的网络营销那点事儿>).现在推陈出新,竟然利用传智正常的人员流动捏造说"因为某些老师的离职,传智的教学质量下滑,传智播客不行了".被某些同行最为广泛粘贴的文章即为"五虎离职"(注:文章提到的黎活明老师并没有离职). 传智五虎百

搭建一个简单struts2框架的登陆

第一步:下载struts2对应的jar包,可以到struts官网下载:http://struts.apache.org/download.cgi#struts252 出于学习的目的,可以把整个完整的压缩文件都下载下来. 里面包括:1 apps:示例应用,对学习很有帮助 : 2 docs:相关学习文档.API文档等: 3 lib:核心类库,依赖包: 4:src:源代码 第二步:在eclipse新建一个Dynamic Web Project类型工程,一直点next,记得勾选generate web.

笨鸟先飞之Java(一)--使用struts2框架实现文件上传和下载

不管是.net还是Java,我们最常接触到的就是文件的上传和下载功能,在Java里要实现这两个常用功能会有很多种解决方式,但是struts2的框架却能给我们一个比较简单的方式,下面就一起来看吧: 文件上传: 首先来看实现上传功能的表单,Index.jsp: <span style="font-family:FangSong_GB2312;font-size:18px;"><%@ page language="java" contentType=&q