一直想写Struts2的底层实现,酝酿了两个星期,今天把它实现。

首先,我们在运用的时候都会使用action,实现跳转,下面我们写一个UserAction:

public class UserAction {public String toAddUser(){return "success";}public String addUser(){return "adduser";}
}

我们在使用Struts2的时候,一个很重要的配置文件是:struts.xml,因此我们需要读取它,知道他里面的内容,java解析xml我写过了一篇文章,可以去看看。

下面我们写一个配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<struts><package name="user" namespace="/user" ><action name="userAction" class="actions.UserAction" ><result name="success">/success.jsp</result><result name="adduser">/addUser.jsp</result></action></package>
</struts>

之后我们就需要去读取这个配置文件,但是之前我们需要我们需要建立几个实体类去存储这些元素,由外到内排列:

1.package的实体类

import java.util.List;
public class PackageEntity {private String name;private String namespace;private List<ActionEntity> actions;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNamespace() {return namespace;}public void setNamespace(String namespace) {this.namespace = namespace;}public List<ActionEntity> getActions() {return actions;}public void setActions(List<ActionEntity> actions) {this.actions = actions;}
}

private List<ActionEntity> actions;是吧action实体类的内容放到package中。

2.action的实体类

import java.util.List;
public class ActionEntity {private String name;private String classname;private List<ResultEntity> results;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 List<ResultEntity> getResults() {return results;}public void setResults(List<ResultEntity> results) {this.results = results;}
}

private List<ResultEntity> results;是把result的实体类放到action中。

3.result的实体类

public class ResultEntity {private String name;private String page;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPage() {return page;}public void setPage(String page) {this.page = page;}
}

page是指后面的jsp。

经过两个list就把配置文件中所有的元素集中到package中,便于下面的跳转。

下面写一个配置的工具类:

public class ConfigUtils {
//new一个package的对象,便于调用元素public static  PackageEntity pe=new PackageEntity();public static void config(){SAXReader reader=new SAXReader();try {//读取struts.xmlDocument doc=reader.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("struts.xml"));//读取根元素Element root=doc.getRootElement();//得到根元素下的节点元素Element packageElement=root.element("package");List<ActionEntity> actions=new ArrayList<ActionEntity>();pe.setName(packageElement.attributeValue("name"));pe.setNamespace(packageElement.attributeValue("namespace"));//得到根元素下的节点元素List<Element> listActions=packageElement.elements("action");for(Element actionElement:listActions){ActionEntity ae=new ActionEntity();//得到子节点ae.setName(actionElement.attributeValue("name"));ae.setClassname(actionElement.attributeValue("class"));//得到根元素下的节点元素List<Element> resultElements=actionElement.elements("result");List<ResultEntity>  results=new ArrayList<ResultEntity>();for(Element resultEle:resultElements){ResultEntity re=new ResultEntity();//得到子节点re.setName(resultEle.attributeValue("name"));re.setPage(resultEle.getText());results.add(re);}ae.setResults(results);actions.add(ae);}pe.setActions(actions);} catch (DocumentException e) {e.printStackTrace();}}
}

写一个index.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><title>首页</title></head><body><a href="<%=path%>/user/userAction!toAddUser.action">跳转</a><br/><a href="<%=path%>/user/userAction!addUser.action">添加用户</a></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><title>My JSP 'success.jsp' starting page</title></head><body>This is my JSP page. <br>成功了</body>
</html>

添加用户是跳到adduser.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><title>My JSP 'addUser.jsp' starting page</title></head><body>This is my JSP page. <br>添加用户了</body>
</html>

写好了jsp之后我们就要过滤这些连接,进行跳转,写一个struts2的过滤器:

public class StrutsFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {HttpServletRequest request=(HttpServletRequest)req;String path=request.getServletPath();System.out.println(path);String[] pathArr=path.split("/");String namespace=pathArr[1];String actionString=pathArr[2];String actionname=actionString.split("!")[0];String methodname=actionString.split("!")[1].split("\\.")[0];System.out.println(actionname+":"+methodname);PackageEntity pe=ConfigUtils.pe;List<ActionEntity> actions=pe.getActions();ActionEntity doAction=null;for(ActionEntity ae:actions){if(ae.getName().equals(actionname)){doAction=ae;break;}}try {Class actioncls=Class.forName(doAction.getClassname());Object actionObj=actioncls.newInstance();Class cls=actionObj.getClass();Method actionMethod=cls.getDeclaredMethod(methodname);String resultValue=(String)actionMethod.invoke(actionObj,null);List<ResultEntity> results=doAction.getResults();ResultEntity re=null;for(ResultEntity result:results){if(resultValue.equals(result.getName())){re=result;break;}}request.getRequestDispatcher(re.getPage()).forward(request, res);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {ConfigUtils.config();    }
}

下面建立一个web的过滤器测试一下:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {HttpServletRequest request=(HttpServletRequest)req;HttpServletResponse response=(HttpServletResponse)res;request.getRequestDispatcher("/success.jsp").forward(request,response); }@Override
public void init(FilterConfig filterConfig) throws ServletException {}
}

建立一个web的servlet测试一下:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
request.getRequestDispatcher("/success.jsp").forward(request, response);}
}

别忘了把解析xml的包导进去。

希望对你们理解框架有帮助!!!

转载于:https://blog.51cto.com/7915791/1350348

Struts2MVC底层的简单实现相关推荐

  1. tensorflow入门教程和底层机制简单解说——本质就是图计算,自动寻找依赖,想想spark机制就明白了...

    简介 本章的目的是让你了解和运行 TensorFlow! 在开始之前, 让我们先看一段使用 Python API 撰写的 TensorFlow 示例代码, 让你对将要学习的内容有初步的印象. 这段很短 ...

  2. 第十三章_Java中常用集合大整理(含底层数据结构简单介绍)

    第十三章_Java中常用集合大整理 1.集合和数组的区别 集合 既可以存储基本数据类型还可以存储引用数据类型 定长–>是数组最大的特点,也是最大的缺点 数组 只能存储引用数据类型 长度可变 相同 ...

  3. HashSet底层原理简单详解

    1.HashSet底层其实是一个HashMap容器,HashSet的无参构造方法是创建一个HashMap对象 private transient HashMap<E, Object> ma ...

  4. 【重难点】【Redis 01】为什么使用 Redis、Redis 的线程模型、Redis 的数据类型及其底层数据结构

    [重难点][Redis 01]为什么使用 Redis.Redis 的线程模型.Redis 的数据类型及其底层数据结构 文章目录 [重难点][Redis 01]为什么使用 Redis.Redis 的线程 ...

  5. 简单了解消息中间件及ActiveMQ

    最近阅读文献,发现一篇介绍中间件及ActiveMQ的好文章,特此转载留存,同时也分享给大家.原文献地址:https://segmentfault.com/a/1190000014958916?utm_ ...

  6. 【Go语言学习】——go 数据结构底层原理

    go 数据结构底层原理 array底层原理 go中的数组是由固定长度的特定类型元素组成的序列,数组的长度是数据类型的组成方式,所以不同长度和不同类型的元素组成的数组是不同的数组类型.数组属于值类型,因 ...

  7. Redis从入门到精通之底层数据结构快表QuickList详解

    文章目录 0.前言 1. 快表的结构 2. Redis 6.0 快表quicklist 基本结构 2.1 成员变量 2.1 主要操作 2.1 推导结果 3. 快表的操作 3. 快表的优缺点 3.1 优 ...

  8. 22张精炼图笔记,深度学习专项学习必备

    作者 | DL&CV_study9 编辑 | Elle 来源 | CSDN 博客 本文为人工智能学习笔记记录. [深度学习基础篇] 一.深度学习基本概念 监督学习:所有输入数据都有确定的对应输 ...

  9. ElasticSearch 面试 4 连问,你顶得住么?

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 者:yanglbme github.com/doocs/ad ...

  10. Elasticsearch 查询数据的工作原理是什么?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:8rr.co/GsAa 面试题 ES 写入数据的工作原理是什 ...

最新文章

  1. NLP能否像人脑一样工作?CMU、MIT三篇论文详解机器和大脑范畴下NLP的关系
  2. IOS开发CALayer隐式动画
  3. 算法测试—机器学习算法评价指标
  4. 教你11 周打造全能Python工程师!
  5. Uiautomator--Uiselector元素定位
  6. 别再叫我“老工”!!!工程师姓什么很重要!
  7. 12个有趣的C语言面试题
  8. Jinja2模板与模板继承
  9. ASP.NET Web开发框架之八 所有ERP部分的源代码全部开放下载
  10. SQL Server商业智能功能–创建简单的OLAP多维数据集
  11. 不可识别的字符转义序列_大庆事业单位车牌识别道闸多少钱,感应小区车牌识别道闸系统...
  12. 软件质量需要静态代码分析和动态测试
  13. 【Multisim仿真】LM317-337双路输出可调直流稳压电源电路
  14. 一个三非渣本的安卓秋招之路
  15. 烤仔星选·NFT实验室 | 非同质化代币在游戏领域的应用
  16. 编译小度deng wifi源码出错
  17. 解决 ImportError: No module named 'serial' 问题
  18. java生成PDF 导出
  19. 软件测试之计算机基础
  20. python计算给定的日期的星期_Python计算给定日期的周内的某一天

热门文章

  1. PHP password_hash 与 password_verify 使用
  2. PHP 使用 ZipArchive 将文件打包成 zip
  3. PAT (Advanced Level) Practice 1001 A+B Format (20分)
  4. 解决办法:std没有成员initializer_list
  5. UOS开启开发者模式
  6. 软件基本功:做自说明的测试文档,
  7. LINUX下载编译libreadline
  8. 取经队伍要裁员,第一个就是唐僧
  9. 晚间看图片就高亮,这体验太差
  10. LINUX开机自启问题