Struts简介、原理及简单实现
struts简介
Struts是Apache软件基金会(ASF)赞助的一个开源项目。它最初是jakarta项目中的一个子项目,并在2004年3月成为ASF的顶级项目。它通过采用JavaServlet/JSP技术,实现了基于JavaEEWeb应用的MVC设计模式的应用框架,是MVC经典设计模式中的一个经典产品。
Struts发展历史
Struts是作为ApacheJakarta项目的组成部分,项目的创立者希望通过对该项目的研究,改进和提高JavaServerPages、servlet、标签库以及面向对象的技术水准。
Struts这个名字的来源于在建筑和旧式飞机中使用的支持金属架。之所以这个框架叫做“struts”,是为了提醒我们记住那些支撑我们房屋,建筑,桥梁,甚至我们踩高跷的基础支撑。这也是解释struts在开发web应用程序中所扮演的角色的精彩描述。
Struts的含义是”支柱,枝干”,它的目的是为了减少程序开发的时间,项目的创建者认为JSP,servlet的存在虽然可以帮助用户解决大部分问题,但是由于它们的编码对项目的开发带来了许多的不方便,可重用性也差,所以struts应运而生,帮助用户在最短的时间内解决这些问题。Struts框架提供如下服务:
(1)作为控制器的Servlet。
(2)提供大量的标签库。
(3)提供了用于国际化的框架,利用不同的配置文件,可以帮助用户选择合适自己的语言。
(4)提供了JDBC的实现,来定义数据源和数据库连接池。
(5)XML语法分析工具。
(6)文件下载机制。
Struts原理
Struts是对JSPModel2设计标准的一种实现,下面分别从模型(Model)、视图(view)和控制器3个部分介绍Struts的体系结构和工作原理。调用流程如下所示(图1.1)。

图1.1
(1)视图(view)
在Struts中,视图层包含两个部分,JSP页面和ActionForm。
ActionForm封装了用户提交的表单信息,其实ActonForm本质上就是JavaBean,这些JavaBean中没有业务逻辑,只提供了所有属性的getter和setter方法,这些属性和用户表单中的输入项是一一对应的。在Struts中就是通过ActionForm把用户表单信息提交给控制器。
JSP页面是经典MVC中主要的视图组件,主要是信息显示和控制器处理结果显示的功能。
除了以上,struts还提供了一个强大的struts标签库,来帮助用户解决显示逻辑,并且利用ActonForm组件将信息传递到控制层。
(2)控制器(Controller)
在控制层,struts提供了一个控制器组件ActionServlet,它继承自HttpServlet,并重载了HttpServlet的doGet(),doPost()方法,可以接受HTTP的响应,并进行转发,同时还提供了使用XML进行转发Mapping(映射)的功能。
(3)模型(Model)
模型表示状态和业务逻辑的处理,在一般的web应用程序中,用JavaBean或者EJB来实现系统的业务逻辑。在Struts中,struts提供Action对象,来管理业务逻辑的调用,帮助用户分离业务逻辑,也就是说struts本身不实现业务逻辑,但可以调用已完成的业务逻辑。
Struts工作流程
Struts工作流程如下(图1.2)所示。

图1.2
ActionServlet是struts中核心的控制器,所有的用户请求都必须通过ActionServlet的处理,而struts-config.xml是struts中核心的配置文件,在这个文件中配置了用户请求URL和控制器Action的映射关系,ActionServlet通过这个配置文件把用户的请求发送到对应的控制器中。
在struts web应用程序中,当web应用程序启动的时候,就会初始化ActionServlet在初始化ActionServlet的时候会加载struts-config.xml配置文件,在加载成功后会把这些URL和控制器映射关系存放在ActionMapping对象或者其他对象中。当ActionServlet接收到用户请求的时候,就会按照下面的流程对用户请求进行处理。
(1)ActionServlet接收到用户的请求后,会根据请求URL寻找匹配的ActionMapping对象,如果匹配失败,说明用户请求的URL路径信息有误,所以返回请求路径无效的信息,当找到匹配的ActionMapping的时候,进入到下一步。
(2)当ActionServlet找到匹配的ActionMapping对象的时候,会根据ActionMapping中的映射信息判断对应的ActionForm对象是否存在,如果不存在对应的ActionForm对象就创建一个新的ActionForm对应,并把用户提交的表单信息保存到这个ActionForm对象中。
(3)在struts-config.xml中这个配置文件,可以配置表单是否需要验证,如果需要验证,就调用ActionForm中的validate()方法对用户输入的表单进行验证。
(4)如果ActionForm的validate()方法返回了ActionErrors对象,则表明验证失败,ActionServlet把这个页面返回到用户输入的界面,提示用户重新输入。如果方法的返回值为null,就表明验证已经通过,可以进入下一步处理。
(5)ActionServlet可以根据ActionMapping对象查找用户请求转发给哪个控制器Action,如果对应的Action对象不存在,就创建这个对象,并调用这个Action的excute()方法。
(6)业务逻辑控制器Action的execute()方法就会返回一个ActionForward对象,ActionServlet把控制器处理的结果转发到ActionForward对象指定的JSP页面。
(7)ActionForward对象指定的JSP页面根据返回的处理结果,用合适形式把服务器处理的结果展示给用户,到这里为止,一个客户请求的整个过程完毕。
以上初步struts框架进行了介绍,和对原理进行了简单的分析。至于struts是如何实现MVC的,ActionServlet属于Controller部分,Action和ActionForm属于Model层,还是Action属于Controller层,不同的人对struts有不同的理解。接下来真正的运用到实践中,在实践中深刻去体会,原理固然重要,重要的是运用,是能驾驭和使用这个框架。就像学习开车一样,不是一蹴而就的。
下面已登录为例,进行简单的实现。
Struts配置步骤总结如下(如图2.1):

1、 jar包拷贝
首先是建立java web项目,之后打开我们我们下载好strtus框架,Struts-1.2.9-bin文件夹和struts-1.2.9.src源文件文件夹。在bin文件夹中的lib文件中拷贝struts的jar包,拷贝到我们自己项目struts_login –>lib文件夹下(如图2.2)。

2、 web.xml文件配置
找到Struts-1.2.9-bin中Struts-1.2.9-bin-->webapps下的struts实例struts-blank中的struts-1.2.9-bin\webapps\struts-blank\WEB-INF下的web.xml文件,复制配置对ActionServlet的配置,粘贴到我们的项目struts_login的WEB-INF下的web.xml中,代码如下所示。主要是对struts自带的ActionServlet进行配置。
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet> <!--Standard Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3、在项目中建立自己的ActionForm
在项目中建立自己的ActionForm,继承struts框架中已经写好的ActionForm,在ActionForm设置用到的数据,并且要和我们界面上设置的名称一致。因为我们在提交表单的时候,所有的请求都会放到ActionForm中。建立登录的ActionForm,LoginActionForm.java代码如下所示。
package com.bjpowernode.struts;
import org.apache.struts.action.ActionForm; /**
* 登录ActionForm,负责表单收集数据.
* 表单的属性必须和ActionForm中的get和set的属性一致.
* @author summer
*
*/
public class LoginActionForm extends ActionForm { //用户名。
private String username;
//密码。
private String password; //设置密码。
public void setPassword(String password) {
this.password = password;
}
//得到用户名。
public String getUsername() {
return username;
}
//设置用户名。
public void setUsername(String username) {
this.username = username;
}
//得到密码。
public String getPassword() { return password;
} }
4、建立自己的Action
建立自己的Action,同时继承struts框架中的org.apache.struts.action.Action,重载父类的execute方法。在这里完成取出表单中的数据。通过CalActionFormcalForm= (CalActionForm)(CalActionForm)form;(struts框架中已经帮我们封装好了,我们去使用就可以了)来取得表单中的值。经过判断后,进行相应的操作,跳转到相应的页面。Action的功能是负责拿到表单数据和调用业务逻辑后进行页面跳转。建立登陆的Action类,LoginAction.java类,调用业务逻辑类UserManager的login方法。代码如下所示。
packagecom.bjpowernode.struts; importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse; importorg.apache.struts.action.Action;
importorg.apache.struts.action.ActionForm;
importorg.apache.struts.action.ActionForward;
importorg.apache.struts.action.ActionMapping; /**
*登录Action
*负责取得表单数据,调用业务逻辑,返回转向信息.
*
* @author summer
*
*/
public class LoginAction extends Action { @Override
public ActionForward execute(ActionMapping mapping,ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception { LoginActionForm laf = (LoginActionForm)form;
String username = laf.getUsername();
String password = laf.getPassword(); UserManager userManager = newUserManager();
//传递用户名和密码
try
{
userManager.login(username, password);
request.setAttribute("username", username);
return mapping.findForward("success");
}catch(UserNotFoundException e)
{
e.printStackTrace();
request.setAttribute("msg","用户不能找到,用户名称=[" +username +"+]");
}catch(PasswordErrorException e)
{
e.printStackTrace();
request.setAttribute("msg","密码错误");
} return mapping.findForward("error");
} }
5、建立struts-config.xml
作为Struts框架的核心描述,struts-config.xml可以说“一切尽在掌握”。它不但描述了MVC模型,定义所有视图层和控制层之间的接口(ActionForm),与控制层和模型层的接口(Action)进行结合,而且可以定义一些附加组件,如国际化信息资源排至文件,标签库信息等。
仍然是站在巨人的肩膀上,将我们下载的struts bin文件夹中的struts-config.xml文件复制到我们的项目的WEB-INF中,删除struts-config.xml中的注释部分。把Action和ActionForm配置起来。ActionForm放到<form-beans></form-beans>中,Action配置放到<action-mappings></action-mappings>中,struts-config.xml配置代码如下所示。
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"> <struts-config>
<form-beans>
<form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"/>
</form-beans> <action-mappings>
<action path="/login"
type="com.bjpowernode.struts.LoginAction"
name="loginForm"
scope="request"
>
<forward name="success" path="/login_success.jsp"/>
<forward name="error" path="/login_error.jsp"/>
</action>
</action-mappings>
</struts-config>
其中form-beans元素中可以定义0个或1个以上的form-bean元素,每个form-bean被认为是一个ActionForm对象,name属性表示form-bean元素的名称,type属性指定其类名和路径。
Action-mappings元素用来包含零到多个action,其子元素action负责具体映射的详细信息。在action-mapping元素中可以定义0个或1个以上的action元素。每个action元素接受path属性定义的请求,并映射到type属性所定义的具体action对象。在映射过程中,将name属性定义的actionform一并传过去,它有如下属性:
Parameter,scope两个属性指定了传送方式和范围,scope常用的值有两个“session”和“request”。
Validate属性指定了是否需要actionform的验证。
Forward元素,将请求success转发到”/login_success.jsp”页面。
6、业务逻辑类UserManager和自定义异常类
代码如下所示:
packagecom.bjpowernode.struts;
public class UserManager {
public void login(String username,String password)
{
if(!"admin".equals(username))
{
throw new UserNotFoundException();
}
if(!"admin".equals(password))
{
throw new PasswordErrorException();
}
}
}
自定义异常类UserNotFoundException和PasswordErrorException代码如下所示。
packagecom.bjpowernode.struts;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException() {
}
public UserNotFoundException(Stringmessage) {
super(message);
}
public UserNotFoundException(Throwable cause) {
super(cause);
}
public UserNotFoundException(String message,Throwable cause) {
super(message, cause);
}
}
packagecom.bjpowernode.struts;
public class PasswordErrorException extends RuntimeException {
public PasswordErrorException() {
}
public PasswordErrorException(String message) {
super(message);
}
public PasswordErrorException(Throwable cause) {
super(cause);
}
public PasswordErrorException(String message,Throwable cause) {
super(message, cause);
}
}
7、视图jsp页面调用。
登录界面login.jsp,错误显示界面login_error.jsp,登录成功界面login_success.jsp。代码如下所示。
<%@pagelanguage="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPEhtml PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Inserttitle here</title>
</head>
<body>
<form action="login.do" method="post">
用户:<inputtypeinputtype="text" name="username"><Br>
密码:<inputtypeinputtype="password" name="password"></br>
<input type="submit" value="登录">
</form>
</body>
</html>
Login_success.jsp.
<%@page language="java"contentType="text/html;charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
${username},登录成功!
</body>
</html>
Login_error.jsp界面。
<%@page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE html PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
<%--
<%=request.getAttribute("msg") %>
--%> ${msg }
</body>
</html>
就这样我们实现了运用struts框架完成用户登录。就这样从初步学习到简单应用,随着应用的次数增多,我们会对struts理解越来越深刻,并且感受struts框架给我们带来的便捷。
Struts简介、原理及简单实现的更多相关文章
- RabbitMQ系列(二)深入了解RabbitMQ工作原理及简单使用
深入了解RabbitMQ工作原理及简单使用 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchange介绍 ...
- 深入解读RabbitMQ工作原理及简单使用
RabbitMQ系列目录 RabbitMQ在Ubuntu上的环境搭建 深入解读RabbitMQ工作原理及简单使用 Rabbit的几种工作模式介绍与实践 Rabbit事务与消息确认 Rabbit集群搭建 ...
- LeakCanary 内存泄漏 监测 性能优化 简介 原理 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- RxJava RxPermissions 动态权限 简介 原理 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Python之路——堡垒机原理及其简单实现
1 堡垒机基本概述 其从功能上讲,它综合了核心系统运维和安全审计管控两大主干功能,从技术实现上讲,通过切断终端计算机对网络和服务器资源的直接访问,而采用协议代理的方式,接管了终端计算机对网络和服务器的 ...
- 深入了解RabbitMQ工作原理及简单使用
深入了解RabbitMQ工作原理及简单使用 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器Exchange介绍 ...
- HBase笔记:对HBase原理的简单理解
早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...
- 编译原理(简单自动词法分析器LEX)
编译原理(简单自动词法分析器LEX)源程序下载地址: http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7 ...
- Optaplanner规划引擎的工作原理及简单示例(2)
开篇 在前面一篇关于规划引擎Optapalnner的文章里(Optaplanner规划引擎的工作原理及简单示例(1)),老农介绍了应用Optaplanner过程中需要掌握的一些基本概念,这些概念有且于 ...
随机推荐
- Codeforces 438D The Child and Sequence
题意:给定一个n个数的序列,完成以下3个操作: 1.给定区间求和 2.给定区间对x取模 3.单点修改 对一个数取模,这个数至少折半.于是我们记一个最大值max,如果x>max则不做处理. #in ...
- 小白的Python之路 day1 模块初识
模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,几乎你想实现的任何功能都有相应的Python库支持,以后的课程中会深入讲解常用到的各种库,现在,我们先来象征性的学2个简单的. ...
- Linux 两台服务器之间传输文件和文件夹
今天处理一个项目要迁移的问题,突然发现这么多图片怎么移过去,可能第一时间想到的是先从这台服务器下载下来,然后再上传到另外一台服务器上面去,这个方法确实是可行,但是实在是太费时间了,今天我就教大家怎么快 ...
- N卡全部历史驱动
记录一下寻找驱动方法 打开链接 http://www.geforce.cn/drivers/beta-legacy 默认搜索出来是10个,之后打开控制台输入如下内容回车显示全部(100,可以修改数字来 ...
- python用户管理系统
学Python这么久了,第一次写一个这么多的代码(我承认只有300多行,重复的代码挺多的,我承认我确实垃圾),但是也挺不容易的 自定义函数+装饰器,每一个模块写的一个函数 很多地方能用装饰器(逻辑跟不 ...
- 高版本号chrome安装flashplayer debuger后无法使用的问题
起因应该是苹果公司指出flash player的安全问题,还有各种原因导致google将在未来取消NPAPI的支持,所以fp们就悲剧了在高版本号chrome(42以上)默认是关闭外部安装的插件使用的, ...
- Matlab 2014b For Mac安装破解
1.Matlab 2014b 的安装和破解文件下载: 安装文件:http://www.cncrk.com/downinfo/80718.html 破解文件:http://pan.baidu.com/s ...
- flask框架-decorator装饰器
调用包: from functools import wraps 装饰器其实就是一个函数:参数是一个函数,返回值是一个函数 1.装饰器使用是通过@符号,在函数的上面 2.装饰器中定义的函数,要使用*a ...
- Struts2学习笔记整理(三)
Struts2的输入校验 之前对请求参数的输入校验一般分为两部分:1.客户端校验,也就是我们写js代码去对客户的误操作进行过滤 2.服务端校验, 这是整个应用组织非法数据的最后防线. Struts2 ...
- jQuery里使用setinterval
如果第一个参数是一个已写好的函数而不是匿名代码块,一定不要加引号,直接var ** = setinterval{myFunction ,500},只能这样,加括号会直接只调用一次,自然不行,加引号和括 ...