Struts 是 Apache 软件基金会(ASF)赞助的一个开源项目。它最初是 Jakarta 项目中的一个子项目,并在 2004 年 3 月成为 ASF 的顶级项目。它通过采用 JavaServlet/JSP 技术,实现了基于 Java EEweb 应用的 MVC 设计模式的应用框架,是 MVC 经典设计模式中的一个经典产品。
这篇文章主要为大家详细介绍了 struts2 如何自定义 MVC 框架, 具有一定的参考价值,感兴趣的小伙伴们可以参考一下
自定义 MVC:(首先了解 Model1 和 Model2 的概念)
Model1 与 Model2:
Model1: 就是一种纯 jsp 开发技术,将业务逻辑代码和视图渲染代码杂糅在一起。
Model2:Model2 是在 Model1 的基础上,将业务逻辑的代码分离开来,单独形成一个 Servlet,Model2 也是基于 MVC 开发。
总结 MVC 特点如下:
(1)数据的获取和显示分离
(2)控制器将不同的模型和视图组合在一起
(3)应用分为三部分,三部分之间松耦合并协同工作,从而提高应用的可扩展性和可维护性
(4)各层负责不同的功能,各司其职,每一层的组件具有相同的特征,便于通过工程化和工具化产生程序代码
MVC 思想及其优势(很强势)
MVC 是一种架构模式,目的是将模型 (业务逻辑)、视图(表示层) 分离,使模型和视图可以独立修改互不影响。大多数软件在设计架构时都采用此模式。使用 MVC 模式有很多处,当一个通过浏览器浏览的系统想要开发手机版本时,只需要重新开发视图,模型部分的业务逻辑可以重用。许多软件需要同时推出 B/S 和 C/S 版本,采用 MVC 模式,模型部分可以重用,只需要开发不同的视图即可。MVC 思想将一个应用分成三个基本部分 M(Model,模型)V(View,视图)C(Controller,控制器)。其中 M 表示处理业务逻辑的部分,V 表示显示数据和获取用户输入的部分,C 类似中介,保证 M 和 V 不会直接交互。
基本步骤如下:
1. 创建 XML 文档 Framework.xml
2. 定义 Action 接口
3. 定义一个 actionMapping 类,视为 action 节点
4. 定义 ActionMappingManage 类来管理 ActionMapping 类(actions 节点)
5. 定义 ActionManager 类使用反射机制根据字符串类型的类名获取到具体的类(web.xml 标签的书写)
6. 编写 servlet 进行运行时机的控制
7. 定义 LoginAction 类进行测试
1. 创建 XML 文档 Framework.xml
- <!--?xml version="1.0" encoding="UTF-8"?-->
- <!-- 定义约束文件 -->
- (标注)
- <!-- ELEMENT 表示元素 -->
- <!-- ATTLIST 表示属性 -->
- <!-- CDATA 表示字符串类型 -->
- <!-- REQUIRED 表示此属性必须的写 -->
- <!-- *代表多个 -->
- <!-- IMPLIED 表示此属性可写 -->
- <!-- redirect 重定向或转发 -->
- <!--ELEMENT actions (action)-->
- <!--ELEMENT action (result*)-->
- (*表示可以多个)
- <!--ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED -->
- <!--ATTLIST RESULT name CDATA #IMPLIED redirect (true|false) "false" -->
- ]>
- <framework>
- <!-- 进行测试 -->
- <actions>
- <action name="loginAction" class="cn.hq.Action.LoginAction">
- <result name="success">
- success.jsp
- </result>
- <result name="login">
- index.jsp
- </result>
- </action>
- </actions>
- </framework>
注意:空格和 <> 的书写规范。
节点的层次。
2. 定义 Action 接口
注意:excute 参数的书写,请求和响应。
3. 定义一个 actionMapping 类,视为 action 节点(进行 action 节点的标签的书写)
进行封装字段和 results 集合的添加数据。
注意:添加数据的书写。(Map 集合)
4. 定义 ActionMappingManage 类来管理 ActionMapping 类(actions 节点)
- /*
- * action节点不止一个
- * 用来来管理ActionMapping类
- */
- public class ActionMappingManager {
- //actionMapping类的集合
- private Map < String,
- ActionMapping > maps = new HashMap < String,
- ActionMapping > ();
- public ActionMapping getActionMapping(String name) {
- return maps.get(name);
- }
- //解析在src项目下的所有配置文件
- //实例化完毕后进行解析
- public ActionMappingManager(String[] file) {
- for (String filename: file) {
- Init(filename);
- }
- }
- //init初始化方法
- //解析xml文档
- public void Init(String path) {
- try {
- InputStream is = this.getClass().getResourceAsStream("/" + path);
- //解析xml
- Document doc = new SAXReader().read(is);
- //获取根节点
- Element root = doc.getRootElement();
- //获取actions节点
- Element actions = (Element) root.elementIterator("actions").next();
- //使用for循环来遍历actions节点下的所有action节点
- for (Iterator < Element > action = actions.elementIterator("action"); action.hasNext();) {
- //获取到<action>节点
- Element actionnext = action.next();
- //分别获取到action节点中的name属性和class属性
- String name = actionnext.attributeValue("name");
- String classname = actionnext.attributeValue("class");
- //将以上两个属性保存到ActionMapping类中
- ActionMapping mapp = new ActionMapping();
- mapp.setClassname(classname);
- mapp.setName(name);
- //由于一个action节点下有多个result节点 遍历action下所有的result节点
- for (Iterator < Element > result = actionnext.elementIterator("result"); result.hasNext();) {
- //获取到result节点
- Element resultnext = result.next();
- //提取result节点的name属性值和result节点中的值
- String resultname = resultnext.attributeValue("name");
- String resultvalue = resultnext.getText();
- //将其分别存入到actionMapping中的双列集合中去,方便调用actionMapping类(actionMapping类中就有数据了!)
- mapp.addResult(resultname, resultvalue);
- System.out.println(mapp.getName());
- }
- //得到所有action节点的集合
- maps.put(mapp.getName(), mapp);
- }
- } catch(Exception e) {
- // TODO: handle exception
- }
- }
- }
概括:
通过 dom4j 解析 Framework.xml 配置文件。从而获取根节点,以及 actions 节点,并通过 for 循环遍历 actions 节点下的 action 节点拿到 name 和 class 的属性值,由于一个 action 节点下有多个 result 节点 及遍历 action 下所有的 result 节点,分别存入到 actionMapping 中的双列集合中,最后得到所有 action 节点的集合。
注意:Init 方法的书写,以及 ActionMappingManager 带参数组的书写。
5. 定义 ActionManager 类使用反射机制根据字符串类型的类名获取到具体的类
- public class ActionManager {
- public static Action getActionClass(String classname) {
- Class clazz = null;
- Action action = null;
- //获取当前线程的类加载器
- try {
- //如果线程中的有那么一个类,直接根据类名获取该类的类型
- clazz = Thread.currentThread().getContextClassLoader().loadClass(classname);
- } catch(ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if (clazz == null) {
- try {
- //如果该线程中没有,那么使用class.forname方法获取
- clazz = Class.forName(classname);
- } catch(ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- if (action == null) {
- try {
- //将获取到的类型转换为action,调用无参构造函数,某种程度上相当于new,不过new需要指定类型
- action = (Action) clazz.newInstance();
- } catch(InstantiationException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch(IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return action;
- }
- }
web.xml 的节点配置:
6. 编写 servlet 进行运行时机的控制(servlet, 初始化所有的类)
- public class MyServlet extends HttpServlet {
- /**
- *你很菜
- */
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- doPost(request, response);
- } < br >
- /**
- *继续努力
- */
- ActionMappingManager man = null;
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- //获取ActionMapping对象
- ActionMapping actionMapping = man.getActionMapping(getPath(request));
- //获取action接口反射机制
- Action action = ActionManager.getActionManager(actionMapping.getClassname());
- try {
- String message = action.execute(request, response);
- String results = actionMapping.getResults(message);
- response.sendRedirect(results);
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- /*
- * 获取请求的路径名
- */
- public String getPath(HttpServletRequest request) {
- //项目+请求地址
- String requestURI = request.getRequestURI();
- //项目名称
- String contextPath = request.getContextPath();
- //具体请求
- String path = requestURI.substring(contextPath.length());
- String filename = path.substring(1, path.lastIndexOf("."));
- return filename;
- }
- /*
- *重写init,程序运行加载所有类
- *
- */
- @Override public void init(ServletConfig config) throws ServletException {
- //config对象是javax.servlet.ServletConfig的对象,功能是获得初始化配置信息
- //config.getInitParameter是取得指定名称的初始化参数内容
- String filename = config.getInitParameter("config");
- String[] filenames = null;
- if (filename == null) {
- //如果为空 ,
- filenames = new String[] {
- "Framework.xml"
- };
- } else {
- //若果有其他的配置参数信息,那么以,分隔存入数组中
- filenames = filename.split(",");
- }
- //使用init方法进行初始化
- man = new ActionMappingManager(filenames);
- }
- }
注意:代码的层次及注释。
7. 定义 LoginAction 类进行测试
- public class LoginAction implements Action{
- @Override
- public String execute(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- String name = request.getParameter("name");
- String pwd = request.getParameter("pwd");
- if(name.equals("1")&&pwd.equals("1")){
- return SUCCESS;
- }else{
- return LOGIN;
- }
- }
- }
jsp 代码:
实现效果:
再长的路,一步步也能走完,再短的路,不迈开双脚也无法到达。
来源: http://www.phperz.com/article/17/1212/359660.html