Struts2 学习笔记一
Struts:Jakarta项目 -> Apache软件基金会开源子项目 -> Struts
Struts是流行和成熟的基于MVC设计模式的Web应用程序框架。
使用Struts的目的是为了帮助我们减少运用MVC设计模式来开发Web应用的时间。
MVC是模型视图控制器,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方式组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
流程:用户通过视图输入,通过Controller控制器将用户输入的指令和数据传递给业务模型,Model模型进行业务逻辑判断、数据库存取,选择不同View视图显示反馈给用户。
MVC三层架构:
- View 视图层 展示数据给用户
- Control 控制层 控制数据流图
- Model 模型层 增删改查
Apache Struts2环境需求:
- Servlet API 2.*
- JSP API 2.*
- Java 5以上
搭建Struts2环境步骤
1.引用Jar包
https://struts.apache.org/download.cgi
需要引入以下jar包:
- commons-fileupload-1.3.2.jar
- commons-io-2.2.jar
- commons-lang3-3.2.jar
- commons-logging-1.1.3.jar
- freemarker-2.3.22.jar
- javassist-3.11.0.GA.jar
- ogln-3.0.19.jar
- struts2-core-2.3.31.jar
- xwork-core-2.3.31.jar
2.配置web.xml
<filter><!--过滤器-->
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<!--过滤路径-->
</filter-mapping>
3.配置strut.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!--配置映射 加入action-->
<package name="default" namespace="/" extends="struts-default">
<action name="helloworld" class="com.imooc.action.HelloWorldAction">
<result>/result.jsp</result>
</action>
</package>
</struts>
Struts2的工作原理及文件结构
web.xml:任何MVC框架都需要与Web应用整合,这就不得不借助于web.xml文件,只有配置在web.xml文件中Servlet才会被应用加载。通常所有的MVC框架都需要Web应用加载一个核心控制器,对于Struts2框架而言,需要加载StrutsPrepareAndExecuteFilter,只要Web应用负责加载StrutsPrepareAndExecuteFilter。StrutsPrepareAndExecuteFilter将加载Struts2框架。
struts.xml:Struts2的核心配置文件,在开发过程中利用率最高。该文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等。
包含内容:
- 全局属性
- 用户请求和Action之间的对应关系
- Action可能用到的参数和返回结果
- 各种拦截器的配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- include节点是struts2中组件化的方式, 可以将每个功能模块独立到一个xml配置文件中,然后用include节点引用 -->
<include file="struts-default.xml"></include>
<!--
package提供了将多个Action组织为一个模块的方式,package的名字必须是唯一的。
package可以扩展,当package扩扎自另一个package时,该package会在本身配置的基础上加入扩展的package的配置,
父package必须在子package前配置
name:package名称
extends:继承的父package名称
abstract:设置package的属性为抽象,true/false,此时抽象的package不能定义action
namespace:定义package命名空间,该命名空间影响到url的地址,
例如此命名空间为/test时,访问的地址是http://localhost:8080/struts2/test/xx.action
-->
<package name="com.kay.struts2" extends="struts-default.xml" abstract="false" namespace="/test">
<interceptors>
<!-- 定义拦截器 name:拦截器名称 class:拦截器类路径 -->
<interceptor name="timer" class="com.kay.timer"></interceptor>
<interceptor name="logger" class="com.kay.logger"></interceptor>
<!-- 定义拦截器栈 -->
<interceptor-stack name="mystack">
<interceptor-ref name="timer"></interceptor-ref>
<interceptor-ref name="logger"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 定义默认的拦截器,每个Action都会自动引用,如果Action中引用了其他的拦截器,默认的拦截器将无效 -->
<default-interceptor-ref name="mystack"></default-interceptor-ref>
<!-- 全局result配置 -->
<global-results>
<result name="input">/error.jsp</result>
</global-results>
<!--
一个Action可以多次被映射(只要action配置中的name不同)
Action配置
name:action的名称 http://localhost:8080/ProjectName/hello.action
class:对应类的路径
method:调用action中的方法名
-->
<action name="hello" class="com.kay.struts2.Action.LoginAction">
<!-- 引用拦截器 name:拦截器的名称或者拦截器栈的名称 -->
<interceptor-ref name="timer"></interceptor-ref>
<!--
节点配置 name:result名称,和action中返回值相同
type:result的类型,不写则选用superpackage的type
struts-default.xml中的默认为dispatcher
-->
<result name="success" type="dispatcher">/talk.jsp</result>
<!--
参数设置
name:对应action中的get/set方法
-->
<param name="url">www.baidu.com</param>
</action>
</package>
<!-- 定义全局属性,与struts.properties中为相同作用 -->
<constant name="struts.i18n.reload" value="true"></constant>
</struts>
struts.properties:Struts2框架的全局属性文件,自动加载。文件位置与strurs.xml相同即可。该文件包含很对key-value对。该文件完全可以配置在struts.xml文件中,使用constant元素。
示例:
#指定默认编码集,对于请求参数中带有中文的情况应该设置为GBK或GB2312,默认值为UTF-8
struts.i18n.encoding=UTF-8
#是否每次HTTP请求到达时,都重新加载国际化资源文件,默认为false
struts.i18n.reload=true
#是否使用struts2的开发者模式,可以获得更多的报错信息,便于调试。在开发阶段设置为true,默认为false
struts.devMode=true
#指定后缀后为.action形式的请求可被struts2处理,可配置多个请求后缀,比如.do,.struts2等,配置时对个后缀名用逗号隔开
struts.action.extension=action,do,struts2
#配置服务器运行时的端口号,一般情况下该属性不修改,如果端口号被占用则重新分配端口号,默认80
struts.url.http.port=80
访问Servlet API
- ActionContext
- 实现***Aware接口
- ServletActionContext
Action搜索顺序
例如:http://localhost:8080/struts2/path1/path2/paht3/student.action
第一步:判断package是否存在,如path1/path2/path3/
第二步:如果package存在,判断action是否存在,如果action不存在则去默认namespace的package里面寻找action,如果仍未找到则报错
第三步:如果package不存在,检查上一级路径的package是否存在(直到默认namespace),返回第一步,如果最后仍未找到,则报错
动态方法调用
为了解决一个action对应对个请求的处理,以免action太多。
- 指定method的属性:在Action类中添加方法,在struts.xml中添加对应的action,并指定对应的方法以及跳转页面
public String add() {
return SUCCESS;
}
public String update() {
return SUCCESS;
}
<action name="addAction" method="add" class="com.imooc.action.HelloWorldAction">
<result>/add.jsp</result>
</action>
<action name="updateAction" method="update" class="com.imooc.action.HelloWorldAction">
<result>/update.jsp</result>
</action>
- 感叹号方式(不推荐使用):在Action类中添加方法,并返回result的名称,在struts.xml文件中添加常量struts.enable.DynamicMethodInvocation,在Action标签中加入不同的result,并加上相应的名称。在使用浏览器访问时,格式如下:http://localhost:8080/HelloWorld/helloworld!add.action
public String add() {
return "add";
}
public String update() {
return "update";
}
<package name="default" namespace="/" extends="struts-default">
<action name="helloworld" class="com.imooc.action.HelloWorldAction">
<result>/result.jsp</result>
<result name="add">/add.jsp</result>
<result name="update">/update.jsp</result>
</action>
</package>
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
- 通配符方式(官方推荐使用的方式):在Action类中添加方法,并返回result的名称,在action标签中配置method通配符,并在result中使用通配符。浏览器访问示例:http://localhost:8080/HelloWorld/helloworld_add.action
<action name="helloworld_*" method="{1}" class="com.imooc.action.HelloWorldAction">
<result>/result.jsp</result>
<result name="add">/{1}.jsp</result>
<result name="update">/{1}.jsp</result>
</action>
指定多个配置文件
<include file="helloworld.xml"></include>
默认Action
当访问的action不存在时,访问默认action
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/error.jsp</result>
</action>
Struts2的后缀
- 方法一:在struts.xml中配置
<!-- 更改后缀名 当value为空时或不设置参数时,访问时不需要后缀名 -->
<constant name="struts.action.extension" value="html,do"></constant>
- 方法二:在struts.properties中配置
struts.action.extension=action,do,struts2
- 方法三:在web.xml中配置
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
<init-param>
<param-name>struts.action.extension</param-name>
<param-value>do</param-value>
</init-param>
</filter>
接收参数
- 使用action的属性接收参数
- 使用Domain接收参数
<form action="LoginAction.action" method="post">
用户名:<input type="text" name="user.username">
密码:<input type="password" name="user.password">
<input type="submit" value="提交">
</form>
public class LoginAction extends ActionSupport {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String login() {
System.out.println(user.getUsername());
return SUCCESS;
}
}
- 使用ModelDriven接收参数
<form action="LoginAction2.action" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
book1:<input type="text" name="bookList[0]">
book2:<input type="text" name="bookList[1]">
book3:<input type="text" name="bookList[2]">
<br>
user1:<input type="text" name="user[0].username">
user2:<input type="text" name="user[1].username">
<input type="submit" value="提交">
</form>
public class LoginAction2 extends ActionSupport implements ModelDriven<User> {
private User user = new User(); // 使用ModelDriven必须实例化对象
public String login() {
System.out.println(user.getUsername());
System.out.println(user.getBookList().get(0));
System.out.println(user.getBookList().get(1));
System.out.println(user.getBookList().get(2));
System.out.println(user.getUser().get(0).getUsername());
System.out.println(user.getUser().get(1).getUsername());
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
- request
处理结果类型
Struts2处理流程:用户请求 -> Struts框架解析 -> 匹配到对应的控制器(Action) -> Action将处理结果返回Struts2框架 -> 返回视图资源
Struts1返回ActionForward,Struts2返回String字符串
<action name="LoginAction" method="login" class="com.imooc.action.LoginAction">
<result name="success">/success.jsp</result>
<!--
result元素中的name是result元素的逻辑视图名称
如果省略name的值,则默认name的值为success
/success.jsp为绝对路径
success.jsp为相对路径
-->
</action>
处理结果类型如下:com.opensymphony.xwork2.Action(位置)
- SUCCESS:Action正确的执行完成,返回相应的值,success是name属性的默认值
- NONE:表示Action正确的执行完成,但是并不需要返回视图
- ERROR:表示Action执行失败,返回到错误处理视图
- LOGIN:Action因为用户没有登录的原因没有正确执行,将返回该登录视图,要求用户登录验证
- INPUT:Action的执行,需要从前端界面获取参数,INPUT就是代表这个参数输入的界面,一般在应用中,会对这些参数进行验证,如果没有验证通过,将自动返回到该视图
处理结果是在struts.xml使用<result />
标签配置结果。根据位置的不同,分为两种结果:
- 局部结果:将
<result />
作为<action />
元素的子元素 - 全局结果:将
<result / >
作为<global-result />
元素的子元素配置
<package name="">
<global-results>
<result name="ERROR404">/error404.jsp</result>
</global-results>
</package>
<result />
标签的子标签<param>
具有两个属性:
- location:该属性定义了该视图对应的实际视图资源
- parse:该参数指定是否可以在实际视图名字中使用OGNL(Object-Graph Navigation Language)表达式
type属性的默认值为dispatcher,这个类型支持JSP视图技术。