Struts 是 Apache 软件基金会(ASF)赞助的一个开源项目。它最初是 Jakarta 项目中的一个子项目,并在 2004 年 3 月成为 ASF 的顶级项目。它通过采用 JavaServlet/JSP 技术,实现了基于 Java EEWeb 应用的 MVC 设计模式的应用框架,是 MVC 经典设计模式中的一个经典产品。
这篇文章主要介绍了 struts1 之简单 mvc 示例的相关资料, 需要的朋友可以参考下
先看 MVC 模式流程图(其实 MVC 设计模式就是 java 中的 model2。):
就像图上所标识的 C 层主要是 Servlet 层控制页面跳转,M 层就是具体的业务处理逻辑,而 JSP 就是所谓的 V 层。MVC 是有别于我们所说的三层,我们平常所说的三层是 UI 层、BLL 层、DAL 层,具体的区别如图:
从图上能看出来,JSP 和 Servlet 构成了 UI 层,而 Model 层分成了 BLL 层和 DAL 层(也就是业务逻辑和数据持久层)。
从理论上认清了 MVC 设计模式之后,下面开始动手敲一个 MVC 设计模式示例代码:
JSP 索引页面 index.jsp:
- <%@ page language="java" contentType="text/html; charset=GB18030"
- pageEncoding="GB18030"%>
- http-equiv="Content-Type" content="text/html; charset=GB18030">
- Insert title here
- action="servlet/addUser.action" method="post">
- 姓名: type="text" name="username" >
- type="submit" value="提交">
业务逻辑代码 UserManager:
- package com.bjpowernode.servlet;
- import java.util.ArrayList;
- import java.util.List;
- public class UserManager {
- public void addUser(String username) {
- System.out.println("UserManager.addUsre()--->username:" + username);
- }
- public void delUser(String username) {
- System.out.println("UserManager.delUser()--->username:" + username);
- }
- public void modifyUser(String username) {
- System.out.println("UserManager.modifyUser()--->username" + username);
- }
- public List queryUser(String username) {
- System.out.println("UserManager.queryUser()--->username" + username);
- List userList = new ArrayList();
- userList.add("a");
- userList.add("b");
- userList.add("c");
- return userList;
- }
- }
Servlet 控制代码:
- package com.bjpowernode.servlet;
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- String requestURI = request.getRequestURI();
- System.out.println("request=" + requestURI);
- String path = requestURI.substring(requestURI.indexOf("/", 1), requestURI.indexOf("."));
- System.out.println("path=" + path);
- String username = request.getParameter("username");
- UserManager userManager = new UserManager();
- //userManager.addUser(username);
- String forward = "";
- if ("/servlet/delUser".equals(path)) {
- userManager.delUser(username);
- forward = "/del_success.jsp";
- } else if ("/servlet/addUser".equals(path)) {
- userManager.addUser(username);
- forward = "/add_success.jsp";
- } else if ("/servlet/modifyUser".equals(path)) {
- userManager.modifyUser(username);
- forward = "/modify_success.jsp";
- } else if ("/servlet/queryUser".equals(path)) {
- List userList = userManager.queryUser(username);
- request.setAttribute("userList", userList);
- forward = "/query_success.jsp";
- } else {
- throw new RuntimeException("请求失败");
- }
- request.getRequestDispatcher(forward).forward(request, response);
- }
这个 servlet 代码主要实现的功能判断是那个页面请求服务器做那些操作,之后调用业务逻辑实现相应业务操作。
配置 Servlet:
- xml version="1.0" encoding="UTF-8"?>
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
- test_Servlet
- index.html
- index.htm
- index.jsp
- default.html
- default.htm
- default.jsp
- TestServlet
- com.cjq.servlet.TestServlet
- TestServlet
- *.action
输出结果:
通过上面的示例已经对 MVC 设计模式有了初步的认识,其实这个示例是对 Struts 框架学习的基础,只有弄清楚了这个实例才能弄清楚 Struts 框架的实现原理和 Struts 框架使用。
那么我们怎么才能通过这个示例引入 Struts 框架呢?这个问题从 IF-Eles 开始。
首先我们看到了 TestServlet 中出现了许多 if-else 语句,这样是非常不稳定的,这样的程序是非常不灵活的,以后如果有变化,那么维护是非常差的;而且我们在 if-else 中出现了大量的字符串,这样在 coding 的时候会出现写错,这样无形中给调试带来了麻烦。所以去掉 if-else 成了我们重构的第一步,也是我们进行 Struts 框架学习的第一步。因为在 TestServlet 中出现了 If-Else 语句块,所以让程序变得不再灵活,让应付需求变化时变得笨拙。所以就承接上篇文章来重构一下 TestServlet 代码,主要是用继承多态来进一步对 TestServlet 进行重构。
下面进入重构阶段:
- package com.bjpowernode.servlet;
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- String requestURI = request.getRequestURI();
- System.out.println("request=" + requestURI);
- String path = requestURI.substring(requestURI.indexOf("/", 1), requestURI.indexOf("."));
- System.out.println("path=" + path);
- String username = request.getParameter("username");
- UserManager userManager = new UserManager();
- //userManager.addUser(username);
- String forward = "";
- if ("/servlet/delUser".equals(path)) {
- userManager.delUser(username);
- forward = "/del_success.jsp";
- } else if ("/servlet/addUser".equals(path)) {
- userManager.addUser(username);
- forward = "/add_success.jsp";
- } else if ("/servlet/modifyUser".equals(path)) {
- userManager.modifyUser(username);
- forward = "/modify_success.jsp";
- } else if ("/servlet/queryUser".equals(path)) {
- List userList = userManager.queryUser(username);
- request.setAttribute("userList", userList);
- forward = "/query_success.jsp";
- } else {
- throw new RuntimeException("请求失败");
- }
- request.getRequestDispatcher(forward).forward(request, response);
- }
- }
首先我们看到了在每个语句块中都出现了给 forward 赋值,其实也就是给页面跳转的路径赋值,针对每个请求路径判断来赋值跳转路径。另外每个 IF-Else 语句块中都有业务处理,我们要把这些业务处理分别放到类里面,让职责更加单
一,这样更加符合面向对象的思路。
就从这里我们开始重构,我们可以将这个跳转路径和业务逻辑封装起来。
既然封装,那么我们就抽象出来一个借口,主要完成一个方法,这个方法主要的功能就是要完成业务逻辑封装和路径跳转的返回。随后建立四个类,主要实现相应的增删改查的业务处理和处理之后的跳转路径返回。
代码如下:
接口 Action:
- package com.bjpowernode.servlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public interface Action {
- public String execute(HttpServletRequest request,HttpServletResponse response)
- throws Exception;
- }
增删改查实现类:
添加用户实现类:
- package com.bjpowernode.servlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class AddUserAction implements Action {
- public String execute(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- String username=request.getParameter("username");
- UserManager userManager=new UserManager();
- userManager.addUser(username);
- return "/add_success.jsp";
- }
- }
删除用户实现类:
- package com.bjpowernode.servlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class DelUserAction implements Action {
- public String execute(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- String username=request.getParameter("username");
- UserManager userManager=new UserManager();
- userManager.delUser(username);
- return "/del_success.jsp";
- }
- }
更新用户实现类:
- package com.bjpowernode.servlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class ModifyUserAction implements Action {
- @Override
- public String execute(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- String username=request.getParameter("username");
- UserManager userManager=new UserManager();
- userManager.modifyUser(username);
- return "/modify_success.jsp";
- }
- }
查询用户实现类:
- package com.bjpowernode.servlet;
- import java.util.List;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class QueryUserAction implements Action {
- @Override
- public String execute(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- String username=request.getParameter("username");
- UserManager userManager=new UserManager();
- List userList=userManager.queryUser(username);
- request.setAttribute("userList", userList);
- return "/query_success.jsp";
- }
- }
TestServlet 类重构如下:
- package com.bjpowernode.servlet;
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- String requestURI = request.getRequestURI();
- System.out.println("request=" + requestURI);
- String path = requestURI.substring(requestURI.indexOf("/", 1), requestURI.indexOf("."));
- System.out.println("path=" + path);
- Action action = null;
- if ("/servlet/delUser".equals(path)) {
- action = new DelUserAction();
- } else if ("/servlet/addUser".equals(path)) {
- action = new AddUserAction();
- } else if ("/servlet/modifyUser".equals(path)) {
- action = new ModifyUserAction();
- } else if ("/servlet/queryUser".equals(path)) {
- action = new QueryUserAction();
- } else {
- throw new RuntimeException("请求失败");
- }
- String forward = null;
- try {
- forward = action.execute(request, response);
- } catch(Exception e) {
- e.printStackTrace();
- }
- request.getRequestDispatcher(forward).forward(request, response);
- }
- }
运行结果:
这样 TestServlet 类虽然没有彻底去掉 If-Else,但是这样的代码变得更加简练,利用多肽实现业务逻辑处理和路径跳转返回。职责更加清晰,让维护变得更加轻松。
- package com.bjpowernode.servlet;
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- String requestURI = request.getRequestURI();
- System.out.println("request=" + requestURI);
- String path = requestURI.substring(requestURI.indexOf("/", 1), requestURI.indexOf("."));
- System.out.println("path=" + path);
- Action action = null;
- if ("/servlet/delUser".equals(path)) {
- action = new DelUserAction();
- } else if ("/servlet/addUser".equals(path)) {
- action = new AddUserAction();
- } else if ("/servlet/modifyUser".equals(path)) {
- action = new ModifyUserAction();
- } else if ("/servlet/queryUser".equals(path)) {
- action = new QueryUserAction();
- } else {
- throw new RuntimeException("请求失败");
- }
- String forward = null;
- try {
- forward = action.execute(request, response);
- } catch(Exception e) {
- e.printStackTrace();
- }
- request.getRequestDispatcher(forward).forward(request, response);
- }
- }
解决字符串问题,当然就要用到配置文件了,用到配置文件就要有用来读取配置文件的相关的类和方法,这里就用 dom4j 中的类来读取配置文件,这里的配置文件的书写是有点逻辑上的难度的。
我们来看 TestServlet 中的代码,我们要在这个 testservlet 中实现读取配置文件和 path 比较,还有利用多肽实例化相应的实现类,最后通过实例化的实现类的方法来返回跳转路径,最终跳转到相应的页面。
所以我们的配置文件就要不仅配上 testservlet 中出现的字符串,还要配置相应的 Action 接口的实现类(我们可以利用反射来实例化该类的对象,进而使用这个类的所有属性和方法),另外还有跳转路径字符串。这样我们的配置文件就变成了如下代码所示:
- xml version="1.0" encoding="UTF-8"?>
- path="/servlet/delUser" type="com.cjq.servlet.DelUserAction">
- name="success">/del_success.jsp
- name="error">/del_error.jsp
- path="/servlet/addUser" type="com.cjq.servlet.AddUserAction">
- name="success">/add_success.jsp
- name="error">/add_error.jsp
- path="/servlet/modifyUser" type="com.cjq.servlet.ModifyUserAction">
- name="success">/modify_success.jsp
- name="error">/modify_error.jsp
- path="/servlet/queryUser" type="com.cjq.servlet.QueryUserAction">
- name="success">/query_success.jsp
- name="error">/query_error.jsp
我们有了配置文件之后就要想法通过相关类读取,并且实现相应的功能。所以这里用 dom4j 来读取完成。其实如果能把这个逻辑捋顺之后就能发现,其实懂我们利用 dom4j 读取完配置文件的时候,我们是取得的是一个配套的匹配路径字符串、相应业务逻辑类还有处理业务逻辑之后跳转页面路径字符串。这样我们就能直截了当的去掉了 if-else。(这里可能逻辑上会出现一些困难,但是看到下面的重构之后的 testservlet 中的代码和读取配置文件之后的代码就会一目了然)。
现在等待解决的问题就是我们要把从配置文件取得的一整套内容放到那里,当然这是毋庸置疑的要放到类中。所以我们就建立一个 ActionMapping 类来放我们的那一整套内容。
ActionMapping 中的代码如下:
- package com.bjpowernode.servlet;
- import java.util.Map;
- public class ActionMapping {
- private String path;
- private Object type;
- private Map forwardMap;
- public String getPath() {
- return path;
- }
- public void setPath(String path) {
- this.path = path;
- }
- public Object getType() {
- return type;
- }
- public void setType(Object type) {
- this.type = type;
- }
- public Map getForwardMap() {
- return forwardMap;
- }
- public void setForwardMap(Map forwardMap) {
- this.forwardMap = forwardMap;
- }
- }
现在 ActionMapping 类已经有了,剩下的工作就是要利用 dom4j 来读取配置文件类,具体代码如下:
- package com.bjpowernode.servlet;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import org.dom4j.Document;
- import org.dom4j.DocumentException;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- public class XmlConfigReader {
- private static XmlConfigReader instance = new XmlConfigReader();
- ActionMapping actionMapping = new ActionMapping();
- private Document doc;
- private Map actionMap = new HashMap();
- private XmlConfigReader() {
- try {
- SAXReader reader = new SAXReader();
- InputStream in =Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml");
- doc = reader.read( in );
- } catch(DocumentException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- public ActionMapping getActionMapping(String path) {
- synchronized(this) {
- Object type = null;
- /*if(action.containsKey(path)){
- type=action.get(path);
- }*/
- Element eltAction = (Element) doc.selectObject("//action[@path=\"" + path + "\"]");
- try {
- type = Class.forName(eltAction.attributeValue("type")).newInstance();
- } catch(Exception e) {
- e.printStackTrace();
- }
- Element eltForwards = eltAction.element("forward");
- for (Iterator iter = eltForwards.elementIterator(); iter.hasNext();) {
- Element eltForward = (Element) iter.next();
- actionMap.put(eltForward.attributeValue("name"), eltForward.getTextTrim());
- }
- actionMapping.setPath(path);
- actionMapping.setType(type);
- actionMapping.setForwardMap(actionMap);
- return actionMapping;
- }
- }
- public static synchronized XmlConfigReader getInstance() {
- return instance;
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- ActionMapping actionMapping = XmlConfigReader.getInstance().getActionMapping("/servlet/delUser");
- System.out.println(actionMapping.getPath());
- System.out.println(actionMapping.getType());
- System.out.println(actionMapping.getForwardMap().toString());
- }
- }
我们通过返回 ActionMapping 来动态创建出 action 相应的实现类,进而完成业务逻辑和页面跳转,重构之后的 TestServlet 代码如下:
- package com.bjpowernode.servlet;
- import java.io.IOException;
- import java.util.List;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class TestServlet extends HttpServlet {
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- String requestURI = request.getRequestURI();
- System.out.println("request=" + requestURI);
- String path = requestURI.substring(requestURI.indexOf("/", 1), requestURI.indexOf("."));
- System.out.println("path=" + path);
- String forward = "";
- ActionMapping actionMapping = XmlConfigReader.getInstance().getActionMapping(path);
- Action action = (Action) actionMapping.getType();
- try {
- forward = action.execute(request, response);
- } catch(Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- request.getRequestDispatcher(forward).forward(request, response);
- }
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
- IOException {
- doGet(request, response);
- }
- }
我们可以清晰的看到 if-else 已经没有了,字符串也已经没有了。通过这篇文章对 if-else 还有字符串问题的解决,又一次重构了 testservlet 代码,程序相对灵活许多。通过这一次的重构,我们已经看到了 struts 框架的雏形,
来源: http://www.phperz.com/article/17/1207/354140.html