MVC模式的讨论与struts1.x和Struts2的比较
一、先看一个简单的jsp实现登录的程序
1、login.jsp
<%@ page contentType="text/html;charset=GBK"%> <HTML> <BODY> <form action="loginAction.jsp" method="post"> <table> <tr> <td>用户名:</td> <td><input type="text" name="name"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password" ></td> </tr> <tr> <td><input type="submit" value="提交"></td> </tr> </table> </form> </BODY> </HTML> |
2、loginAction.jsp
逻辑判断的页面
<%@ page contentType="text/html;charset=GBK"%> <% String username=request.getParameter("name"); String password=request.getParameter("password"); if(username.equals("mkf")&&password.equals("mkf")) { %> <jsp:forward page="/success.jsp"></jsp:forward> <% }else { %> <jsp:forward page="/error.jsp"></jsp:forward> <% } %> |
3、登录成功后的页面:
<%@ page contentType="text/html;charset=GBK"%> <html> <body> <h1>success</h1> </body> </html> |
4、登录失败后的页面
<%@ page contentType="text/html;charset=GBK"%> <html> <body> <H1>error</H1> </body> </html> |
总结:
Model 1模式:
Model 1模式的实现比较简单,适用于快速开发小规模项目。但从工程化的角度看,它的局限性非常明显:JSP页面身兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用性非常低,增加了应用的扩展性和维护的难度。
|
二、引入servlet后
package demo;
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 LoginAction extends HttpServlet { private static final long serialVersionUID = 1L ;
public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException { String username=request.getParameter("name"); String password=request.getParameter("password"); if(username.equals("mkf")||password.equals("mkf")) { response.sendRedirect(request.getContextPath()+"/success.jsp"); }else { response.sendRedirect(request.getContextPath()+"/error.jsp"); } } }
|
总结:model2
Model 2下JSP不再承担控制器的责任,它仅仅是表现层角色,仅仅用于将结果呈现给用户,JSP页面的请求与Servlet(控制器)交互,而Servlet负责与后台的JavaBean通信。在Model 2模式下,模型(Model)由JavaBean 充当,视图(View)由JSP页面充当,而控制器(Controller)则由Servlet充当。Model 2下JSP不再承担控制器的责任,它仅仅是表现层角色,仅仅用于将结果呈现给用户,JSP页面的请求与Servlet(控制器)交互,而Servlet负责与后台的JavaBean通信。
|
什么是框架?
框架是一个可复用的设计构件,它规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法。
为什么要用框架?
因为软件系统发展到今天已经很复杂了,特别是服务器端软件,设计到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。而且框架一般是成熟,稳健的,他可以处理系统很多细节问题,比如,事物处理,安全性,数据流控制等问题。还有框架一般都经过很多人使用,所以结构很好,所以扩展性也很好,而且它是不断升级的,你可以直接享受别人升级代码带来的好处。
三、Struts1.x与Struts2的比较:
1、struts1.x体系结构
|
LoginAction:
package demo;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping;
public class LoginAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
LoginForm user = (LoginForm) form; String username = user.getName(); String password = user.getPassword(); if (username.equals("mkf") && password.equals("mkf")) { return mapping.findForward("success"); } else { return mapping.findForward("error"); } } } |
LoginForm:
package demo; import org.apache.struts.action.ActionForm;
public class LoginForm extends ActionForm {
private static final long serialVersionUID = 1L ; private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } |
看一下struts-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config> <form-beans> <form-bean name="loginForm" type="demo.LoginForm"> <form-property name="name" type="java.lang.String"/> <form-property name="password" type="java.lang.String"/> </form-bean> </form-beans> <action-mappings> <action path="/login" type="demo.LoginAction" name="loginForm" scope="request" input="/login.jsp"> <forward name="success" path="/success.jsp"></forward> <forward name="error" path="/error.jsp"></forward> </action> </action-mappings> </struts-config>
|
(1)为什么需要FormBean?
每一个FormBean 都必须继承ActionForm类,FormBean是对页面请求的封装。即把HTTP request 封装在一个对象中,需要说明的一点就是多个HTTP request可以共用一个FormBean,便于维护和重用。
(2)FormBean所带给我们的问题是什么?
(3)为什么要有配置文件?
让我欢喜让我忧!
2、Strust2的体系结构
|
(1) 核心控制器FilterDispatcher根据请求决定调用合适的Action。
(2) WebWork的拦截器链自动对请求应用通用功能,例如workflow、validation或文件上传等功能。
(3) 回调Action的execute方法,该execute方法先获取用户请求参数,然后执行某种数据库操作,既可以是将数据保存到数据库,也可以从数据库中检索信息。实际上,因为Action只是一个控制器,它会调用业务逻辑组件来处理用户的请求。
(4) Action的execute方法处理结果信息将被输出到浏览器中,可以是HTML页面、图像,也可以是PDF文档或者其他文档。此时支持的视图技术非常多,既支持JSP,也支持Velocity、FreeMarker等模板技术。
LoginAction:
package demo;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport { private static final long serialVersionUID = 1L ;
private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute() { if(name.equals("mkf")&&password.equals("mkf")) { return SUCCESS; }else { return ERROR; } } } |
struts.xml
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <include file="struts-default.xml"/> <package name="demo" extends="struts-default"> <action name="Login" class="demo.Login"> <result name="input">/login.jsp</result> <result name="succes">/success.jsp</result> <result name="error">/error.jsp</result> </action> </package> </struts> |
struts1.x与struts2的Action的比较:
特征 | Struts1.x | Struts2 |
Action | Struts1.x要求Action类继承一个抽象基类。Struts1.x的一个普遍问题是使用抽象类编程而不是接口。 | Struts 2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现 常用的接口。Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的Action对象。 |
Servlet依赖 | Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。 | Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。 |
可测试性 | 测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得测试要依赖于容器)。不方便测试。 | Struts 2 Action可以通过初始化、设置属性、调用方法来测试。 |
FormBean | Struts要求有FormBean对应每一个表单,而且FormBean必需继承抽象类ActionForm。 | 能够动态的收集web的数据然后再赋值给bean。它也可以使用FormBean的形式,FormBean可以是普通的DTO和域对象,它不用重新根据域对象来生成新的FormBean,也不需继承抽象类ActionForm。 |