第一次(Struts2入门、基本配置)
一、Struts2入门。【
1、Struts2框架介绍《
(1)它是MVC的一个框架,它以前叫做WebWork框架。后面它被Apache(阿帕奇)和
Sun(丧)公司收购了,Apache公司是我们比较出名的一个公司。
你用的tomcat也是Apache下面的。Oracle和jdk是Sun下面的。收购以后就给它取
了一个名字叫Stsrus2。
(2)什么是MVC?{<1>它是一种三层加构“模型Model、视图View、控制器
Controller”的模型<2>登录是怎样直行流程?首先在login.jsp页面做一个请求
,然后
请求到控制器“Controller Filter”,控制器对你的登录里的用户名跟密码进行
判断,判断完了后它才决定到底是到这个欢迎页面还是到主页面还是返回过去。
在
这个数据处理过程当中它要用到MVC的一个流程。}》
2、Struts2工作流程《
(1)客户端浏览器发出HTTP请求.
(2)根据web.xml配置,该请求被FilterDispatcher接收
(3)根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,
将值注入给Aciton
(4)Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
(5)Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并
跳转到相应页面
(6)返回HTTP响应到客户端浏览器》
3、Struts官方地址《
http://struts.apache.org。Struts2它在Apache这个平台上它的服务器在国外,
所以去登录的时候可能会有点慢,这和你的网速是没有关系的。》】
二、基本配置【
1、使用Struts2开发程序的基本步骤。
(1)加载Struts2类库,把下面的9个包复制到web项目中的WebContent目录下的
WEB-INF中的lib中。《
下载jar包,导入Web工程。推荐去官方网站下载,不要去百度搜索,因为它会有
很多插件。在浏览器上打开http://struts.apache.org这个网站,然后在
打开Download这个按钮,打开以后看它的新版本是<例如:Struts 2.5.12>代表它
的版本是2.5,12是第12次修改。推荐不要下载最新版本,下载倒数第二个版本。
[例如:Struts 2.3.33:
[1]{Full Distribution:struts-2.3.33-all.zip(65MB)[PGP][MD5],Struts2所
有安装以后的文件jar包都在里面。}
[2]{Example[举例,案例] Applications:struts-2.3.33-apps.zip(35MB)[PGP]
[MD5],这里面有一些例子,比如注册这么简单的它里面一定也有。}
[3]{Essential Dependencies Only:struts-2.3.33-min-lib.zip(4MB)[PGP]
[MD5],这个就比较关键了,这个就是你在使用Struts2这个框架的时候你需要的
一些
包,大约有十几个包,我们一般在开发过程中会用这个。}
[4]{All Dependencies Only:struts-2.3.33-lib.zip(19MB)[PGP][MD5],这个是
struts2当中你在使用的一些特殊功能的一个支持包或叫扩张功能的包。}
[5]{Source:struts-2.3.33-src.zip(7MB)[PGP][MD5],这个是源代码,推荐下载
下来。}
[6]下载[3][5]就行了。点击就可以下载,不需要收费。下载完以后解压,大约有
9个jar包。
{<1>struts2-core-xxx.jar[Struts 2框架的核心类库,这个必须要有。]
<2>xwork-core-xxx.jar[XWork类库,Struts 2的构建基础]
<3>ognl-xxx.jar[Struts 2使用的一种表达式语言类库]<4>freemarker-xxx.jar
[Struts 2的标签模板使用类库]
<5>javassist-xxx.GA.jar[对字节码进行处理]<6>commons-fileupload-xxx.jar[
文件上传时需要使用]
<7>commons-io-xxx.jar[Java IO扩展。commons开头的包代表是公共的包。]
<8>commons-lang-xxx.jar[包含了一些数据类型的工具类]
<9>commons-logging-1.1.3.jar。库中包含很多jar包,但是并不是都需要导入到
项目中,因此只需要选择与项目功能实现相关的jar包导入即可。}
[7]打开MyEclipse,新建web项目{Ctrl+n/输入‘web’/Web Project/Next/
[Project name:struts2、Java EE version:JavaEE 6-Web 3.0、Java
version:1.7
、JSTL Version:<none>]/Next/Next/(勾选)Generate web.xml dep....[自动生
成一个web.xml]/Next/Finish}
[8]把下载的9个jar包复制到web项目中的WebContent目录下的WEB-INF中的lib中
。]》
(2)配置web.xml文件《
[1]在src中新建com.zking.test包,包中新建Test.java{package
com.zking.test;import
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
public class Test {public static void main(String[] args) {
//[导包的过程:StrutsPrepareAndExecuteFilter<Filter是过滤器,。Struts准
备和执行的过滤器/核心过滤器:StrutsPrepareAndExecuteFilters,Struts2要
启动就必须要这个东西>
在这里只要一个导包的过
程“org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilt
er;”》}}
[2]在WebContent下的WEB-INF中新建web.xml{在<web-app>标签中。...<!-- 配
置struts2的核心过滤器 -->
<filter><!--名字--><filter-name>struts2Filter</filter-name><!--名字所对
应的那个类--><filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter</filter-class></filter>
<filter-mapping><filter-name>struts2Filter</filter-name><url-
pattern>*.action</url-pattern></filter-mapping>}》
第一种:实现action接口《这种方法有它的局限性,就是Action里面只有execute
方法,而且必须使用这个方法》:
/**(3)开发视图层页面,也就是jsp文件。《
login.jsp{...<body><div align="Center"><!-- Login要跟struts.xml中的
<action name="Login">一样。-->
<form action="Login.action" method="post"><table><tr><td>用户名:
</td><td><input type="text" name="s_name"/> </td></tr><tr><td>密码:
</td>
<td><input type="password" name="s_pwd"/> </td></tr><tr
align="Center"><td colspan="2"><input type="submit" value="登录"/>
</td></tr>
</table></form></div></body></html>}》
(4)开发控制层Action[动作]《
在src中新建com.zking.action包,包中新建LoginAction.action{package
com.zking.action;import com.opensymphony.xwork2.Action;
/** 处理登录的action。*/public class LoginAction implements Action{//表
单的name属性值必须跟action中的属性值的名字一样,而且必须get/set封装。
private String s_name;private String s_pwd;//《get/set。》//《execute是
执行方法》public String execute() throws Exception {
System.out.println("到了LoginAction");//获取这两个值。
System.out.println("用户名:"+this.s_name);System.out.println("密
码:"+this.s_pwd);
//System.out.println(Actin.SUCCESS/Actin.NONE/Actin.ERROR);//<这个返回
值必须跟struts.xml中的<result name="success">一样。>return "success";}}
}》
(5)配置struts.xml文件[每一个框架都有一个配置文件]《
在src下面创建struts.xml文件{[1]Ctrl+n/输入'file'/File/Next/File
name:struts.xml[不要去改]/Finish。
[2]《<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!--name[名字可
随意],extends[它必须继承struts-default.xml<Libraries/Web App
Libraries/
struts2-core-2.3.33.jar下面。因为框架是别人的,所以要继承>]。namespace[
工作空间,这个"/"代表根目录,等一下去请求的时候它直接代表WebRoot]-->
<package name="defaultPackage" extends="struts-default"
namespace="/"><!-- name[名字可随意],用在loginjsp页面的form表单中的
action。
class[对应LoginAction类的全限命名]现在配置的LoginAction取了个名字叫
Login,等会根据Login来请求的时候就可以直接找到
com.zking.action.LoginAction。
UserAction里面的execute方法它会自动执行, 但也可以人为去设定。method[方
法的设定,它可以直接规定你进去到底执行的是哪个方法]-->
<action name="Login" class="com.zking.action.LoginAction"><!-- 找到之后
结果返回到welcome.jsp页面--><result name="success">welcome.jsp</result>
</action></package></struts>}》
(6)部署、运行项目《welcome.jsp{<body><h1>欢迎</h1></body>[发布Tomcat
。打开浏览器运行,输入用户名和密码看是否在控制台中打印用户名和密码]}》
**/
第二种:继承ActionSupport:
/**(3)在src中新建com.zking.entity,包中新建User.java{package
com.zking.entity;import java.io.Serializable;//Serializable序列化接口。
public class User implements Serializable{//表单的name属性值必须跟
action中的属性值的名字一样,而且必须get/set封装。
private String s_name;private String s_pwd;//无参构造。//《get/set。》}
}
(4)在src中新建com.zking.action包,包中新建UserAction.action{package
com.zking.action;import com.zking.entity.User;
import com.opensymphony.xwork2.Action;import
org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.ActionSupport;
/* * 处理登录的action。*/public class UserAction extends ActionSupport
{//用户对象属性。private User user;public User getUser(){return user;}
public void setUser(User user){this.user=user;}public UserAction()
{System.out.println("UserAction被实例化了。。。。");}
public String mylogin() throws Exception {System.out.println("到了
UserAction");//获取这两个值。System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());//将登录者信息放入
session 耦合方式。
ServletActionContext.getRequest().getSession().setAttribute("myUser",
this.user);return Action.SUCCESS;}
public String myreg() throws Exception {System.out.println("到了
LoginAction。。。。。。reg");System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());return
Action.SUCCESS;}}}
(5)配置struts.xml文件[每一个框架都有一个配置文件]《在src下面创建
struts.xml文件{[1]Ctrl+n/输入'file'/File/Next/File name:struts.xml[不
要去改]/Finish。
[2]《<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!--让struts2支
持动态方法调用--><constant name="struts.enable.DynamicMethodInvocation"
value="true" />
<package name="defaultPackage" extends="struts-default"
namespace="/"><action name="login" class="com.zking.action.UserAction">
<!-- 找到之后结果返回到welcome.jsp页面--><result
name="success">welcome.jsp</result></action></package></struts>}》
(6)login.jsp{...<body><div align="Center"><form action="login!
mylogin.action" method="post"><table><tr><td>用户名:</td>
<td><input type="text" name="user.s_name"/></td></tr><tr><td>密 码:
</td><td><input type="password" name="user.s_pwd"/></td></tr><tr
align="Center">
<td colspan="2"><input type="submit" value="登
录"/></td></tr></table></form></div></body></html>}
(7)welcome.jsp{<body><h1>欢迎。。。</h1>用户名:${myUser.s_name}
<br><a href="vip/myvip.jsp">去vip界面</a></body></html>}
(8)在WebContent下面建vip文件夹,myvip.jsp{<body>This is my JSP page.
<br></body>
[发布Tomcat。打开浏览器运行,输入用户名和密码看是否在控制台中打印用户名
和密码]}**/】
第二次(Struts2详细配置)
一、Action中属性的获取【(1)表单的name属性值必须跟action中的属性值名字
一样,而且必须封装(2)属性名-->action中属性名(3)属性对象名.属性名--
>action中属性】
二、在struts.xml下配置编码【<!--常量配置--><constant
name="struts.i18n.encoding" value="UTF-8"/>】
三、Action方法的动态调用【
A、要想使用动态调用,必须去打开‘<constant
name="struts.enable.DynamicMethodInvocation" value="true" />’动态调用
的开关,而且是在struts.xml里面通过一个常量配置。
动态语法《action名!方法名.action。举例:user!login.action 调用名字为
user的action下面的login方法{上面的第二种:继承ActionSupport用的就是!
的动态调用}》
B、通配符{*}形式的动态调用《<!--*代表所有的意思,可以是0个也可以是多个
。method=”{1}”里面的1代表第一个*的值--><action name= "*User" method=
”{1}”<result>{1}_success.jsp</result>》
举例:loginUser.action 调用名字为user的action下面的login方法。《在上面
的第二种:继承ActionSupport的基础上改。
(1)struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE
struts PUBLIC ……struts-2.0.dtd"><struts><!-- 让struts2支持动态方法调
用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"
/><package name="defaultPackage" extends="struts-default"
namespace="/">
<!-- 。UserAction里面的execute方法它会自动执行, 但也可以人为去设定,
method[方法的设定,它可以直接规定你进去到底执行的是哪个方法]-->
<action name="*User" class="com.zking.action.UserAction"
method="{1}"><!-- 登录成功:找到之后结果返回到welcome.jsp页面-->
<result name="success">welcome.jsp</result></action></package></struts>
}
(2)把login.jsp里面的form表单改为<form action="myloginUser.action"
method="post">》】
四、全局错误action请求结果配置【就是在这里你请求了action可能会有个请求
的错误,我们一般会给一个错误界面处理。
struts.xml{写在<package>标签里面的<action>上面。<!--action请求不存在的
配置。如果是error错误就跳到all_error.jsp页面-->
<global-results><result name="error" >all_error.jsp</result></global-
results>}】
五、Result常用的结果类型,即type属性【
A、dispatcher(默认){底层使用RequestDispatcher转发请求}
B、redirect{底层使用sendRedirect将请求重定向}
C、redirectAction{重定向到action}《举例:product.action?myName=
${user.name}&myPwd=${user.pwd}<result name="success"
type="redirectAction">
<param name="actionName">product</param><param name="myName">
${user.name}</param><param name="myPwd">${user.pwd}</param></result>》
】
六、注解形式的Struts2配置《重点。写法<@Action("user")>它是一种全新的映
射关系,它会根据你的注解的名字去自动帮你的某个Action去实例化。》【
1、在配置之前必须要导包《struts2-convention-plugin-2.3.33.jar》
2、Action配置《@ParentPackage(value="struts-default")[你的父包是谁,父
包都要继承一个“struts-default”。它还有很多个属性,如果只有一个的话
value可省略]
@NameSpaces("/一般写Action的类名,但首字母要小写"){工作空间} @Action("
请求的是哪个方法")》
3、示例:在上面的基础上改。《
(1)struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!
DOCTYPE..."><struts><constant
name="struts.enable.DynamicMethodInvocation" value="true"
/>
<package name="defaultPackage" extends="struts-default"
namespace="/"></package></struts>}
(2)login.jsp{……<body><div align="Center"><form
action="user/mylogin.action" method="post"><table><tr><td>用户名:
</td><td><input type="text"
name="user.s_name"/>
</td></tr><tr><td>密 码:</td><td><input type="password"
name="user.s_pwd"/> </td></tr><tr align="Center"><td colspan="2"><input
type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(3)UserAction.java{package com.zking.action;import
com.zking.entity.User;import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;import
org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;import
com.opensymphony.xwork2.ActionSupport;/* * 处理登录的action。*/
@ParentPackage(value="struts-default")@Namespace("/user")public class
UserAction extends ActionSupport{private User user;public User getUser
() {return user;}
public void setUser(User user) {this.user = user;}public UserAction()
{System.out.println("UserAction被实例化了。。。。");}
@Action(value="/mylogin",results={@Result
(name="success",location="/welcome.jsp"),@Result
(name="fail",location="/login_fail.jsp")})
public String mylogin() throws Exception {System.out.println("到了
UserAction");System.out.println("用户名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd
());ServletActionContext.getRequest().getSession().setAttribute
("myUser", this.user);return "success";}
public String myreg() throws Exception {System.out.println("到了
LoginAction。。。。。。reg");System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());return "toAction";}}
}》】
七、约定对Action的限制【
(1)约定Action类名:要求Action的命名必须以“Action”为后缀,例如:
UserAction、BookAction等等。可以使用下面常量来修改后缀限制:<constant
name="struts.convention.action.suffix" value="Action"/>
(2)约定Action包名:要求Action必须放到action、actions、struts、struts2
包中。例如:cn.itcast.action、cn.itcast.sturts、cn.itcast.action.user等
等。
可以使用下面常量来修改Actoin的包<constant
name="struts.convention.package.locators"
value="action,actions,struts,struts2"/>】
第三次(拦截器[Interceptor]+文件上传、下载)
一、struts2为什么用拦截器?【
1、拦截器[interceptor]是Struts2最强大的特性之一,也可以说是struts2的核
心,拦截器可以让你在Action和result被执行之前或之后进行一些处理。
同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很
多特性都是由拦截器来完成的。拦截是AOP的一种实现策略。
拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义
在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。
同时也是提供了一种可以提取action中可重用的部分的方式。
2、拦截器可以说相当于是个过滤器:就是把 不想要的或不想显示的内容给过滤
掉。拦截器可以抽象出一部分代码可以用来完善原来的action。
同时可以减轻代码冗余,提高重用率。比如在登入一个页面时,如果要求用户密
码、权限等的验证,就可以用自定义的拦截器进行密码验证和权限限制。
对符合的登入者才跳转到正确页面。这样如果有新增权限的话,不用在action里
修改任何代码,直接在interceptor里修改就行了。】
二、拦截器的优点?【
a:简化了Action的实现。拦截器能把很多功能从Action中独立出来,大量减少了
Action的代码。
b:功能更单一。按照上面的描述,把功能从Action中分离出来,分散到不同的拦
截器中,这样每个拦截器的功能,以及Action本身的功能就更单一了。
c:通用代码模块化。从Action中把功能分离出来,放到拦截器中去实现,这样能
把一些在多个Action中通用的代码进行模块化,封装在一个或者几个拦截器中。
d:提高重用性。当通用的功能代码被封装在拦截器中,实现了代码模块化过程之
后,就可以对不同的Action,根据功能需要,来配置相同的拦截器了。
e:实现AOP。
拦截器相比Filter具有更强大的功能,比如拦截器与Servlet的API无关,比如拦
截器可以访问到值栈等。】
三、Struts2的预定义拦截器?【
1、params拦截器{把请求参数设置进Action的相应属性,并自动进行类型转换}
2、staticParams拦截器{将struts.xml配置文件里定义的Action参数,设置到对
应的Action实例中,Action参数使用<param>标签,是<action>标签的子元素。
《<action name="hello" class="HelloAction"><param
name="account">test</param></action>》
这要求action中有一个account属性,并有相应的setter和getter方法,运行的时
候,action的account属性在初始化过后,会接到这里的赋值test。}
3、prepare拦截器{在action执行之前调用Action的prepare方法,这个方法是用
来准备action之前要做的工作,它要求用户必须实现
com.opensymphony.xwork2.Preparable接口。}
4、modelDriven拦截器{如果action实现了ModelDriven接口,它将getModel方法
取得的模型对象存入OgnlValueStack中。}
5、chain拦截器{chain拦截器,将前一个执行结束的Action属性设置到当前的
action中,它被用在ResultType为"chain"所指定的结果的Action中,
该结果Action对象会从值栈获得前一个Action对应的属性,它实现Action链之间
的数据传递。}
6、exception拦截器{在抛出异常的时候,这个拦截器起作用,任何应用都应该
引用这个拦截器,而且引用的时候,最好把它放在第一位,让它能捕获所有的异
常。}
7、validation拦截器{调用验证框架读取*-validation.xml文件,并且应用在这
些文件中声明的校验。}
8、token拦截器{核对当前Action请求(request)的有效标识,防止重复提交
Action请求,使用标签<s:token>可以生成表单令牌,该标签会在Session中设置
一个预期的值,
并且在表单中创建一个隐藏的input字段,Token拦截器会检查这个令牌,如果不
合法,将不会执行Action,这个拦截器是手工添加的,还需要一个
invalide.token的result。}
9、conversionError拦截器{用来处理框架进行类型转化(Type Conversion)时
的出错信息,它将存储在ActionContext中的类型转化错误信息转化成相应的
Action字段的错
误信息,保存在堆栈中。根据需要,可以将这些错误信息在视图中显示出来。}
10、fileUpload拦截器{用来处理上传文件}
11、workflow拦截器{Action默认的工作流,如果Action实现了Validateable接
口,那么interceptor会调用action的validate()方法,如果Action实现了
ValidateAware接口
,那么interceptor将会检查Action是否包含错误信息,如果包含错误信息,那么
Interceptor将会返回input,而不让Action继续执行。}
12、servletConfig拦截器{这个拦截器提供Action直接对Servlet API的调用,
把Servlet API的对象注入到Action中,包括ServletRequestAware,
ServletResponseAware
,ParameterAware,SessionAware和ApplicationAware}
13、timer拦截器{记录ActionInvocation剩余部分执行的时间,并作为日志信息
记录下来,便于寻找性能瓶颈。}
14、logger拦截器{在日志信息中输出要执行的Action信息,这样,在调试的时
候,就能很快的定位到这个对应的Action中了。}
15、tokenSession拦截器{扩展了token拦截器的功能,当提交无效的Action请求
标识时,它会跳转到第一次成功后的页面}】
四、struts2中拦截器实现的三种方式?【
1、实现Interceptor接口
2、继承AbstractInterceptor类
3、继承MethodFilterInterceptor类[当自定义拦截器配置了拦截参数时,自定义
拦截器必须使用该方法]
如:《<!-- 配置拦截器 --><interceptors><!-- 配置自定义拦截器,定义了一
个名为myInterceptor的拦截器 --><interceptor name="myInterceptor"
class="com.caokaiyuan.interceptor.MyInterceptor"></interceptor><!-- 配
置拦截器栈 --><interceptor-stack name="myStack"><interceptor-ref
name="defaultStack"/><!-- 加载默认拦截器 -->
<!-- 加载自定义拦截器 --><interceptor-ref name="myInterceptor"><!-- 配
置要拦截的方法;user,client为方法名 --><param
name="includeMethods">user,client</param>
<!-- 配置不需要拦截的方法;login为方法名 --><param
name="excludeMethods">login</param></interceptor-ref></interceptor-
stack></interceptors>》
此时必须要用方法三来实现自定义拦截器。】
五、拦截器与过滤器区别。【
(1)、拦截器是基于java的反射机制的,而过滤器是基于函数回调。
(2)、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
(3)、拦截器与过滤器原理相似,拦截器只能对action请求起作用,而过滤器则
可以对几乎所有的请求起作用。
(4)、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
(5)、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初
始化时被调用一次
(6)、执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。】
六、拦截器的的调用顺序【
a:首先,要找到它自己有没有声明拦截器的引用,即<action>元素有没有
<interceptor-ref>子元素,如果有,则不用继续寻找,直接使用这些拦截器,如
果没有进行下一步的查找。
b:其次,找到这个<action>所在包有没有声明默认的拦截器引用,即<package>
元素的<default-interceptor-ref>子元素,如果有,则不用继续再找,直接使用
这些拦截器,如果没有,则进行下一步的查找。
c:递归的查找这个包的父包,看看有没有声明默认的拦截器引用,直到找到默认
的拦截器引用为止。】
七、开发自定义的拦截器【
开发自定义的拦截器,要实现Interceptor接口,还要使用到ActionInvocation接
口,现在对ActionInvocation接口进行简单的介绍。
它里面有一些方法,如下:《
a:getAction,获得这次请求准备执行的Action对象。
b:getProxy,返回这次请求的ActionProxy对象,可以在这个对象上获得要运行
Action的哪个方法。
c:getInvocationContext,返回这个Action执行的上下文(ActionContext),可
以在这个上下文对象中获得大量的数据,比如请求的parameter值,session的值
等。
d:在ActionContext中取到的parameter值是一个Map<String, Object>,其中以
String为key,以String[]为value,这个Map记录了所有的request参数。
e:getResult方法,返回Result运行之后代表结果的Result对象。》
我们要实现这样一个Aciton,要求拦截器输出如下的信息:运行哪个Action类,
运行哪个方法,请求的参数和Action运行完要跳转到哪个JSP。】
八、Struts2文件上传【
Struts2的文件上传实现非常简单,只需要简单几步就可完成;
注意:
(1)文件上传的struts2标签为:<s:file name="" label="上传"/>
(2)文件上传的前提是表单属性method="post" enctype="multipart/form-data";
(3)web应用中必须包含common-fileupload.jar和common-io.jar,因为struts2默
认上传解析器使用的是jakarta;
(4)可以在struts.xml中配置最大允许上传的文件大小:<constant
name="struts.multipart.maxSize" value="....."/>,默认为2M;
(5)普通文件上传{
实现规则:
[1]JSP中设定表单控件<s:file name="upload" label="上传"/>
[2]Action中定义属性:private File upload; //包含文件内容。private
String uploadFileName;//上传文件的名称;
private String uploadContentType;//上传文件的MIME类型;这些属性都会随着
文件的上传自动赋值;
[3]在execute()中完成写入磁盘功能;}】
九、struts2相关配置(参考)【
<!-- 指定由spring负责action对象的创建 --><constant
name="struts.objectFactory" value="spring" />
<!-- 所有匹配*.action的请求都由struts2处理 --><constant
name="struts.action.extension" value="action" />
<!-- 是否启用开发模式 --><constant name="struts.devMode" value="true"
/>
<!-- struts配置文件改动后,是否重新加载 --><constant
name="struts.configuration.xml.reload" value="true" />
<!-- 设置浏览器是否缓存静态内容 --><constant
name="struts.serve.static.browserCache" value="false" />
<!-- 请求参数的编码方式 --><constant name="struts.i18n.encoding"
value="utf-8" />
<!-- 每次HTTP请求系统都重新加载资源文件,有助于开发 --><constant
name="struts.i18n.reload" value="true" />
<!-- 文件上传最大值 --><constant name="struts.multipart.maxSize"
value="104857600" />
<!-- 让struts2支持动态方法调用 --><constant
name="struts.enable.DynamicMethodInvocation" value="true" />
<!-- Action名称中是否还是用斜线 --><constant
name="struts.enable.SlashesInActionNames" value="false" />
<!-- 允许标签中使用表达式语法 --><constant name="struts.tag.altSyntax"
value="true" />
<!-- 对于WebLogic,Orion,OC4J此属性应该设置成true --><constant
name="struts.dispatcher.parametersWorkaround" value="false" />】
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
1、拦截器。
(1)在lib中导入11个jar包。
(2)在src中建com.zking.action包和UserAction.java类{package
com.zking.action;import
javax.swing.plaf.basic.BasicSliderUI.ActionScroller;
import com.opensymphony.xwork2.ActionSupport;public class UserAction
extends ActionSupport{//登录。public String login() throws Exception {
System.out.println("到了UserAction。。。。。login");return "success";}}
}
(3)在src中建struts.xml配置文件{<?xml version="1.0" encoding="UTF-8"
?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts><!--编码配置--><constant name="struts.i18n.encoding"
value="UTF-8"/>
<!-- 打开方法动态调用开关 constant:常量--><constant
name="struts.enable.DynamicMethodInvocation" value="true" />
<package name="mypackage" extends="struts-default"
namespace="/"><interceptors><interceptor name="encodInter"
class="com.zking.interceptor.EncodInterceptor">
</interceptor><interceptor name="userLoinInter"
class="com.zking.interceptor.UserLoginInterceptor"></interceptor><!--
拦截器栈 stack:栈 -->
<interceptor-stack name="mys"><interceptor-ref
name="defaultStack"></interceptor-ref><interceptor-ref
name="encodInter"></interceptor-ref>
<interceptor-ref name="userLoinInter"></interceptor-ref></interceptor-
stack></interceptors><!--<default-interceptor-ref
name="mys"></default-interceptor-ref>-->
<!-- action配置 --><action name="user"
class="com.zking.action.UserAction"><interceptor-ref
name="mys"></interceptor-ref><param name="abc">utf-8</param>
<result name="success">login_success.jsp</result><result
name="login">login.jsp</result></action><action name="myfile"
class="com.zking.action.FileAction">
<result
name="success">file_success.jsp</result></action></package></struts>}
(4)web.xml{...<!-- struts2 核心过滤器配置 --> <filter><filter-
name>struts2</filter-name>
<filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter</filter-class></filter>
<filter-mapping><filter-name>struts2</filter-name><url-
pattern>*.action</url-pattern></filter-mapping></web-app>}
(5)login.jsp{<body><div align="Center"><form action="user!
login.action" method="post"><table><tr><td>用户名:</td><td><input
type="text" name="s_name"/></td>
</tr><tr><td>密 码:</td><td><input type="password"
name="s_pwd"/></td></tr><tr align="Center"><td colspan="2"><input
type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(6)在src中建com.zking.interceptor包和EncodInterceptor.java类{package
com.zking.interceptor;import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class EncodInterceptor extends AbstractInterceptor{//intercept:
拦截。@Override public String intercept(ActionInvocation arg0) throws
Exception {
System.out.println("到了EncodInterceptor。。。。");//设置编码。
ServletActionContext.getRequest().setCharacterEncoding("UTF-8");
ServletActionContext.getResponse().setCharacterEncoding("UTF-
8");//ServletActionContext 获取config对象。return arg0.invoke();}}}
(7)UserLoginInterceptor.java类{package com.zking.interceptor;import
java.util.Map;import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;import
com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/** * 判断用户是否登录 * @author Teacher'Tan * */public class
UserLoginInterceptor extends AbstractInterceptor{//intercept:拦截。
@Override public String intercept(ActionInvocation arg0) throws
Exception {System.out.println("到了UserLoginInterceptor。。。。");//获
取当前登陆者信息。
Map<String, Object> session = arg0.getInvocationContext().getSession
();Object userObj = session.get("myuser");//判断。if(userObj==null){
return Action.LOGIN;}//拦截器栈。return arg0.invoke();}}}
2、文件上传、下载。
(1)fileup.jsp{<body><div align="Center"><form action="myfile!
upload.action" method="post" enctype="multipart/form-
data"><table><tr><td>文件上传:</td>
<td><input name="myf" type="file" /> </td></tr><tr align="Center"><td
colspan="2"><input type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(2)FileAction.java{package com.zking.action;import
java.io.File;import java.io.FileInputStream;import
java.io.FileOutputStream;
import javax.swing.plaf.basic.BasicSliderUI.ActionScroller;import
org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.ActionSupport;
public class FileAction extends ActionSupport{//文件对象 myf必须跟表单
的那么值一样。private File myf;//文件类型。private String
myfContentType;//文件名字。
private String myfFileName;//登录。public String upload() throws
Exception {System.out.println("到了UserAction。。。。。upload");
System.out.println("文件:"+this.myf);System.out.println("类
型:"+this.myfContentType);System.out.println("文件名
字:"+this.myfFileName);
//输入流。FileInputStream fis = new FileInputStream(myf);//输出流。
String path = ServletActionContext.getServletContext().getRealPath
("/myupload");
path = path+"\\"+this.getMyfFileName();System.out.println
("path:"+path);FileOutputStream fos = new FileOutputStream(path);int
n;while((n=fis.read())!=-1){
//System.out.println(n);//写入。fos.write(n);}//关闭流。fis.close
();fos.close();return "success";}public File getMyf() {return myf;}
public void setMyf(File myf) {this.myf = myf;}public String
getMyfContentType() {return myfContentType;}public void
setMyfContentType(String myfContentType){
this.myfContentType = myfContentType;}public String getMyfFileName()
{return myfFileName;}public void setMyfFileName(String myfFileName){
this.myfFileName = myfFileName;}}}
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
示例1:struts2完美实现文件上传和下载!
(1)第一步:在webx项目lib目录下加入struts.jar包{asm-3.3.jar、asm-
commons-3.3.jar、asm-tree-3.3.jar、commons-fileupload-1.3.1.jar、
commons-io-2.2.jar
、commons-lang3-3.2.jar、freemarker-2.3.22.jar、javassist-3.11.0.GA.jar
、log4j-api-2.2.jar、log4j-core-2.2.jar、ognl-3.0.6.jar
struts2-core-2.3.24.1.jar、struts2-dojo-plugin-2.3.24.1.jar、xwork-
core-2.3.24.1.jar}
(2)第二步:配置web.xml{<?xml version="1.0" encoding="UTF-8"?><web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
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"><display-name>Struts08</display-name><!--
struts2.配置--><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>*.action</url-pattern><url-pattern>*.jsp</url-
pattern></filter-mapping><!-- struts2配置--><welcome-file-list>
<welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>`}
(3)第三步:配置struts.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><!-- 设置字符编
码 --><constant name="struts.i18n.encoding" value="utf-8" /><!-- 设置自
动装载国际化 -->
<constant name="struts.i18n.reload" value="true" /><!-- 设置动态方法调
用 --><constant name="struts.enable.DnamicMethodInvocation"
value="true" />
<!-- 设置开发模式 --><constant name="struts.devMode" value="true"
/><!-- 指定每次配置文件更改后,自动重新加载 -->
<constant name="struts.configuration.xml.reload" value="true" /><!-- 设
置访问方式 --><constant name="struts.action.extension" value="action,,"
/>
<!-- 去除多余的格式 --><constant name="struts.ui.theme" value="simple"
/><!--设置上传文件大小20MB,默认为2MB大小 -->
<constant name="struts.multipart.maxSize"
value="20971520"></constant><package name="default" extends="struts-
default" namespace="/"><!-- 文件上传配置 -->
<action name="m" class="com.action.UploadManyFile"><!-- 文件上传到user
目录下--><param name="path">/user</param><param
name="size">10240000</param></action>
<!-- 文件下载配置 --><action name="down"
class="com.action.FileDownloadAction"><param
name="path">/user</param><result name="success" type="stream">
<param name="contentType">application/octet-stream</param><param
name="inputName">inputStream</param> <param
name="inputName">inputStream</param>
<param name="contentDisposition">filename=${fn}</param><param
name="bufferSize">4096</param></result></action></package></struts>}
(4)第四步:jsp写入代码{<%@ page language="java"
pageEncoding="UTF8"%><!Doctype html><html ><head><meta charset="UTF-8"
/><title>struts2 多文件上传</title>
</head><body><h1>struts-多文件 上传</h1><form action="m.action"
method="post" enctype="multipart/form-data">姓名:<input type="text"
name="name" value="张三"><br>
文件:<input type="file" name="fs" multiple ><br>文件1:<input
type="file" name="fs" multiple ><br>文件2:<input type="file" name="fs"
multiple ><br>
文件3:<input type="file" name="fs" multiple ><br><input type="submit"
value="上传"><br></form><hr><h1>文件下载</h1><a href="user/abc.jpg">下
载</a>
<a href="user/abc.rar">下载zip</a><a href="down.action?
fn=abc.rar">struts2文件下载</a></body></html>}
(5)第五步:在src目录下建立com.action包建立UploadManyFile{package
com.action;import java.io.File;import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;import
org.apache.struts2.ServletActionContext;import
org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionSupport;public class
UploadManyFile extends ActionSupport implements ServletContextAware
{private String name;
private File[] fs; //文件名。private String [] fsFileName;private
String[] fsContentType;//文件类型。private String path;//文件路径
private int size; //文件大小。
private ServletContext ctx;public String getName() {return name;}public
void setName(String name) {this.name = name;}public File[] getFs()
{return fs;}
public void setFs(File[] fs) {this.fs = fs;}public String getPath()
{return path;}public void setPath(String path) {this.path = path;}
public int getSize() {return size;}public void setSize(int size)
{this.size = size;}public String[] getFsFileName() {return fsFileName;}
public void setFsFileName(String[] fsFileName) {this.fsFileName =
fsFileName;}public String[] getFsContentType() {return fsContentType;}
public void setFsContentType(String[] fsContentType)
{this.fsContentType = fsContentType;}@Override public void
setServletContext(ServletContext ctx) {
this.ctx=ctx;}@Override public String execute() throws Exception
{String p=ctx.getRealPath(path);File f=new File(p);if(!f.exists())
{f.mkdirs();}
for(int i=0;i<fs.length;i++){System.out.println
(path);System.out.println(p);System.out.println
(size);System.out.println(fs[i].length());
System.out.println("------------");/* * 如果文件大于上传限定值*/if(fs
[i].length()<size){FileUtils.copyFile(fs[i],new File(f,fsFileName
[i]));}}return null;}}}
(6)第六步:建立FileDownloadAction{package com.action;import
java.io.FileInputStream;import java.io.FileNotFoundException;import
java.io.InputStream;
import org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.Action;public class FileDownloadAction
implements Action {
private String fn; //文件名。private String path; //路径。public String
getFn() {return fn;}public void setFn(String fn) {this.fn = fn;}
public String getPath() {return path;}public void setPath(String path)
{this.path = path;}@Override public String execute() throws Exception
{return SUCCESS;}
public InputStream getInputStream() throws Exception{//获得路径和文件名
。String ip=ServletActionContext.getServletContext().getRealPath
(path)+"/"+fn;
InputStream is=new FileInputStream(ip);return is;}}}
(7)第七步输入项目名称运行。
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
第四次(优化)
第一部分【
(1)在lib中导入11个jar包。
(2)在src中建com.zking.action包和UserAction.java类{package
com.zking.action;import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{public String login()
throws Exception {System.out.println("到了UserAction");
//这里必须要配置,不然后报404错。return "success";}}}
(3)在src中建struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!
DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts
Configuration
2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!-- 打开方法的
动态调用 --><constant name="struts.enable.DynamicMethodInvocation"
value="true" />
<package name="mypackage" extends="struts-default"
namespace="/"><action name="user" class="com.zking.action.UserAction">
<!--根据你返回的结果字符串找到对应的页面,这是种映射关系--><result
name="success">login_success.jsp</result></action></package></struts>}
(4)web.xml{<?xml version="1.0" encoding="UTF-8"?><web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
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">
<display-name>Stsrus2</display-name><welcome-file-list><welcome-
file>index.html</welcome-file></welcome-file-list>
<!-- struts2核心过滤器配置 --><filter><filter-name>struts2</filter-
name><filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter
</filter-class></filter><filter-mapping><filter-name>struts2</filter-
name><url-pattern>*.action</url-pattern></filter-mapping></web-app>}
(5)login.jsp{<body><div align="Center"><!--这是种动态调用--><form
action="user!login.action" method="post"><table>
<tr><td>用户名:</td><td><input type="text"
name="s_name"/></td></tr><tr><td>密码:</td><td><input type="password"
name="s_pwd"/></td></tr>
<tr align="Center"><td colspan="2"><input type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(6)login_success.jsp{<body>This is my login_success.jsp <br><a
href="test.action?myname=小白">去testAction</a></body>}】
第二部分配置拦截器。【
(7)在src中建com.zking.interceptor包和UserInterceptor.java类{package
com.zking.interceptor;import java.util.Map;
import com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class UserInterceptor extends AbstractInterceptor
{@Overridepublic String intercept(ActionInvocation arg0) throws
Exception {
//获取session中的登陆者信息。System.out.println("到了UserInterceptor。
。。。。");Map<String, Object> session = arg0.getInvocationContext
().getSession();
//判断。Object obj = session.get("myuser");if(obj==null){//返回登录界面
。return "login";}return arg0.invoke();}}}
(8)struts.xml{在原有的基础上加[1]“<result
name="login">login.jsp</result>”,把它放到<action>中。
[2]“<interceptors><interceptor name="userLoginInter"
class="com.zking.interceptor.UserInterceptor"></interceptor></intercept
ors>”把它放到<action>上面。
[3]“<interceptor-ref name="defaultStack"></interceptor-
ref><interceptor-ref name="userLoginInter"></interceptor-ref>”把它放到
<action>中<result>上面。}】
第三部分【
(9)在src中建com.zking.entity包和User.java类{package
com.zking.entity;import java.io.Serializable;
public class User implements Serializable {private String
s_name;private String s_pwd;《无参构造、封装》}}
(10)UserAction.java{package com.zking.action;import
org.apache.log4j.Logger;import
com.opensymphony.xwork2.ActionSupport;import com.zking.entity.User;
public class UserAction extends ActionSupport {//日志属性。private
Logger log = Logger.getLogger(UserAction.class);
//用户属性。private User user;《封装》public String login() throws
Exception {//日志打印 log4j。log.info("到了UserAction。。。。");
//到数据去查询//如果成功,将登陆者信息放入session(解耦方式)//如果失败,
返回login.jsp。return "success";}}}
(11)login.jsp{把里面用户名和密码的name=“s_name,s_pwd”改
为“user.s_name,user.s_pwd”。}
(12)在src中建log4j.properties{log4j.rootLogger =INFO,A1 #输出到控制
台? log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm
\:ss,SSS}][%c]%m%n
log4j.appender.systemOut.Threshold =?ALL
log4j.appender.A1.Target=System.out
##保存到文件
#log4j.appender.FileLog = org.apache.log4j.RollingFileAppender
#log4j.appender.FileLog.MaxFileSize = 1MB
#log4j.appender.FileLog.MaxBackupIndex = 14
#log4j.appender.FileLog.File =G160618.log
#log4j.appender.FileLog.layout = org.apache.log4j.PatternLayout
#log4j.appender.FileLog.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm
\:ss,SSS}][%c] %m%n
##发送到邮件
#log4j.appender.mail=org.apache.log4j.net.SMTPAppender
#log4j.appender.mail.Threshold=ERROR
#log4j.appender.mail.BufferSize=1
#log4j.appender.mail.SMTPHost=smtp.163.com
##发件邮箱、收件邮件
#log4j.appender.mail.From=18569032110@163.com
#log4j.appender.mail.To=1793489869@qq.com
##发送邮件箱的用户名、密码
#log4j.appender.mail.SMTPUsername=18569032110@163.com
#log4j.appender.mail.SMTPPassword=tn8522155
##邮箱主题
#log4j.appender.mail.Subject=This's T199_Test Error Message
#log4j.appender.mail.layout=org.apache.log4j.PatternLayout
#log4j.appender.mail.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH
\:mm\:ss,SSS}][%c]\:%m%n}
(13)struts.xml{把“<interceptor-ref
name="defaultStack"></interceptor-ref><interceptor-ref
name="userLoginInter"></interceptor-ref>”注释}】
第四部分【
(14)在src中建com.zking.service包和UserServiceI.java接口{//登录。
public boolean login(User user);}
(15)在src中建com.zking.service.impl包和UserServiceImpl.java类{public
class UserServiceImpl implements UserServiceI {//UserDao属性。
private BaseDao<User> baseDao = new UserDaoImpl();@Override public
boolean login(User user) {return baseDao.login(user);}}}
(16)在src中建com.zking.dao包和BaseDao.java接口{public boolean login
(T t);}
(17)在src中建com.zking.dao.impl包和UserDaoImpl.java类{public class
UserDaoImpl implements BaseDao<User>{@Override public boolean login
(User user){
//调用DBHelper的方法。。。。return false;}}}
(18)UserAction.java{public class UserAction extends ActionSupport
{private Logger log = Logger.getLogger(UserAction.class);
//UserService属性。private UserServiceI userService = new
UserServiceImpl();private User user;《封装》public String login()
throws Exception {
log.info("到了UserAction。。。。");userService.login(this.user);return
"success";}}}
(19)在com.zking.action包中BaseAction.java类{package
com.zking.action;import java.io.IOException;import
org.apache.struts2.ServletActionContext;
public class BaseAction {//向页面写入JSON字符串的方法。public void
writeJSON(Object obj) throws IOException{//将obj转换成JSON。String
strJSON = "";
//。。。。。ServletActionContext.getPageContext().getResponse
().getWriter().print(strJSON);}}}】
.......................................................................
.......................................................................
.......................................................................
..................
报错:
1、java.lang.NoSuchMethodException:
com.zking.action.UserAction.myloginUser()
【解决方法:查看一下你的struts.xml配置文件的action名字格式是否写对,或
者查看你的jsp里面的form表单是否和struts.xml里面的action名字对应。】
2、java.lang.IllegalArgumentException: attempt to create saveOrUpdate
event with null entity
【解决方法:查看一下你jsp里面属性名字有没有加上对象。】
3、java.lang.NoClassDefFoundError:org/objectweb/asm/ClassVisitor
【字节码错误。解决方案:导包:asm-all-3.3.1.jar】
4、警告: Could not find action or result: /Struts2/userAction!
mylogin.action
There is no Action mapped for namespace [/] and action name
[userAction] associated with context path [/Struts2]. - [unknown
location]
【解决方法:(1)把"@Action()"删除。因为struts.xml里面开起了一个动态方法
的调用。然后在jsp页面请求的时间也用了。所以它直接到达了你的方法。
(2)把@Namespace改为“@Namespace("/")”,把“@Action()”还原,把jsp页面里
面的form表单里面的action改为“action="mylogin.action" ”
(3)把@Namespace改为“@Namespace("/user")”,把“@Action("/mylogin")”还
原,把jsp页面里面的form表单里面的action改为“action="mylogin.action"”
前面三种方法运行完以后还是会报错,因为后面还有东西没有写完,所以不要紧
。查看控制台是否打印“UserAction被实例化了。。。。到了UserAction用户名
:we密 码:1243”
(4)动态配置:改成:把所有的return都改成"success"。 @Action
(value="/mylogin",results={@Result
(name="success",location="/welcome.jsp"),
@Result(name="fail",location="/fail.jsp")})用第四种方法不会在报错了。】
.......................................................................
.......................................................................
.......................................................................
..................
-----------------------------------
----------------------------
MyEclipse:
新建web项目{Ctrl+n/输入‘web’/Web Project/Next/[Project name:struts2
、Java EE version:JavaEE 6-Web 3.0、Java version:1.7
、JSTL Version:<none>]/Next/Next/(勾选)Generate web.xml dep....[自动生
成一个web.xml]/Next/Finish}
-----------------------------------
----------------------------
***********************************************************************
***********************************************************************
************************************************************
Struts2面试题:
一、Struts2工作流程:
1、客户端浏览器发出HTTP请求.
2、根据web.xml配置,该请求被FilterDispatcher(核心控制器)接收
3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将
值注入给Aciton
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳
转到相应页面
6、返回HTTP响应到客户端浏览器
二、拦截器和过滤器的区别:
1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。
4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。
5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时
被调用一次。
三、说下Struts的设计模式
MVC模式
什么是MVC?{<1>它是一种三层加构“模型Model、视图View、控制器Controller
”的模型<2>登录是怎样直行流程?首先在login.jsp页面做一个请求,然后
请求到控制器“Controller Filter”,控制器对你的登录里的用户名跟密码进行
判断,判断完了后它才决定到底是到这个欢迎页面还是到主页面还是返回过去。
在
这个数据处理过程当中它要用到MVC的一个流程。}
四、struts1于struts2的比较:
1、Action类:
Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类
编程而不是接口。
Struts2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制
的服务成为可能。Struts2提供一个ActionSupport基类去 实现常用的接口。
Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的
Action对象。
2、线程模式:
Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例
来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时
特别小心。Action资源必须是线程安全的或同步的。
Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实
际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾
回收问题)
3、Servlet依赖:
Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时
HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
Struts2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,
Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少
或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
4、可测性:
测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得
测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套
Struts1的模拟对象(来进行测试)。
Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支
持也使测试更容易。
5、捕获输入:
Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。
因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。动
态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是
在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
Struts2 直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面
上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对
象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入
对象的引用。
6、表达式语言:
Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合
和索引属性的支持很弱。
Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言-- "Object
Graph Notation Language " (OGNL).
7、绑定值到页面(view):
Struts1使用标准JSP机制把对象绑定到页面中来访问。
Struts2使用 "ValueStack "技术,使taglib能够访问值而不需要把你的页面
(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同
的属性重用页面(view)。
8、类型转换:
Struts1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils
进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
9、校验:
Struts1支持在ActionForm的validate方法中手动校验,或者通过Commons
Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用
为属性类类型定义的校验和内容校验,来支持chain校验子属性
10、Action执行的控制:
Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中
的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的
生命周期。堆栈能够根据需要和不同的Action一起使用。
五、为什么要使用Struts2?
1、【首先,它是一个基于MVC的web应用框架,基于struts1和webwork,合并优化
之后的产物。
对于广大用户给它的赞美,这里简单的翻译一下apache网站下的两段话。
《阿帕奇的struts2项目是一个优雅的,可扩展的框架,可以用来创建为企业准备
的javaWeb应用,这个框架被设计来简化整个开发的周期,从构建到部署到维护,
贯穿整个软件生命周期的时间段。阿帕奇struts2最初被叫做WebWork2,独立工作
数年之后,webWork和Struts的交流合作促进创造了strust2,这个新版本的struts
简化了使用,跟之前我们想要使用的struts很接近。》
从这两段话看出,其实它主要就两个价值点,一个是可扩展性,第二个就是简化
了web应用的开发周期。】
2、【Struts2 是一个相当强大的Java Web开源框架,是一个基于POJO的Action的
MVC Web框架。它基于当年的Webwork和XWork框架,继承其优点,同时做了相当的
改进。
(1)Struts2基于MVC架构,框架结构清晰,开发流程一目了然,开发人员可以很
好的掌控开发的过程。
(2)使用OGNL进行参数传递。
OGNL提供了在Struts2里访问各种作用域中的数据的简单方式,你可以方便的获取
Request,Attribute,Application,Session,Parameters中的数据。大大简化
了开发人员在获取这些数据时的代码量。
(3)强大的拦截器
Struts2 的拦截器是一个Action级别的AOP,Struts2中的许多特性都是通过拦截
器来实现的,例如异常处理,文件上传,验证等。拦截器是可配置与重用的,可
以将一些通用的功能如:登录验证,权限验证等置于拦截器中以完成一些Java
Web项目中比较通用的功能。在我实现的的一Web项目中,就是使用Struts2的拦截
器来完成了系统中的权限验证功能。
(4)易于测试
Struts2的Action都是简单的POJO,这样可以方便的对Struts2的Action编写测试
用例,大大方便了5Java Web项目的测试。
易于扩展的插件机制在Struts2添加扩展是一件愉快而轻松的事情,只需要将所需
要的Jar包放到WEB-INF/lib文件夹中,在struts.xml中作一些简单的设置就可以
实现扩展。
(6)模块化管理
Struts2已经把模块化作为了体系架构中的基本思想,可以通过三种方法来将应用
程序模块化:将配置信息拆分成多个文件把自包含的应用模块创建为插件创建新
的框架特性,即将与特定应用无关的新功能组织成插件,以添加到多个应用中去
。
(7)全局结果与声明式异常
为应用程序添加全局的Result,和在配置文件中对异常进行处理,这样当处理过
程中出现指定异常时,可以跳转到特定页面。
他的如此之多的优点,是很多人比较的青睐,与spring ,Hibernate进行结合,组
成了现在比较流行的ssh框架,当然每个公司都要自己的框架,也是ssh变异的产
品。】
六、struts2有哪些优点?
1)在软件设计上Struts2的应用可以不依赖于Servlet API和struts API。
Struts2的这种设计属于无侵入式设计;
2)拦截器,实现如参数拦截注入等功能;
3)类型转换器,可以把特殊的请求参数转换成需要的类型;
4)多种表现层技术,如:JSP、freeMarker、Velocity等;
5)Struts2的输入校验可以对指定某个方法进行校验;
6)提供了全局范围、包范围和Action范围的国际化资源文件管理实现
七、struts2是如何启动的?
struts2框架是通过Filter启动的,即StrutsPrepareAndExecuteFilter,此过滤
器为struts2的核心过滤器;
StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文
件struts.xml完成初始化操作。struts2读取到struts.xml的内容后,是将内容封
装进javabean对象然后存放在内存中,以后用户的每次请求处理将使用内存中的
数据,而不是每次请求都读取struts.xml文件。
八、struts2框架的核心控制器是什么?它有什么作用?
1)Struts2框架的核心控制器是StrutsPrepareAndExecuteFilter。
2)作用:
负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到
达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径
不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则
struts2框架将略过该请求的处理。
可以通过常量"struts.action.extension"修改action的后缀,如:
<constant name="struts.action.extension" value="do"/>
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。
<constant name="struts.action.extension" value="do,go"/>
九、struts2配置文件的加载顺序?
struts.xml ——> struts.properties
常量可以在struts.xml或struts.properties中配置,如果在多个文件中配置了同
一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值.
struts.xml文件的作用:通知Struts2框架加载对应的Action资源
十、struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置,两种配置方式如下:
1)在struts.xml文件中配置常量
<constant name="struts.action.extension" value="do"/>
2)在struts.properties中配置常量(struts.properties文件放置在src下):
struts.action.extension=do
十一、struts2如何访问HttpServletRequest、HttpSession、ServletContext三
个域对象?
方案一:【
HttpServletRequest request =ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session= request.getSession();
ServletContext servletContext=ServletActionContext.getServletContext();
】
方案二: 【
类 implements ServletRequestAware,ServletResponseAware,SessionAware,
ServletContextAware 】
注意:框架自动传入对应的域对象 。
十二、struts2是如何管理action的?这种管理方式有什么好处?
struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的。
主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务
功能相关的Action放在同一个包下。
十三、struts2中的默认包struts-default有什么作用?
1)struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和
Result类型,而Struts2很多核心的功能都是通过这些内置的拦截器实现,如:从
请求中
把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当
包继承了struts-default包才能使用struts2为我们提供的这些功能。
2)struts-default包是在struts-default.xml中定义,struts-default.xml也是
Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。
3)通常每个包都应该继承struts-default包。
十四、struts2如何对指定的方法进行验证?
1)validate()方法会校验action中所有与execute方法签名相同的方法;
2)要校验指定的方法通过重写validateXxx()方法实现, validateXxx()只会校
验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写;
3)当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加
校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport
), 如果系统 的fieldErrors包含失败信息,struts2会将请求转发到名为input
的result;
4)在input视图中可以通过<s:fielderror/>显示失败信息。
5)先执行validateXxxx()->validate()->如果出错了,会转发<result
name="input"/>所指定的页面,如果不出错,会直接进行Action::execute()方法
十五、struts2默认能解决get和post提交方式的乱码问题吗?
不能。struts.i18n.encoding=UTF-8属性值只能解析POST提交下的乱码问题。
十六、请你写出struts2中至少5个的默认拦截器?
fileUpload 提供文件上传功能
cookies 使用配置的name,value来是指cookies
checkbox 添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为
false,而html默认情况下不提交没有选中的checkbox。
chain 让前一个Action的属性可以被后一个Action访问,现在和chain类型的
result()结合使用。
alias 在不同请求之间将请求参数在不同名字件转换,请求内容不变
十七、值栈ValueStack的原理与生命周期?
1)ValueStack贯穿整个 Action 的生命周期,保存在request域中,所以
ValueStack和request的生命周期一样。当Struts2接受一个请求时,会迅速创建
ActionContext, ValueStack,action。然后把action存放进ValueStack,所以
action的实例变量可以被OGNL访问。 请求来的时候,action、ValueStack的生命
开始,请求结束,action、
ValueStack的生命结束;
2)action是多例的,和Servlet不一样,Servelt是单例的;
3)每个action的都有一个对应的值栈,值栈存放的数据类型是该action的实例,
以及该action中的实例变量,Action对象默认保存在栈顶;
4)ValueStack本质上就是一个ArrayList;
5)关于ContextMap,Struts 会把下面这些映射压入 ContextMap 中:
parameters : 该 Map 中包含当前请求的请求参数
request : 该 Map 中包含当前 request 对象中的所有属性 session :该 Map 中
包含当前 session 对象中的所有属性
application :该 Map 中包含当前 application 对象中的所有属性
attr:该 Map 按如下顺序来检索某个属性: request, session, application
6)使用OGNL访问值栈的内容时,不需要#号,而访问request、session、
application、attr时,需要加#号;
7)注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:
<s:property value="name"/>
8)在struts2配置文件中引用ognl表达式 ,引用值栈的值 ,此时使用的"$",而
不是#或者%;
十八、ActionContext、ServletContext、pageContext的区别?
1)ActionContext是当前的Action的上下文环境,通过ActionContext可以获取到
request、session、ServletContext等与Action有关的对象的引用;
2)ServletContext是域对象,一个web应用中只有一个ServletContext,生命周
期伴随整个web应用;
3)pageContext是JSP中的最重要的一个内置对象,可以通过pageContext获取其
他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结
束时,pageContext销毁, 生命周期是JSP四个域对象中最小的。
十九、result的type属性中有哪几种结果类型?
dispatcher
struts默认的结果类型,把控制权转发给应用程序里的某个资源不能把控制权转
发给一个外部资源,若需要把控制权重定向到一个外部资源, 应该使用
redirect结果类型
redirect 把响应重定向到另一个资源(包括一个外部资源)
redirectAction 把响应重定向到另一个 Action
freemarker、velocity、chain、httpheader、xslt、plainText、stream
二十、拦截器的生命周期与工作过程?
1)每个拦截器都是实现了Interceptor接口的 Java 类;
2)init(): 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只
被调用一次. 可以在该方法中对相关资源进行必要的初始化;
3)intercept(ActionInvocation invocation): 每拦截一个动作请求, 该方法就
会被调用一次;
4)destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也
只被调用一次;
5)struts2中有内置了18个拦截器。
二十一、struts2如何完成文件的上传?
1、JSP页面:
1)JSP页面的上传文件的组件:<s: file name=”upload” />,如果需要一次上
传多个文件, 就必须使用多个 file 标签, 但它们的名字必须是相同的,即:
name=“xxx”的值必须一样;
2)必须把表单的enctype属性设置为:multipart/form-data;
3)表单的方法必须为post,因为post提交的数据在消息体中,而无大小限制。
2、对应的action:
1)在 Action 中新添加 3 个和文件上传相关的属性;
2)如果是上传单个文件, uploadImage属性的类型就是 java.io.File, 它代表被
上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文件的文
件名和文件类型,定义方式是分别是:
jsp页面file组件的名称+ContentType, jsp页面file组件的名称+FileName
3)如果上上传多个文件, 可以使用数组或 List
二十二、struts的工作原理
1、初始化,读取struts-config.xml、web.xml等配置文件(所有配置文件的初始
化)
2、发送HTTP请求,客户端发送以.do结尾的请求
3、填充FormBean(实例化、复位、填充数据、校验、保存)
4、将请求转发到Action(调用Action的execute()方法)
5、处理业务(可以调用后台类,返回ActionForward对象)
6、返回目标响应对象(从Action返回到ActionServlet)
7、转换Http请求到目标响应对象(查找响应,根据返回的Forward keyword)
8、Http响应,返回到Jsp页面
二十三、Struts2框架在三层架构中哪部分进行的再优化?
表现层进行的再优化。
三层架构:
表现层 MVC
业务层 service
持久层 dao(data access object)
二十四、Struts1和Struts2的一个显著区别是什么?
Struts1的核心控制器是一个servlet。
Struts2的核心控制器是一个过滤器。
二十五、Struts2的编写步骤?
1.导入相关jar包
2.配置web.xml中的过滤器
3.编写struts.xml
4.开发action。
二十六、Struts2的执行过程?
tomcat启动的时候加载应用的web.xml,实例化并初始化过滤器,过滤器的初始化
方法加载struts.xml。客户端发送请求,请求到达过滤器,截取请求的动作名称
(没有或以action结尾),并从struts.xml中找,找到后,实例化动作类。调用
对应的动作方法,方法有返回值,根据返回值,找到name取值对应的结果视图,
找到jsp页面。
二十七、Struts2的配置文件加载时机和加载顺序?
当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。加载顺序:
default.properties、struts-default.xml、struts-plugin.xml、struts.xml、
web.xml
二十八、常量中struts.devMode是什么意思,如何配置?
开发模式。修改了struts.xml中的配置,你不必每次都重启服务器。
<constant name="struts.devMode" value="true" />
二十九、struts.xml配置文件中package的四个属性分别什么意思?
name:包名
extends:一般是继承struts-default包,但不是必须的。不过如果不继承的话,
将无法使用struts2提供的核心功能。
abstract:把包声明为抽象包,抽象包就是用来被继承的。只要是没有<action>
元素的包,就可以声明为抽象包。
namespace:名称空间。
三十、访问带有名称空间的动作时,是如何查找的? /user/abc/action1.action
先找user/abc,有action1就执行,没有再找user下面的action1,有就执行,最
后找根目录。
三十一、action元素的三个属性什么意思
name:动作名称
class:动作类全名。默认的动作类是:
com.opensymphony.xwork2.ActionSupport是在struts-default.xml中定义的。
method:动作类中的方法名称。默认是public String execute(){}
要求:
1.public的
2.返回值必须是String
3.没有参数
三十二、result元素的两个属性分别指的是什么?
name:逻辑视图的名称,对应着动作方法的返回值。默认值是success。
type:结果类型,指的就是用什么方式转到定义的页面。默认是dispatcher。
三十三、4个常用结果类型分别是什么?
dispatcher:(默认值)使用请求转发,转向一个页面。
redirect:使用重定向,转向一个页面。
redirectAction:注意:使用的是重定向。
a.重定向到另一个相同名称空间的动作。b.重定向到不同名称空间的动作
chain:注意:使用的是请求转发。
a.转发到另一个相同名称空间的动作。b.请求转发到不同名称空间的动作
三十四、访问ServletAPI的两种方式?
第一种方式:使用ServletActionContext类
第二种方式:使用实现接口的方式(ServletRequestAware、
ServletResponseAware)
三十五、如何封装静态请求参数?
在struts.xml配置文件中,给动作类注入值。调用的是setter方法。
三十六、动作类和模型分开的动态封装请求参数,set和get方法是怎么调用的?
先get出来,判断存不存在,存在直接get第二次(给这个对象赋值),不存在(
把这个对象创建出来,set回去,然后再get出来)
三十七、使用模型驱动动态封装请求参数的要求是什么?
实现ModelDriven接口,动作类和实体模型分开,创建模型对象并将其实例化,重
写getModel方法,返回一个引用。
三十八、实际开发中类型转换的两种情况是什么?
转字符串,转其他类型。
写的时候,发送请求,经过过滤器,最后到数据库,字符串转其他类型。
读的时候,到页面,其他类型转成字符串
三十九、Struts2中提供的常用类型转换分几类?
a.基本数据类型自动转换。
b.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)。
c.字符串数组:默认用逗号+空格,连接成一个字符串
四十、自定义类型转换器是如何注册的?(两种情况)
局部类型转换器:只能指定javabean中的属性用
按照属性来注册。在属性所属的javabean的包下建立一个.properties文件。文件
名称:javabean名称-conversion.properties
全局类型转换器:(推荐)
按照要转换的数据类型来注册。at the top op classpath,建立一个固定名称
xwork-conversion.properties的属性文件。
四十一、如何解决编程式验证动作类中的全部动作方法都验证?
在动作类中覆盖public void validate()方法。
四十二、声明式验证的分别可以基于什么?
基于字段和验证器。
四十三、命名声明式验证xml文件名的两种方式,有什么不同?
a.针对动作类中的所有动作进行验证:在动作类所在的包中,建立一个
ActionClassName-validation.xml的文件
b、针对动作类中的某个动作进行验证:在动作类所在的包中建立一个xml文件,
名称为ActionClassName-ActionName-validation.xml。
四十四、国际化的消息资源文件如何命名?
一个资源包由多个文件组成,这些文件名都有命名规范:主要文件名_语言代码_
国家代码.properties。
语言代码:由iso规定的。国家代码:有iso规定的当文件只有主要文件
名.properties时,表明它是默认资源包。浏览器会根据不同的语言环境找对应语
言环境的资源包,当没有时,找默认的。
每个资源包的内容都由相同的key和对应语言环境的value组成。
比如:
message_zh_CN.properties message_zh_HK.properties
message_en_US.properties
四十五、 Struts2中全局,动作范围和包范围,哪个加载优先级高?页面上如何
读取指定的消息资源包?
动作范围。
四十六、Struts2中拦截器的执行时机?
拦截动作方法之前,正序执行;拦截动作方法之后,倒序执行。
四十七、自定义拦截器的步骤是什么?
a、编写一个类,继承AbstractInterceptor类或者实现Interceptor接口。重写
intercept方法。
b、配置拦截器:注意拦截器必须先声明再使用
四十八、多个拦截器如何确定执行顺序?
使用顺序。
四十九、自定义拦截器除了继承AbstractInterceptor还可以继承哪个?另一个有
什么好处?
可以继承MethodFilterInterceptor并且重写doIntercept方法。
通过参数注入的方式,哪个拦截和不拦截。
五十、文件上传是哪个拦截器为我们做的?如何限定上传文件的大小和类型?
fileupload拦截器
在struts.xml中改变default.properties文件中的常量。
给fileUpload拦截器注入参,数通过限制上传文件的MIME类型
五十一、struts2中文件下载是由哪个结果类型完成的?需要我们提供什么参数?
stream类型。输入流的字段名称(inputname)、文件类型(contentType)、响
应消息头(contentDisposition)
五十二、OGNL是什么?使用它能否访问普通方法?能否直接访问静态方法?
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是
一个单独的开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
可以直接访问普通方法。不能直接访问静态方法。需要在struts.xml中启用。
五十三、ActionContext和ValueStack什么时候创建?是否是线程安全的?
明确:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的
。与Struts1的区别是,struts1的动作类是单例的。
在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个
ActionContext和ValueStack对象。且每次动作访问都会创建。
这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部
变量(ThreadLocal)上了。所以是线程安全的。
五十四、ContextMap中的结构是什么样的?
除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又
封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结
构)
***********************************************************************
一、Struts2入门。【
1、Struts2框架介绍《
(1)它是MVC的一个框架,它以前叫做WebWork框架。后面它被Apache(阿帕奇)和
Sun(丧)公司收购了,Apache公司是我们比较出名的一个公司。
你用的tomcat也是Apache下面的。Oracle和jdk是Sun下面的。收购以后就给它取
了一个名字叫Stsrus2。
(2)什么是MVC?{<1>它是一种三层加构“模型Model、视图View、控制器
Controller”的模型<2>登录是怎样直行流程?首先在login.jsp页面做一个请求
,然后
请求到控制器“Controller Filter”,控制器对你的登录里的用户名跟密码进行
判断,判断完了后它才决定到底是到这个欢迎页面还是到主页面还是返回过去。
在
这个数据处理过程当中它要用到MVC的一个流程。}》
2、Struts2工作流程《
(1)客户端浏览器发出HTTP请求.
(2)根据web.xml配置,该请求被FilterDispatcher接收
(3)根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,
将值注入给Aciton
(4)Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
(5)Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并
跳转到相应页面
(6)返回HTTP响应到客户端浏览器》
3、Struts官方地址《
http://struts.apache.org。Struts2它在Apache这个平台上它的服务器在国外,
所以去登录的时候可能会有点慢,这和你的网速是没有关系的。》】
二、基本配置【
1、使用Struts2开发程序的基本步骤。
(1)加载Struts2类库,把下面的9个包复制到web项目中的WebContent目录下的
WEB-INF中的lib中。《
下载jar包,导入Web工程。推荐去官方网站下载,不要去百度搜索,因为它会有
很多插件。在浏览器上打开http://struts.apache.org这个网站,然后在
打开Download这个按钮,打开以后看它的新版本是<例如:Struts 2.5.12>代表它
的版本是2.5,12是第12次修改。推荐不要下载最新版本,下载倒数第二个版本。
[例如:Struts 2.3.33:
[1]{Full Distribution:struts-2.3.33-all.zip(65MB)[PGP][MD5],Struts2所
有安装以后的文件jar包都在里面。}
[2]{Example[举例,案例] Applications:struts-2.3.33-apps.zip(35MB)[PGP]
[MD5],这里面有一些例子,比如注册这么简单的它里面一定也有。}
[3]{Essential Dependencies Only:struts-2.3.33-min-lib.zip(4MB)[PGP]
[MD5],这个就比较关键了,这个就是你在使用Struts2这个框架的时候你需要的
一些
包,大约有十几个包,我们一般在开发过程中会用这个。}
[4]{All Dependencies Only:struts-2.3.33-lib.zip(19MB)[PGP][MD5],这个是
struts2当中你在使用的一些特殊功能的一个支持包或叫扩张功能的包。}
[5]{Source:struts-2.3.33-src.zip(7MB)[PGP][MD5],这个是源代码,推荐下载
下来。}
[6]下载[3][5]就行了。点击就可以下载,不需要收费。下载完以后解压,大约有
9个jar包。
{<1>struts2-core-xxx.jar[Struts 2框架的核心类库,这个必须要有。]
<2>xwork-core-xxx.jar[XWork类库,Struts 2的构建基础]
<3>ognl-xxx.jar[Struts 2使用的一种表达式语言类库]<4>freemarker-xxx.jar
[Struts 2的标签模板使用类库]
<5>javassist-xxx.GA.jar[对字节码进行处理]<6>commons-fileupload-xxx.jar[
文件上传时需要使用]
<7>commons-io-xxx.jar[Java IO扩展。commons开头的包代表是公共的包。]
<8>commons-lang-xxx.jar[包含了一些数据类型的工具类]
<9>commons-logging-1.1.3.jar。库中包含很多jar包,但是并不是都需要导入到
项目中,因此只需要选择与项目功能实现相关的jar包导入即可。}
[7]打开MyEclipse,新建web项目{Ctrl+n/输入‘web’/Web Project/Next/
[Project name:struts2、Java EE version:JavaEE 6-Web 3.0、Java
version:1.7
、JSTL Version:<none>]/Next/Next/(勾选)Generate web.xml dep....[自动生
成一个web.xml]/Next/Finish}
[8]把下载的9个jar包复制到web项目中的WebContent目录下的WEB-INF中的lib中
。]》
(2)配置web.xml文件《
[1]在src中新建com.zking.test包,包中新建Test.java{package
com.zking.test;import
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;
public class Test {public static void main(String[] args) {
//[导包的过程:StrutsPrepareAndExecuteFilter<Filter是过滤器,。Struts准
备和执行的过滤器/核心过滤器:StrutsPrepareAndExecuteFilters,Struts2要
启动就必须要这个东西>
在这里只要一个导包的过
程“org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilt
er;”》}}
[2]在WebContent下的WEB-INF中新建web.xml{在<web-app>标签中。...<!-- 配
置struts2的核心过滤器 -->
<filter><!--名字--><filter-name>struts2Filter</filter-name><!--名字所对
应的那个类--><filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter</filter-class></filter>
<filter-mapping><filter-name>struts2Filter</filter-name><url-
pattern>*.action</url-pattern></filter-mapping>}》
第一种:实现action接口《这种方法有它的局限性,就是Action里面只有execute
方法,而且必须使用这个方法》:
/**(3)开发视图层页面,也就是jsp文件。《
login.jsp{...<body><div align="Center"><!-- Login要跟struts.xml中的
<action name="Login">一样。-->
<form action="Login.action" method="post"><table><tr><td>用户名:
</td><td><input type="text" name="s_name"/> </td></tr><tr><td>密码:
</td>
<td><input type="password" name="s_pwd"/> </td></tr><tr
align="Center"><td colspan="2"><input type="submit" value="登录"/>
</td></tr>
</table></form></div></body></html>}》
(4)开发控制层Action[动作]《
在src中新建com.zking.action包,包中新建LoginAction.action{package
com.zking.action;import com.opensymphony.xwork2.Action;
/** 处理登录的action。*/public class LoginAction implements Action{//表
单的name属性值必须跟action中的属性值的名字一样,而且必须get/set封装。
private String s_name;private String s_pwd;//《get/set。》//《execute是
执行方法》public String execute() throws Exception {
System.out.println("到了LoginAction");//获取这两个值。
System.out.println("用户名:"+this.s_name);System.out.println("密
码:"+this.s_pwd);
//System.out.println(Actin.SUCCESS/Actin.NONE/Actin.ERROR);//<这个返回
值必须跟struts.xml中的<result name="success">一样。>return "success";}}
}》
(5)配置struts.xml文件[每一个框架都有一个配置文件]《
在src下面创建struts.xml文件{[1]Ctrl+n/输入'file'/File/Next/File
name:struts.xml[不要去改]/Finish。
[2]《<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!--name[名字可
随意],extends[它必须继承struts-default.xml<Libraries/Web App
Libraries/
struts2-core-2.3.33.jar下面。因为框架是别人的,所以要继承>]。namespace[
工作空间,这个"/"代表根目录,等一下去请求的时候它直接代表WebRoot]-->
<package name="defaultPackage" extends="struts-default"
namespace="/"><!-- name[名字可随意],用在loginjsp页面的form表单中的
action。
class[对应LoginAction类的全限命名]现在配置的LoginAction取了个名字叫
Login,等会根据Login来请求的时候就可以直接找到
com.zking.action.LoginAction。
UserAction里面的execute方法它会自动执行, 但也可以人为去设定。method[方
法的设定,它可以直接规定你进去到底执行的是哪个方法]-->
<action name="Login" class="com.zking.action.LoginAction"><!-- 找到之后
结果返回到welcome.jsp页面--><result name="success">welcome.jsp</result>
</action></package></struts>}》
(6)部署、运行项目《welcome.jsp{<body><h1>欢迎</h1></body>[发布Tomcat
。打开浏览器运行,输入用户名和密码看是否在控制台中打印用户名和密码]}》
**/
第二种:继承ActionSupport:
/**(3)在src中新建com.zking.entity,包中新建User.java{package
com.zking.entity;import java.io.Serializable;//Serializable序列化接口。
public class User implements Serializable{//表单的name属性值必须跟
action中的属性值的名字一样,而且必须get/set封装。
private String s_name;private String s_pwd;//无参构造。//《get/set。》}
}
(4)在src中新建com.zking.action包,包中新建UserAction.action{package
com.zking.action;import com.zking.entity.User;
import com.opensymphony.xwork2.Action;import
org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.ActionSupport;
/* * 处理登录的action。*/public class UserAction extends ActionSupport
{//用户对象属性。private User user;public User getUser(){return user;}
public void setUser(User user){this.user=user;}public UserAction()
{System.out.println("UserAction被实例化了。。。。");}
public String mylogin() throws Exception {System.out.println("到了
UserAction");//获取这两个值。System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());//将登录者信息放入
session 耦合方式。
ServletActionContext.getRequest().getSession().setAttribute("myUser",
this.user);return Action.SUCCESS;}
public String myreg() throws Exception {System.out.println("到了
LoginAction。。。。。。reg");System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());return
Action.SUCCESS;}}}
(5)配置struts.xml文件[每一个框架都有一个配置文件]《在src下面创建
struts.xml文件{[1]Ctrl+n/输入'file'/File/Next/File name:struts.xml[不
要去改]/Finish。
[2]《<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!--让struts2支
持动态方法调用--><constant name="struts.enable.DynamicMethodInvocation"
value="true" />
<package name="defaultPackage" extends="struts-default"
namespace="/"><action name="login" class="com.zking.action.UserAction">
<!-- 找到之后结果返回到welcome.jsp页面--><result
name="success">welcome.jsp</result></action></package></struts>}》
(6)login.jsp{...<body><div align="Center"><form action="login!
mylogin.action" method="post"><table><tr><td>用户名:</td>
<td><input type="text" name="user.s_name"/></td></tr><tr><td>密 码:
</td><td><input type="password" name="user.s_pwd"/></td></tr><tr
align="Center">
<td colspan="2"><input type="submit" value="登
录"/></td></tr></table></form></div></body></html>}
(7)welcome.jsp{<body><h1>欢迎。。。</h1>用户名:${myUser.s_name}
<br><a href="vip/myvip.jsp">去vip界面</a></body></html>}
(8)在WebContent下面建vip文件夹,myvip.jsp{<body>This is my JSP page.
<br></body>
[发布Tomcat。打开浏览器运行,输入用户名和密码看是否在控制台中打印用户名
和密码]}**/】
第二次(Struts2详细配置)
一、Action中属性的获取【(1)表单的name属性值必须跟action中的属性值名字
一样,而且必须封装(2)属性名-->action中属性名(3)属性对象名.属性名--
>action中属性】
二、在struts.xml下配置编码【<!--常量配置--><constant
name="struts.i18n.encoding" value="UTF-8"/>】
三、Action方法的动态调用【
A、要想使用动态调用,必须去打开‘<constant
name="struts.enable.DynamicMethodInvocation" value="true" />’动态调用
的开关,而且是在struts.xml里面通过一个常量配置。
动态语法《action名!方法名.action。举例:user!login.action 调用名字为
user的action下面的login方法{上面的第二种:继承ActionSupport用的就是!
的动态调用}》
B、通配符{*}形式的动态调用《<!--*代表所有的意思,可以是0个也可以是多个
。method=”{1}”里面的1代表第一个*的值--><action name= "*User" method=
”{1}”<result>{1}_success.jsp</result>》
举例:loginUser.action 调用名字为user的action下面的login方法。《在上面
的第二种:继承ActionSupport的基础上改。
(1)struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE
struts PUBLIC ……struts-2.0.dtd"><struts><!-- 让struts2支持动态方法调
用 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"
/><package name="defaultPackage" extends="struts-default"
namespace="/">
<!-- 。UserAction里面的execute方法它会自动执行, 但也可以人为去设定,
method[方法的设定,它可以直接规定你进去到底执行的是哪个方法]-->
<action name="*User" class="com.zking.action.UserAction"
method="{1}"><!-- 登录成功:找到之后结果返回到welcome.jsp页面-->
<result name="success">welcome.jsp</result></action></package></struts>
}
(2)把login.jsp里面的form表单改为<form action="myloginUser.action"
method="post">》】
四、全局错误action请求结果配置【就是在这里你请求了action可能会有个请求
的错误,我们一般会给一个错误界面处理。
struts.xml{写在<package>标签里面的<action>上面。<!--action请求不存在的
配置。如果是error错误就跳到all_error.jsp页面-->
<global-results><result name="error" >all_error.jsp</result></global-
results>}】
五、Result常用的结果类型,即type属性【
A、dispatcher(默认){底层使用RequestDispatcher转发请求}
B、redirect{底层使用sendRedirect将请求重定向}
C、redirectAction{重定向到action}《举例:product.action?myName=
${user.name}&myPwd=${user.pwd}<result name="success"
type="redirectAction">
<param name="actionName">product</param><param name="myName">
${user.name}</param><param name="myPwd">${user.pwd}</param></result>》
】
六、注解形式的Struts2配置《重点。写法<@Action("user")>它是一种全新的映
射关系,它会根据你的注解的名字去自动帮你的某个Action去实例化。》【
1、在配置之前必须要导包《struts2-convention-plugin-2.3.33.jar》
2、Action配置《@ParentPackage(value="struts-default")[你的父包是谁,父
包都要继承一个“struts-default”。它还有很多个属性,如果只有一个的话
value可省略]
@NameSpaces("/一般写Action的类名,但首字母要小写"){工作空间} @Action("
请求的是哪个方法")》
3、示例:在上面的基础上改。《
(1)struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!
DOCTYPE..."><struts><constant
name="struts.enable.DynamicMethodInvocation" value="true"
/>
<package name="defaultPackage" extends="struts-default"
namespace="/"></package></struts>}
(2)login.jsp{……<body><div align="Center"><form
action="user/mylogin.action" method="post"><table><tr><td>用户名:
</td><td><input type="text"
name="user.s_name"/>
</td></tr><tr><td>密 码:</td><td><input type="password"
name="user.s_pwd"/> </td></tr><tr align="Center"><td colspan="2"><input
type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(3)UserAction.java{package com.zking.action;import
com.zking.entity.User;import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;import
org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;import
com.opensymphony.xwork2.ActionSupport;/* * 处理登录的action。*/
@ParentPackage(value="struts-default")@Namespace("/user")public class
UserAction extends ActionSupport{private User user;public User getUser
() {return user;}
public void setUser(User user) {this.user = user;}public UserAction()
{System.out.println("UserAction被实例化了。。。。");}
@Action(value="/mylogin",results={@Result
(name="success",location="/welcome.jsp"),@Result
(name="fail",location="/login_fail.jsp")})
public String mylogin() throws Exception {System.out.println("到了
UserAction");System.out.println("用户名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd
());ServletActionContext.getRequest().getSession().setAttribute
("myUser", this.user);return "success";}
public String myreg() throws Exception {System.out.println("到了
LoginAction。。。。。。reg");System.out.println("用户
名:"+this.user.getS_name());
System.out.println("密 码:"+this.user.getS_pwd());return "toAction";}}
}》】
七、约定对Action的限制【
(1)约定Action类名:要求Action的命名必须以“Action”为后缀,例如:
UserAction、BookAction等等。可以使用下面常量来修改后缀限制:<constant
name="struts.convention.action.suffix" value="Action"/>
(2)约定Action包名:要求Action必须放到action、actions、struts、struts2
包中。例如:cn.itcast.action、cn.itcast.sturts、cn.itcast.action.user等
等。
可以使用下面常量来修改Actoin的包<constant
name="struts.convention.package.locators"
value="action,actions,struts,struts2"/>】
第三次(拦截器[Interceptor]+文件上传、下载)
一、struts2为什么用拦截器?【
1、拦截器[interceptor]是Struts2最强大的特性之一,也可以说是struts2的核
心,拦截器可以让你在Action和result被执行之前或之后进行一些处理。
同时,拦截器也可以让你将通用的代码模块化并作为可重用的类。Struts2中的很
多特性都是由拦截器来完成的。拦截是AOP的一种实现策略。
拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义
在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。
同时也是提供了一种可以提取action中可重用的部分的方式。
2、拦截器可以说相当于是个过滤器:就是把 不想要的或不想显示的内容给过滤
掉。拦截器可以抽象出一部分代码可以用来完善原来的action。
同时可以减轻代码冗余,提高重用率。比如在登入一个页面时,如果要求用户密
码、权限等的验证,就可以用自定义的拦截器进行密码验证和权限限制。
对符合的登入者才跳转到正确页面。这样如果有新增权限的话,不用在action里
修改任何代码,直接在interceptor里修改就行了。】
二、拦截器的优点?【
a:简化了Action的实现。拦截器能把很多功能从Action中独立出来,大量减少了
Action的代码。
b:功能更单一。按照上面的描述,把功能从Action中分离出来,分散到不同的拦
截器中,这样每个拦截器的功能,以及Action本身的功能就更单一了。
c:通用代码模块化。从Action中把功能分离出来,放到拦截器中去实现,这样能
把一些在多个Action中通用的代码进行模块化,封装在一个或者几个拦截器中。
d:提高重用性。当通用的功能代码被封装在拦截器中,实现了代码模块化过程之
后,就可以对不同的Action,根据功能需要,来配置相同的拦截器了。
e:实现AOP。
拦截器相比Filter具有更强大的功能,比如拦截器与Servlet的API无关,比如拦
截器可以访问到值栈等。】
三、Struts2的预定义拦截器?【
1、params拦截器{把请求参数设置进Action的相应属性,并自动进行类型转换}
2、staticParams拦截器{将struts.xml配置文件里定义的Action参数,设置到对
应的Action实例中,Action参数使用<param>标签,是<action>标签的子元素。
《<action name="hello" class="HelloAction"><param
name="account">test</param></action>》
这要求action中有一个account属性,并有相应的setter和getter方法,运行的时
候,action的account属性在初始化过后,会接到这里的赋值test。}
3、prepare拦截器{在action执行之前调用Action的prepare方法,这个方法是用
来准备action之前要做的工作,它要求用户必须实现
com.opensymphony.xwork2.Preparable接口。}
4、modelDriven拦截器{如果action实现了ModelDriven接口,它将getModel方法
取得的模型对象存入OgnlValueStack中。}
5、chain拦截器{chain拦截器,将前一个执行结束的Action属性设置到当前的
action中,它被用在ResultType为"chain"所指定的结果的Action中,
该结果Action对象会从值栈获得前一个Action对应的属性,它实现Action链之间
的数据传递。}
6、exception拦截器{在抛出异常的时候,这个拦截器起作用,任何应用都应该
引用这个拦截器,而且引用的时候,最好把它放在第一位,让它能捕获所有的异
常。}
7、validation拦截器{调用验证框架读取*-validation.xml文件,并且应用在这
些文件中声明的校验。}
8、token拦截器{核对当前Action请求(request)的有效标识,防止重复提交
Action请求,使用标签<s:token>可以生成表单令牌,该标签会在Session中设置
一个预期的值,
并且在表单中创建一个隐藏的input字段,Token拦截器会检查这个令牌,如果不
合法,将不会执行Action,这个拦截器是手工添加的,还需要一个
invalide.token的result。}
9、conversionError拦截器{用来处理框架进行类型转化(Type Conversion)时
的出错信息,它将存储在ActionContext中的类型转化错误信息转化成相应的
Action字段的错
误信息,保存在堆栈中。根据需要,可以将这些错误信息在视图中显示出来。}
10、fileUpload拦截器{用来处理上传文件}
11、workflow拦截器{Action默认的工作流,如果Action实现了Validateable接
口,那么interceptor会调用action的validate()方法,如果Action实现了
ValidateAware接口
,那么interceptor将会检查Action是否包含错误信息,如果包含错误信息,那么
Interceptor将会返回input,而不让Action继续执行。}
12、servletConfig拦截器{这个拦截器提供Action直接对Servlet API的调用,
把Servlet API的对象注入到Action中,包括ServletRequestAware,
ServletResponseAware
,ParameterAware,SessionAware和ApplicationAware}
13、timer拦截器{记录ActionInvocation剩余部分执行的时间,并作为日志信息
记录下来,便于寻找性能瓶颈。}
14、logger拦截器{在日志信息中输出要执行的Action信息,这样,在调试的时
候,就能很快的定位到这个对应的Action中了。}
15、tokenSession拦截器{扩展了token拦截器的功能,当提交无效的Action请求
标识时,它会跳转到第一次成功后的页面}】
四、struts2中拦截器实现的三种方式?【
1、实现Interceptor接口
2、继承AbstractInterceptor类
3、继承MethodFilterInterceptor类[当自定义拦截器配置了拦截参数时,自定义
拦截器必须使用该方法]
如:《<!-- 配置拦截器 --><interceptors><!-- 配置自定义拦截器,定义了一
个名为myInterceptor的拦截器 --><interceptor name="myInterceptor"
class="com.caokaiyuan.interceptor.MyInterceptor"></interceptor><!-- 配
置拦截器栈 --><interceptor-stack name="myStack"><interceptor-ref
name="defaultStack"/><!-- 加载默认拦截器 -->
<!-- 加载自定义拦截器 --><interceptor-ref name="myInterceptor"><!-- 配
置要拦截的方法;user,client为方法名 --><param
name="includeMethods">user,client</param>
<!-- 配置不需要拦截的方法;login为方法名 --><param
name="excludeMethods">login</param></interceptor-ref></interceptor-
stack></interceptors>》
此时必须要用方法三来实现自定义拦截器。】
五、拦截器与过滤器区别。【
(1)、拦截器是基于java的反射机制的,而过滤器是基于函数回调。
(2)、拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
(3)、拦截器与过滤器原理相似,拦截器只能对action请求起作用,而过滤器则
可以对几乎所有的请求起作用。
(4)、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
(5)、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初
始化时被调用一次
(6)、执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。】
六、拦截器的的调用顺序【
a:首先,要找到它自己有没有声明拦截器的引用,即<action>元素有没有
<interceptor-ref>子元素,如果有,则不用继续寻找,直接使用这些拦截器,如
果没有进行下一步的查找。
b:其次,找到这个<action>所在包有没有声明默认的拦截器引用,即<package>
元素的<default-interceptor-ref>子元素,如果有,则不用继续再找,直接使用
这些拦截器,如果没有,则进行下一步的查找。
c:递归的查找这个包的父包,看看有没有声明默认的拦截器引用,直到找到默认
的拦截器引用为止。】
七、开发自定义的拦截器【
开发自定义的拦截器,要实现Interceptor接口,还要使用到ActionInvocation接
口,现在对ActionInvocation接口进行简单的介绍。
它里面有一些方法,如下:《
a:getAction,获得这次请求准备执行的Action对象。
b:getProxy,返回这次请求的ActionProxy对象,可以在这个对象上获得要运行
Action的哪个方法。
c:getInvocationContext,返回这个Action执行的上下文(ActionContext),可
以在这个上下文对象中获得大量的数据,比如请求的parameter值,session的值
等。
d:在ActionContext中取到的parameter值是一个Map<String, Object>,其中以
String为key,以String[]为value,这个Map记录了所有的request参数。
e:getResult方法,返回Result运行之后代表结果的Result对象。》
我们要实现这样一个Aciton,要求拦截器输出如下的信息:运行哪个Action类,
运行哪个方法,请求的参数和Action运行完要跳转到哪个JSP。】
八、Struts2文件上传【
Struts2的文件上传实现非常简单,只需要简单几步就可完成;
注意:
(1)文件上传的struts2标签为:<s:file name="" label="上传"/>
(2)文件上传的前提是表单属性method="post" enctype="multipart/form-data";
(3)web应用中必须包含common-fileupload.jar和common-io.jar,因为struts2默
认上传解析器使用的是jakarta;
(4)可以在struts.xml中配置最大允许上传的文件大小:<constant
name="struts.multipart.maxSize" value="....."/>,默认为2M;
(5)普通文件上传{
实现规则:
[1]JSP中设定表单控件<s:file name="upload" label="上传"/>
[2]Action中定义属性:private File upload; //包含文件内容。private
String uploadFileName;//上传文件的名称;
private String uploadContentType;//上传文件的MIME类型;这些属性都会随着
文件的上传自动赋值;
[3]在execute()中完成写入磁盘功能;}】
九、struts2相关配置(参考)【
<!-- 指定由spring负责action对象的创建 --><constant
name="struts.objectFactory" value="spring" />
<!-- 所有匹配*.action的请求都由struts2处理 --><constant
name="struts.action.extension" value="action" />
<!-- 是否启用开发模式 --><constant name="struts.devMode" value="true"
/>
<!-- struts配置文件改动后,是否重新加载 --><constant
name="struts.configuration.xml.reload" value="true" />
<!-- 设置浏览器是否缓存静态内容 --><constant
name="struts.serve.static.browserCache" value="false" />
<!-- 请求参数的编码方式 --><constant name="struts.i18n.encoding"
value="utf-8" />
<!-- 每次HTTP请求系统都重新加载资源文件,有助于开发 --><constant
name="struts.i18n.reload" value="true" />
<!-- 文件上传最大值 --><constant name="struts.multipart.maxSize"
value="104857600" />
<!-- 让struts2支持动态方法调用 --><constant
name="struts.enable.DynamicMethodInvocation" value="true" />
<!-- Action名称中是否还是用斜线 --><constant
name="struts.enable.SlashesInActionNames" value="false" />
<!-- 允许标签中使用表达式语法 --><constant name="struts.tag.altSyntax"
value="true" />
<!-- 对于WebLogic,Orion,OC4J此属性应该设置成true --><constant
name="struts.dispatcher.parametersWorkaround" value="false" />】
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
1、拦截器。
(1)在lib中导入11个jar包。
(2)在src中建com.zking.action包和UserAction.java类{package
com.zking.action;import
javax.swing.plaf.basic.BasicSliderUI.ActionScroller;
import com.opensymphony.xwork2.ActionSupport;public class UserAction
extends ActionSupport{//登录。public String login() throws Exception {
System.out.println("到了UserAction。。。。。login");return "success";}}
}
(3)在src中建struts.xml配置文件{<?xml version="1.0" encoding="UTF-8"
?><!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts><!--编码配置--><constant name="struts.i18n.encoding"
value="UTF-8"/>
<!-- 打开方法动态调用开关 constant:常量--><constant
name="struts.enable.DynamicMethodInvocation" value="true" />
<package name="mypackage" extends="struts-default"
namespace="/"><interceptors><interceptor name="encodInter"
class="com.zking.interceptor.EncodInterceptor">
</interceptor><interceptor name="userLoinInter"
class="com.zking.interceptor.UserLoginInterceptor"></interceptor><!--
拦截器栈 stack:栈 -->
<interceptor-stack name="mys"><interceptor-ref
name="defaultStack"></interceptor-ref><interceptor-ref
name="encodInter"></interceptor-ref>
<interceptor-ref name="userLoinInter"></interceptor-ref></interceptor-
stack></interceptors><!--<default-interceptor-ref
name="mys"></default-interceptor-ref>-->
<!-- action配置 --><action name="user"
class="com.zking.action.UserAction"><interceptor-ref
name="mys"></interceptor-ref><param name="abc">utf-8</param>
<result name="success">login_success.jsp</result><result
name="login">login.jsp</result></action><action name="myfile"
class="com.zking.action.FileAction">
<result
name="success">file_success.jsp</result></action></package></struts>}
(4)web.xml{...<!-- struts2 核心过滤器配置 --> <filter><filter-
name>struts2</filter-name>
<filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter</filter-class></filter>
<filter-mapping><filter-name>struts2</filter-name><url-
pattern>*.action</url-pattern></filter-mapping></web-app>}
(5)login.jsp{<body><div align="Center"><form action="user!
login.action" method="post"><table><tr><td>用户名:</td><td><input
type="text" name="s_name"/></td>
</tr><tr><td>密 码:</td><td><input type="password"
name="s_pwd"/></td></tr><tr align="Center"><td colspan="2"><input
type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(6)在src中建com.zking.interceptor包和EncodInterceptor.java类{package
com.zking.interceptor;import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class EncodInterceptor extends AbstractInterceptor{//intercept:
拦截。@Override public String intercept(ActionInvocation arg0) throws
Exception {
System.out.println("到了EncodInterceptor。。。。");//设置编码。
ServletActionContext.getRequest().setCharacterEncoding("UTF-8");
ServletActionContext.getResponse().setCharacterEncoding("UTF-
8");//ServletActionContext 获取config对象。return arg0.invoke();}}}
(7)UserLoginInterceptor.java类{package com.zking.interceptor;import
java.util.Map;import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;import
com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/** * 判断用户是否登录 * @author Teacher'Tan * */public class
UserLoginInterceptor extends AbstractInterceptor{//intercept:拦截。
@Override public String intercept(ActionInvocation arg0) throws
Exception {System.out.println("到了UserLoginInterceptor。。。。");//获
取当前登陆者信息。
Map<String, Object> session = arg0.getInvocationContext().getSession
();Object userObj = session.get("myuser");//判断。if(userObj==null){
return Action.LOGIN;}//拦截器栈。return arg0.invoke();}}}
2、文件上传、下载。
(1)fileup.jsp{<body><div align="Center"><form action="myfile!
upload.action" method="post" enctype="multipart/form-
data"><table><tr><td>文件上传:</td>
<td><input name="myf" type="file" /> </td></tr><tr align="Center"><td
colspan="2"><input type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(2)FileAction.java{package com.zking.action;import
java.io.File;import java.io.FileInputStream;import
java.io.FileOutputStream;
import javax.swing.plaf.basic.BasicSliderUI.ActionScroller;import
org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.ActionSupport;
public class FileAction extends ActionSupport{//文件对象 myf必须跟表单
的那么值一样。private File myf;//文件类型。private String
myfContentType;//文件名字。
private String myfFileName;//登录。public String upload() throws
Exception {System.out.println("到了UserAction。。。。。upload");
System.out.println("文件:"+this.myf);System.out.println("类
型:"+this.myfContentType);System.out.println("文件名
字:"+this.myfFileName);
//输入流。FileInputStream fis = new FileInputStream(myf);//输出流。
String path = ServletActionContext.getServletContext().getRealPath
("/myupload");
path = path+"\\"+this.getMyfFileName();System.out.println
("path:"+path);FileOutputStream fos = new FileOutputStream(path);int
n;while((n=fis.read())!=-1){
//System.out.println(n);//写入。fos.write(n);}//关闭流。fis.close
();fos.close();return "success";}public File getMyf() {return myf;}
public void setMyf(File myf) {this.myf = myf;}public String
getMyfContentType() {return myfContentType;}public void
setMyfContentType(String myfContentType){
this.myfContentType = myfContentType;}public String getMyfFileName()
{return myfFileName;}public void setMyfFileName(String myfFileName){
this.myfFileName = myfFileName;}}}
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
示例1:struts2完美实现文件上传和下载!
(1)第一步:在webx项目lib目录下加入struts.jar包{asm-3.3.jar、asm-
commons-3.3.jar、asm-tree-3.3.jar、commons-fileupload-1.3.1.jar、
commons-io-2.2.jar
、commons-lang3-3.2.jar、freemarker-2.3.22.jar、javassist-3.11.0.GA.jar
、log4j-api-2.2.jar、log4j-core-2.2.jar、ognl-3.0.6.jar
struts2-core-2.3.24.1.jar、struts2-dojo-plugin-2.3.24.1.jar、xwork-
core-2.3.24.1.jar}
(2)第二步:配置web.xml{<?xml version="1.0" encoding="UTF-8"?><web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
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"><display-name>Struts08</display-name><!--
struts2.配置--><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>*.action</url-pattern><url-pattern>*.jsp</url-
pattern></filter-mapping><!-- struts2配置--><welcome-file-list>
<welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>`}
(3)第三步:配置struts.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><!-- 设置字符编
码 --><constant name="struts.i18n.encoding" value="utf-8" /><!-- 设置自
动装载国际化 -->
<constant name="struts.i18n.reload" value="true" /><!-- 设置动态方法调
用 --><constant name="struts.enable.DnamicMethodInvocation"
value="true" />
<!-- 设置开发模式 --><constant name="struts.devMode" value="true"
/><!-- 指定每次配置文件更改后,自动重新加载 -->
<constant name="struts.configuration.xml.reload" value="true" /><!-- 设
置访问方式 --><constant name="struts.action.extension" value="action,,"
/>
<!-- 去除多余的格式 --><constant name="struts.ui.theme" value="simple"
/><!--设置上传文件大小20MB,默认为2MB大小 -->
<constant name="struts.multipart.maxSize"
value="20971520"></constant><package name="default" extends="struts-
default" namespace="/"><!-- 文件上传配置 -->
<action name="m" class="com.action.UploadManyFile"><!-- 文件上传到user
目录下--><param name="path">/user</param><param
name="size">10240000</param></action>
<!-- 文件下载配置 --><action name="down"
class="com.action.FileDownloadAction"><param
name="path">/user</param><result name="success" type="stream">
<param name="contentType">application/octet-stream</param><param
name="inputName">inputStream</param> <param
name="inputName">inputStream</param>
<param name="contentDisposition">filename=${fn}</param><param
name="bufferSize">4096</param></result></action></package></struts>}
(4)第四步:jsp写入代码{<%@ page language="java"
pageEncoding="UTF8"%><!Doctype html><html ><head><meta charset="UTF-8"
/><title>struts2 多文件上传</title>
</head><body><h1>struts-多文件 上传</h1><form action="m.action"
method="post" enctype="multipart/form-data">姓名:<input type="text"
name="name" value="张三"><br>
文件:<input type="file" name="fs" multiple ><br>文件1:<input
type="file" name="fs" multiple ><br>文件2:<input type="file" name="fs"
multiple ><br>
文件3:<input type="file" name="fs" multiple ><br><input type="submit"
value="上传"><br></form><hr><h1>文件下载</h1><a href="user/abc.jpg">下
载</a>
<a href="user/abc.rar">下载zip</a><a href="down.action?
fn=abc.rar">struts2文件下载</a></body></html>}
(5)第五步:在src目录下建立com.action包建立UploadManyFile{package
com.action;import java.io.File;import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;import
org.apache.struts2.ServletActionContext;import
org.apache.struts2.util.ServletContextAware;
import com.opensymphony.xwork2.ActionSupport;public class
UploadManyFile extends ActionSupport implements ServletContextAware
{private String name;
private File[] fs; //文件名。private String [] fsFileName;private
String[] fsContentType;//文件类型。private String path;//文件路径
private int size; //文件大小。
private ServletContext ctx;public String getName() {return name;}public
void setName(String name) {this.name = name;}public File[] getFs()
{return fs;}
public void setFs(File[] fs) {this.fs = fs;}public String getPath()
{return path;}public void setPath(String path) {this.path = path;}
public int getSize() {return size;}public void setSize(int size)
{this.size = size;}public String[] getFsFileName() {return fsFileName;}
public void setFsFileName(String[] fsFileName) {this.fsFileName =
fsFileName;}public String[] getFsContentType() {return fsContentType;}
public void setFsContentType(String[] fsContentType)
{this.fsContentType = fsContentType;}@Override public void
setServletContext(ServletContext ctx) {
this.ctx=ctx;}@Override public String execute() throws Exception
{String p=ctx.getRealPath(path);File f=new File(p);if(!f.exists())
{f.mkdirs();}
for(int i=0;i<fs.length;i++){System.out.println
(path);System.out.println(p);System.out.println
(size);System.out.println(fs[i].length());
System.out.println("------------");/* * 如果文件大于上传限定值*/if(fs
[i].length()<size){FileUtils.copyFile(fs[i],new File(f,fsFileName
[i]));}}return null;}}}
(6)第六步:建立FileDownloadAction{package com.action;import
java.io.FileInputStream;import java.io.FileNotFoundException;import
java.io.InputStream;
import org.apache.struts2.ServletActionContext;import
com.opensymphony.xwork2.Action;public class FileDownloadAction
implements Action {
private String fn; //文件名。private String path; //路径。public String
getFn() {return fn;}public void setFn(String fn) {this.fn = fn;}
public String getPath() {return path;}public void setPath(String path)
{this.path = path;}@Override public String execute() throws Exception
{return SUCCESS;}
public InputStream getInputStream() throws Exception{//获得路径和文件名
。String ip=ServletActionContext.getServletContext().getRealPath
(path)+"/"+fn;
InputStream is=new FileInputStream(ip);return is;}}}
(7)第七步输入项目名称运行。
-----------------------------------------------------------------------
-----------------------------------------------------------------------
------------------------------------------------------------
第四次(优化)
第一部分【
(1)在lib中导入11个jar包。
(2)在src中建com.zking.action包和UserAction.java类{package
com.zking.action;import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport{public String login()
throws Exception {System.out.println("到了UserAction");
//这里必须要配置,不然后报404错。return "success";}}}
(3)在src中建struts.xml{<?xml version="1.0" encoding="UTF-8" ?><!
DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts
Configuration
2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"><struts><!-- 打开方法的
动态调用 --><constant name="struts.enable.DynamicMethodInvocation"
value="true" />
<package name="mypackage" extends="struts-default"
namespace="/"><action name="user" class="com.zking.action.UserAction">
<!--根据你返回的结果字符串找到对应的页面,这是种映射关系--><result
name="success">login_success.jsp</result></action></package></struts>}
(4)web.xml{<?xml version="1.0" encoding="UTF-8"?><web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
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">
<display-name>Stsrus2</display-name><welcome-file-list><welcome-
file>index.html</welcome-file></welcome-file-list>
<!-- struts2核心过滤器配置 --><filter><filter-name>struts2</filter-
name><filter-
class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFi
lter
</filter-class></filter><filter-mapping><filter-name>struts2</filter-
name><url-pattern>*.action</url-pattern></filter-mapping></web-app>}
(5)login.jsp{<body><div align="Center"><!--这是种动态调用--><form
action="user!login.action" method="post"><table>
<tr><td>用户名:</td><td><input type="text"
name="s_name"/></td></tr><tr><td>密码:</td><td><input type="password"
name="s_pwd"/></td></tr>
<tr align="Center"><td colspan="2"><input type="submit" value="登录"/>
</td></tr></table></form></div></body>}
(6)login_success.jsp{<body>This is my login_success.jsp <br><a
href="test.action?myname=小白">去testAction</a></body>}】
第二部分配置拦截器。【
(7)在src中建com.zking.interceptor包和UserInterceptor.java类{package
com.zking.interceptor;import java.util.Map;
import com.opensymphony.xwork2.ActionInvocation;import
com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class UserInterceptor extends AbstractInterceptor
{@Overridepublic String intercept(ActionInvocation arg0) throws
Exception {
//获取session中的登陆者信息。System.out.println("到了UserInterceptor。
。。。。");Map<String, Object> session = arg0.getInvocationContext
().getSession();
//判断。Object obj = session.get("myuser");if(obj==null){//返回登录界面
。return "login";}return arg0.invoke();}}}
(8)struts.xml{在原有的基础上加[1]“<result
name="login">login.jsp</result>”,把它放到<action>中。
[2]“<interceptors><interceptor name="userLoginInter"
class="com.zking.interceptor.UserInterceptor"></interceptor></intercept
ors>”把它放到<action>上面。
[3]“<interceptor-ref name="defaultStack"></interceptor-
ref><interceptor-ref name="userLoginInter"></interceptor-ref>”把它放到
<action>中<result>上面。}】
第三部分【
(9)在src中建com.zking.entity包和User.java类{package
com.zking.entity;import java.io.Serializable;
public class User implements Serializable {private String
s_name;private String s_pwd;《无参构造、封装》}}
(10)UserAction.java{package com.zking.action;import
org.apache.log4j.Logger;import
com.opensymphony.xwork2.ActionSupport;import com.zking.entity.User;
public class UserAction extends ActionSupport {//日志属性。private
Logger log = Logger.getLogger(UserAction.class);
//用户属性。private User user;《封装》public String login() throws
Exception {//日志打印 log4j。log.info("到了UserAction。。。。");
//到数据去查询//如果成功,将登陆者信息放入session(解耦方式)//如果失败,
返回login.jsp。return "success";}}}
(11)login.jsp{把里面用户名和密码的name=“s_name,s_pwd”改
为“user.s_name,user.s_pwd”。}
(12)在src中建log4j.properties{log4j.rootLogger =INFO,A1 #输出到控制
台? log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm
\:ss,SSS}][%c]%m%n
log4j.appender.systemOut.Threshold =?ALL
log4j.appender.A1.Target=System.out
##保存到文件
#log4j.appender.FileLog = org.apache.log4j.RollingFileAppender
#log4j.appender.FileLog.MaxFileSize = 1MB
#log4j.appender.FileLog.MaxBackupIndex = 14
#log4j.appender.FileLog.File =G160618.log
#log4j.appender.FileLog.layout = org.apache.log4j.PatternLayout
#log4j.appender.FileLog.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm
\:ss,SSS}][%c] %m%n
##发送到邮件
#log4j.appender.mail=org.apache.log4j.net.SMTPAppender
#log4j.appender.mail.Threshold=ERROR
#log4j.appender.mail.BufferSize=1
#log4j.appender.mail.SMTPHost=smtp.163.com
##发件邮箱、收件邮件
#log4j.appender.mail.From=18569032110@163.com
#log4j.appender.mail.To=1793489869@qq.com
##发送邮件箱的用户名、密码
#log4j.appender.mail.SMTPUsername=18569032110@163.com
#log4j.appender.mail.SMTPPassword=tn8522155
##邮箱主题
#log4j.appender.mail.Subject=This's T199_Test Error Message
#log4j.appender.mail.layout=org.apache.log4j.PatternLayout
#log4j.appender.mail.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH
\:mm\:ss,SSS}][%c]\:%m%n}
(13)struts.xml{把“<interceptor-ref
name="defaultStack"></interceptor-ref><interceptor-ref
name="userLoginInter"></interceptor-ref>”注释}】
第四部分【
(14)在src中建com.zking.service包和UserServiceI.java接口{//登录。
public boolean login(User user);}
(15)在src中建com.zking.service.impl包和UserServiceImpl.java类{public
class UserServiceImpl implements UserServiceI {//UserDao属性。
private BaseDao<User> baseDao = new UserDaoImpl();@Override public
boolean login(User user) {return baseDao.login(user);}}}
(16)在src中建com.zking.dao包和BaseDao.java接口{public boolean login
(T t);}
(17)在src中建com.zking.dao.impl包和UserDaoImpl.java类{public class
UserDaoImpl implements BaseDao<User>{@Override public boolean login
(User user){
//调用DBHelper的方法。。。。return false;}}}
(18)UserAction.java{public class UserAction extends ActionSupport
{private Logger log = Logger.getLogger(UserAction.class);
//UserService属性。private UserServiceI userService = new
UserServiceImpl();private User user;《封装》public String login()
throws Exception {
log.info("到了UserAction。。。。");userService.login(this.user);return
"success";}}}
(19)在com.zking.action包中BaseAction.java类{package
com.zking.action;import java.io.IOException;import
org.apache.struts2.ServletActionContext;
public class BaseAction {//向页面写入JSON字符串的方法。public void
writeJSON(Object obj) throws IOException{//将obj转换成JSON。String
strJSON = "";
//。。。。。ServletActionContext.getPageContext().getResponse
().getWriter().print(strJSON);}}}】
.......................................................................
.......................................................................
.......................................................................
..................
报错:
1、java.lang.NoSuchMethodException:
com.zking.action.UserAction.myloginUser()
【解决方法:查看一下你的struts.xml配置文件的action名字格式是否写对,或
者查看你的jsp里面的form表单是否和struts.xml里面的action名字对应。】
2、java.lang.IllegalArgumentException: attempt to create saveOrUpdate
event with null entity
【解决方法:查看一下你jsp里面属性名字有没有加上对象。】
3、java.lang.NoClassDefFoundError:org/objectweb/asm/ClassVisitor
【字节码错误。解决方案:导包:asm-all-3.3.1.jar】
4、警告: Could not find action or result: /Struts2/userAction!
mylogin.action
There is no Action mapped for namespace [/] and action name
[userAction] associated with context path [/Struts2]. - [unknown
location]
【解决方法:(1)把"@Action()"删除。因为struts.xml里面开起了一个动态方法
的调用。然后在jsp页面请求的时间也用了。所以它直接到达了你的方法。
(2)把@Namespace改为“@Namespace("/")”,把“@Action()”还原,把jsp页面里
面的form表单里面的action改为“action="mylogin.action" ”
(3)把@Namespace改为“@Namespace("/user")”,把“@Action("/mylogin")”还
原,把jsp页面里面的form表单里面的action改为“action="mylogin.action"”
前面三种方法运行完以后还是会报错,因为后面还有东西没有写完,所以不要紧
。查看控制台是否打印“UserAction被实例化了。。。。到了UserAction用户名
:we密 码:1243”
(4)动态配置:改成:把所有的return都改成"success"。 @Action
(value="/mylogin",results={@Result
(name="success",location="/welcome.jsp"),
@Result(name="fail",location="/fail.jsp")})用第四种方法不会在报错了。】
.......................................................................
.......................................................................
.......................................................................
..................
-----------------------------------
----------------------------
MyEclipse:
新建web项目{Ctrl+n/输入‘web’/Web Project/Next/[Project name:struts2
、Java EE version:JavaEE 6-Web 3.0、Java version:1.7
、JSTL Version:<none>]/Next/Next/(勾选)Generate web.xml dep....[自动生
成一个web.xml]/Next/Finish}
-----------------------------------
----------------------------
***********************************************************************
***********************************************************************
************************************************************
Struts2面试题:
一、Struts2工作流程:
1、客户端浏览器发出HTTP请求.
2、根据web.xml配置,该请求被FilterDispatcher(核心控制器)接收
3、根据struts.xml配置,找到需要调用的Action类和方法, 并通过IoC方式,将
值注入给Aciton
4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证。
5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result,并跳
转到相应页面
6、返回HTTP响应到客户端浏览器
二、拦截器和过滤器的区别:
1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2、过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。
4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。
5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时
被调用一次。
三、说下Struts的设计模式
MVC模式
什么是MVC?{<1>它是一种三层加构“模型Model、视图View、控制器Controller
”的模型<2>登录是怎样直行流程?首先在login.jsp页面做一个请求,然后
请求到控制器“Controller Filter”,控制器对你的登录里的用户名跟密码进行
判断,判断完了后它才决定到底是到这个欢迎页面还是到主页面还是返回过去。
在
这个数据处理过程当中它要用到MVC的一个流程。}
四、struts1于struts2的比较:
1、Action类:
Struts1要求Action类继承一个抽象基类。Struts1的一个普遍问题是使用抽象类
编程而不是接口。
Struts2 Action类可以实现一个Action接口,也可实现其他接口,使可选和定制
的服务成为可能。Struts2提供一个ActionSupport基类去 实现常用的接口。
Action接口不是必须的,任何有execute标识的POJO对象都可以用作Struts2的
Action对象。
2、线程模式:
Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例
来处理所有的请求。单例策略限制了Struts1 Action能作的事,并且要在开发时
特别小心。Action资源必须是线程安全的或同步的。
Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实
际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾
回收问题)
3、Servlet依赖:
Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时
HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
Struts2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,
Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少
或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。
4、可测性:
测试Struts1 Action的一个主要问题是execute方法暴露了servlet API(这使得
测试要依赖于容器)。一个第三方扩展--Struts TestCase--提供了一套
Struts1的模拟对象(来进行测试)。
Struts 2 Action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支
持也使测试更容易。
5、捕获输入:
Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须继承一个基类。
因为其他JavaBean不能用作ActionForm,开发者经 常创建多余的类捕获输入。动
态Bean(DynaBeans)可以作为创建传统ActionForm的选择,但是,开发者可能是
在重新描述(创建)已经存 在的JavaBean(仍然会导致有冗余的javabean)。
Struts2 直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。
输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过 web页面
上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对
象,能够用作输入/输出对象。这种 ModelDriven 特性简化了taglib对POJO输入
对象的引用。
6、表达式语言:
Struts1 整合了JSTL,因此使用JSTL EL。这种EL有基本对象图遍历,但是对集合
和索引属性的支持很弱。
Struts2可以使用JSTL,但是也支持一个更强大和灵活的表达式语言-- "Object
Graph Notation Language " (OGNL).
7、绑定值到页面(view):
Struts1使用标准JSP机制把对象绑定到页面中来访问。
Struts2使用 "ValueStack "技术,使taglib能够访问值而不需要把你的页面
(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同
的属性重用页面(view)。
8、类型转换:
Struts1 ActionForm 属性通常都是String类型。Struts1使用Commons-Beanutils
进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
Struts2 使用OGNL进行类型转换。提供基本和常用对象的转换器。
9、校验:
Struts1支持在ActionForm的validate方法中手动校验,或者通过Commons
Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用
为属性类类型定义的校验和内容校验,来支持chain校验子属性
10、Action执行的控制:
Struts1支持每一个模块有单独的Request Processors(生命周期),但是模块中
的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的
生命周期。堆栈能够根据需要和不同的Action一起使用。
五、为什么要使用Struts2?
1、【首先,它是一个基于MVC的web应用框架,基于struts1和webwork,合并优化
之后的产物。
对于广大用户给它的赞美,这里简单的翻译一下apache网站下的两段话。
《阿帕奇的struts2项目是一个优雅的,可扩展的框架,可以用来创建为企业准备
的javaWeb应用,这个框架被设计来简化整个开发的周期,从构建到部署到维护,
贯穿整个软件生命周期的时间段。阿帕奇struts2最初被叫做WebWork2,独立工作
数年之后,webWork和Struts的交流合作促进创造了strust2,这个新版本的struts
简化了使用,跟之前我们想要使用的struts很接近。》
从这两段话看出,其实它主要就两个价值点,一个是可扩展性,第二个就是简化
了web应用的开发周期。】
2、【Struts2 是一个相当强大的Java Web开源框架,是一个基于POJO的Action的
MVC Web框架。它基于当年的Webwork和XWork框架,继承其优点,同时做了相当的
改进。
(1)Struts2基于MVC架构,框架结构清晰,开发流程一目了然,开发人员可以很
好的掌控开发的过程。
(2)使用OGNL进行参数传递。
OGNL提供了在Struts2里访问各种作用域中的数据的简单方式,你可以方便的获取
Request,Attribute,Application,Session,Parameters中的数据。大大简化
了开发人员在获取这些数据时的代码量。
(3)强大的拦截器
Struts2 的拦截器是一个Action级别的AOP,Struts2中的许多特性都是通过拦截
器来实现的,例如异常处理,文件上传,验证等。拦截器是可配置与重用的,可
以将一些通用的功能如:登录验证,权限验证等置于拦截器中以完成一些Java
Web项目中比较通用的功能。在我实现的的一Web项目中,就是使用Struts2的拦截
器来完成了系统中的权限验证功能。
(4)易于测试
Struts2的Action都是简单的POJO,这样可以方便的对Struts2的Action编写测试
用例,大大方便了5Java Web项目的测试。
易于扩展的插件机制在Struts2添加扩展是一件愉快而轻松的事情,只需要将所需
要的Jar包放到WEB-INF/lib文件夹中,在struts.xml中作一些简单的设置就可以
实现扩展。
(6)模块化管理
Struts2已经把模块化作为了体系架构中的基本思想,可以通过三种方法来将应用
程序模块化:将配置信息拆分成多个文件把自包含的应用模块创建为插件创建新
的框架特性,即将与特定应用无关的新功能组织成插件,以添加到多个应用中去
。
(7)全局结果与声明式异常
为应用程序添加全局的Result,和在配置文件中对异常进行处理,这样当处理过
程中出现指定异常时,可以跳转到特定页面。
他的如此之多的优点,是很多人比较的青睐,与spring ,Hibernate进行结合,组
成了现在比较流行的ssh框架,当然每个公司都要自己的框架,也是ssh变异的产
品。】
六、struts2有哪些优点?
1)在软件设计上Struts2的应用可以不依赖于Servlet API和struts API。
Struts2的这种设计属于无侵入式设计;
2)拦截器,实现如参数拦截注入等功能;
3)类型转换器,可以把特殊的请求参数转换成需要的类型;
4)多种表现层技术,如:JSP、freeMarker、Velocity等;
5)Struts2的输入校验可以对指定某个方法进行校验;
6)提供了全局范围、包范围和Action范围的国际化资源文件管理实现
七、struts2是如何启动的?
struts2框架是通过Filter启动的,即StrutsPrepareAndExecuteFilter,此过滤
器为struts2的核心过滤器;
StrutsPrepareAndExecuteFilter的init()方法中将会读取类路径下默认的配置文
件struts.xml完成初始化操作。struts2读取到struts.xml的内容后,是将内容封
装进javabean对象然后存放在内存中,以后用户的每次请求处理将使用内存中的
数据,而不是每次请求都读取struts.xml文件。
八、struts2框架的核心控制器是什么?它有什么作用?
1)Struts2框架的核心控制器是StrutsPrepareAndExecuteFilter。
2)作用:
负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到
达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径
不带后缀或者后缀以.action结尾,这时请求将被转入struts2框架处理,否则
struts2框架将略过该请求的处理。
可以通过常量"struts.action.extension"修改action的后缀,如:
<constant name="struts.action.extension" value="do"/>
如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。
<constant name="struts.action.extension" value="do,go"/>
九、struts2配置文件的加载顺序?
struts.xml ——> struts.properties
常量可以在struts.xml或struts.properties中配置,如果在多个文件中配置了同
一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值.
struts.xml文件的作用:通知Struts2框架加载对应的Action资源
十、struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置,两种配置方式如下:
1)在struts.xml文件中配置常量
<constant name="struts.action.extension" value="do"/>
2)在struts.properties中配置常量(struts.properties文件放置在src下):
struts.action.extension=do
十一、struts2如何访问HttpServletRequest、HttpSession、ServletContext三
个域对象?
方案一:【
HttpServletRequest request =ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session= request.getSession();
ServletContext servletContext=ServletActionContext.getServletContext();
】
方案二: 【
类 implements ServletRequestAware,ServletResponseAware,SessionAware,
ServletContextAware 】
注意:框架自动传入对应的域对象 。
十二、struts2是如何管理action的?这种管理方式有什么好处?
struts2框架中使用包来管理Action,包的作用和java中的类包是非常类似的。
主要用于管理一组业务功能相关的action。在实际应用中,我们应该把一组业务
功能相关的Action放在同一个包下。
十三、struts2中的默认包struts-default有什么作用?
1)struts-default包是由struts内置的,它定义了struts2内部的众多拦截器和
Result类型,而Struts2很多核心的功能都是通过这些内置的拦截器实现,如:从
请求中
把请求参数封装到action、文件上传和数据验证等等都是通过拦截器实现的。当
包继承了struts-default包才能使用struts2为我们提供的这些功能。
2)struts-default包是在struts-default.xml中定义,struts-default.xml也是
Struts2默认配置文件。 Struts2每次都会自动加载 struts-default.xml文件。
3)通常每个包都应该继承struts-default包。
十四、struts2如何对指定的方法进行验证?
1)validate()方法会校验action中所有与execute方法签名相同的方法;
2)要校验指定的方法通过重写validateXxx()方法实现, validateXxx()只会校
验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写;
3)当某个数据校验失败时,调用addFieldError()方法往系统的fieldErrors添加
校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport
), 如果系统 的fieldErrors包含失败信息,struts2会将请求转发到名为input
的result;
4)在input视图中可以通过<s:fielderror/>显示失败信息。
5)先执行validateXxxx()->validate()->如果出错了,会转发<result
name="input"/>所指定的页面,如果不出错,会直接进行Action::execute()方法
十五、struts2默认能解决get和post提交方式的乱码问题吗?
不能。struts.i18n.encoding=UTF-8属性值只能解析POST提交下的乱码问题。
十六、请你写出struts2中至少5个的默认拦截器?
fileUpload 提供文件上传功能
cookies 使用配置的name,value来是指cookies
checkbox 添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为
false,而html默认情况下不提交没有选中的checkbox。
chain 让前一个Action的属性可以被后一个Action访问,现在和chain类型的
result()结合使用。
alias 在不同请求之间将请求参数在不同名字件转换,请求内容不变
十七、值栈ValueStack的原理与生命周期?
1)ValueStack贯穿整个 Action 的生命周期,保存在request域中,所以
ValueStack和request的生命周期一样。当Struts2接受一个请求时,会迅速创建
ActionContext, ValueStack,action。然后把action存放进ValueStack,所以
action的实例变量可以被OGNL访问。 请求来的时候,action、ValueStack的生命
开始,请求结束,action、
ValueStack的生命结束;
2)action是多例的,和Servlet不一样,Servelt是单例的;
3)每个action的都有一个对应的值栈,值栈存放的数据类型是该action的实例,
以及该action中的实例变量,Action对象默认保存在栈顶;
4)ValueStack本质上就是一个ArrayList;
5)关于ContextMap,Struts 会把下面这些映射压入 ContextMap 中:
parameters : 该 Map 中包含当前请求的请求参数
request : 该 Map 中包含当前 request 对象中的所有属性 session :该 Map 中
包含当前 session 对象中的所有属性
application :该 Map 中包含当前 application 对象中的所有属性
attr:该 Map 按如下顺序来检索某个属性: request, session, application
6)使用OGNL访问值栈的内容时,不需要#号,而访问request、session、
application、attr时,需要加#号;
7)注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:
<s:property value="name"/>
8)在struts2配置文件中引用ognl表达式 ,引用值栈的值 ,此时使用的"$",而
不是#或者%;
十八、ActionContext、ServletContext、pageContext的区别?
1)ActionContext是当前的Action的上下文环境,通过ActionContext可以获取到
request、session、ServletContext等与Action有关的对象的引用;
2)ServletContext是域对象,一个web应用中只有一个ServletContext,生命周
期伴随整个web应用;
3)pageContext是JSP中的最重要的一个内置对象,可以通过pageContext获取其
他域对象的应用,同时它是一个域对象,作用范围只针对当前页面,当前页面结
束时,pageContext销毁, 生命周期是JSP四个域对象中最小的。
十九、result的type属性中有哪几种结果类型?
dispatcher
struts默认的结果类型,把控制权转发给应用程序里的某个资源不能把控制权转
发给一个外部资源,若需要把控制权重定向到一个外部资源, 应该使用
redirect结果类型
redirect 把响应重定向到另一个资源(包括一个外部资源)
redirectAction 把响应重定向到另一个 Action
freemarker、velocity、chain、httpheader、xslt、plainText、stream
二十、拦截器的生命周期与工作过程?
1)每个拦截器都是实现了Interceptor接口的 Java 类;
2)init(): 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只
被调用一次. 可以在该方法中对相关资源进行必要的初始化;
3)intercept(ActionInvocation invocation): 每拦截一个动作请求, 该方法就
会被调用一次;
4)destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也
只被调用一次;
5)struts2中有内置了18个拦截器。
二十一、struts2如何完成文件的上传?
1、JSP页面:
1)JSP页面的上传文件的组件:<s: file name=”upload” />,如果需要一次上
传多个文件, 就必须使用多个 file 标签, 但它们的名字必须是相同的,即:
name=“xxx”的值必须一样;
2)必须把表单的enctype属性设置为:multipart/form-data;
3)表单的方法必须为post,因为post提交的数据在消息体中,而无大小限制。
2、对应的action:
1)在 Action 中新添加 3 个和文件上传相关的属性;
2)如果是上传单个文件, uploadImage属性的类型就是 java.io.File, 它代表被
上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文件的文
件名和文件类型,定义方式是分别是:
jsp页面file组件的名称+ContentType, jsp页面file组件的名称+FileName
3)如果上上传多个文件, 可以使用数组或 List
二十二、struts的工作原理
1、初始化,读取struts-config.xml、web.xml等配置文件(所有配置文件的初始
化)
2、发送HTTP请求,客户端发送以.do结尾的请求
3、填充FormBean(实例化、复位、填充数据、校验、保存)
4、将请求转发到Action(调用Action的execute()方法)
5、处理业务(可以调用后台类,返回ActionForward对象)
6、返回目标响应对象(从Action返回到ActionServlet)
7、转换Http请求到目标响应对象(查找响应,根据返回的Forward keyword)
8、Http响应,返回到Jsp页面
二十三、Struts2框架在三层架构中哪部分进行的再优化?
表现层进行的再优化。
三层架构:
表现层 MVC
业务层 service
持久层 dao(data access object)
二十四、Struts1和Struts2的一个显著区别是什么?
Struts1的核心控制器是一个servlet。
Struts2的核心控制器是一个过滤器。
二十五、Struts2的编写步骤?
1.导入相关jar包
2.配置web.xml中的过滤器
3.编写struts.xml
4.开发action。
二十六、Struts2的执行过程?
tomcat启动的时候加载应用的web.xml,实例化并初始化过滤器,过滤器的初始化
方法加载struts.xml。客户端发送请求,请求到达过滤器,截取请求的动作名称
(没有或以action结尾),并从struts.xml中找,找到后,实例化动作类。调用
对应的动作方法,方法有返回值,根据返回值,找到name取值对应的结果视图,
找到jsp页面。
二十七、Struts2的配置文件加载时机和加载顺序?
当应用被tomcat加载的时候,struts2的配置文件就已经被加载过了。加载顺序:
default.properties、struts-default.xml、struts-plugin.xml、struts.xml、
web.xml
二十八、常量中struts.devMode是什么意思,如何配置?
开发模式。修改了struts.xml中的配置,你不必每次都重启服务器。
<constant name="struts.devMode" value="true" />
二十九、struts.xml配置文件中package的四个属性分别什么意思?
name:包名
extends:一般是继承struts-default包,但不是必须的。不过如果不继承的话,
将无法使用struts2提供的核心功能。
abstract:把包声明为抽象包,抽象包就是用来被继承的。只要是没有<action>
元素的包,就可以声明为抽象包。
namespace:名称空间。
三十、访问带有名称空间的动作时,是如何查找的? /user/abc/action1.action
先找user/abc,有action1就执行,没有再找user下面的action1,有就执行,最
后找根目录。
三十一、action元素的三个属性什么意思
name:动作名称
class:动作类全名。默认的动作类是:
com.opensymphony.xwork2.ActionSupport是在struts-default.xml中定义的。
method:动作类中的方法名称。默认是public String execute(){}
要求:
1.public的
2.返回值必须是String
3.没有参数
三十二、result元素的两个属性分别指的是什么?
name:逻辑视图的名称,对应着动作方法的返回值。默认值是success。
type:结果类型,指的就是用什么方式转到定义的页面。默认是dispatcher。
三十三、4个常用结果类型分别是什么?
dispatcher:(默认值)使用请求转发,转向一个页面。
redirect:使用重定向,转向一个页面。
redirectAction:注意:使用的是重定向。
a.重定向到另一个相同名称空间的动作。b.重定向到不同名称空间的动作
chain:注意:使用的是请求转发。
a.转发到另一个相同名称空间的动作。b.请求转发到不同名称空间的动作
三十四、访问ServletAPI的两种方式?
第一种方式:使用ServletActionContext类
第二种方式:使用实现接口的方式(ServletRequestAware、
ServletResponseAware)
三十五、如何封装静态请求参数?
在struts.xml配置文件中,给动作类注入值。调用的是setter方法。
三十六、动作类和模型分开的动态封装请求参数,set和get方法是怎么调用的?
先get出来,判断存不存在,存在直接get第二次(给这个对象赋值),不存在(
把这个对象创建出来,set回去,然后再get出来)
三十七、使用模型驱动动态封装请求参数的要求是什么?
实现ModelDriven接口,动作类和实体模型分开,创建模型对象并将其实例化,重
写getModel方法,返回一个引用。
三十八、实际开发中类型转换的两种情况是什么?
转字符串,转其他类型。
写的时候,发送请求,经过过滤器,最后到数据库,字符串转其他类型。
读的时候,到页面,其他类型转成字符串
三十九、Struts2中提供的常用类型转换分几类?
a.基本数据类型自动转换。
b.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)。
c.字符串数组:默认用逗号+空格,连接成一个字符串
四十、自定义类型转换器是如何注册的?(两种情况)
局部类型转换器:只能指定javabean中的属性用
按照属性来注册。在属性所属的javabean的包下建立一个.properties文件。文件
名称:javabean名称-conversion.properties
全局类型转换器:(推荐)
按照要转换的数据类型来注册。at the top op classpath,建立一个固定名称
xwork-conversion.properties的属性文件。
四十一、如何解决编程式验证动作类中的全部动作方法都验证?
在动作类中覆盖public void validate()方法。
四十二、声明式验证的分别可以基于什么?
基于字段和验证器。
四十三、命名声明式验证xml文件名的两种方式,有什么不同?
a.针对动作类中的所有动作进行验证:在动作类所在的包中,建立一个
ActionClassName-validation.xml的文件
b、针对动作类中的某个动作进行验证:在动作类所在的包中建立一个xml文件,
名称为ActionClassName-ActionName-validation.xml。
四十四、国际化的消息资源文件如何命名?
一个资源包由多个文件组成,这些文件名都有命名规范:主要文件名_语言代码_
国家代码.properties。
语言代码:由iso规定的。国家代码:有iso规定的当文件只有主要文件
名.properties时,表明它是默认资源包。浏览器会根据不同的语言环境找对应语
言环境的资源包,当没有时,找默认的。
每个资源包的内容都由相同的key和对应语言环境的value组成。
比如:
message_zh_CN.properties message_zh_HK.properties
message_en_US.properties
四十五、 Struts2中全局,动作范围和包范围,哪个加载优先级高?页面上如何
读取指定的消息资源包?
动作范围。
四十六、Struts2中拦截器的执行时机?
拦截动作方法之前,正序执行;拦截动作方法之后,倒序执行。
四十七、自定义拦截器的步骤是什么?
a、编写一个类,继承AbstractInterceptor类或者实现Interceptor接口。重写
intercept方法。
b、配置拦截器:注意拦截器必须先声明再使用
四十八、多个拦截器如何确定执行顺序?
使用顺序。
四十九、自定义拦截器除了继承AbstractInterceptor还可以继承哪个?另一个有
什么好处?
可以继承MethodFilterInterceptor并且重写doIntercept方法。
通过参数注入的方式,哪个拦截和不拦截。
五十、文件上传是哪个拦截器为我们做的?如何限定上传文件的大小和类型?
fileupload拦截器
在struts.xml中改变default.properties文件中的常量。
给fileUpload拦截器注入参,数通过限制上传文件的MIME类型
五十一、struts2中文件下载是由哪个结果类型完成的?需要我们提供什么参数?
stream类型。输入流的字段名称(inputname)、文件类型(contentType)、响
应消息头(contentDisposition)
五十二、OGNL是什么?使用它能否访问普通方法?能否直接访问静态方法?
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是
一个单独的开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
可以直接访问普通方法。不能直接访问静态方法。需要在struts.xml中启用。
五十三、ActionContext和ValueStack什么时候创建?是否是线程安全的?
明确:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的
。与Struts1的区别是,struts1的动作类是单例的。
在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个
ActionContext和ValueStack对象。且每次动作访问都会创建。
这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部
变量(ThreadLocal)上了。所以是线程安全的。
五十四、ContextMap中的结构是什么样的?
除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又
封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结
构)
***********************************************************************