Struts2.1笔记

Struts2.1
官方文档:
1.	set标签处value的String改为object
2.	struts2标签的type为String表示字符串,为Object表示Ognl表达式
一:Myeclipse的简单操作
1.	将类进行源码展示:
右击Jar包->Properties->Java Source Attachment->
F:/JAR_Total/Struts/struts2.x/struts-2.1.8.1/src/core/src/main/java
2.	文档的展示:
右击Jar包->Properties->JavaDoc Loction->
file:/F:/JAR_Total/Struts/struts2.x/struts-2.1.8.1/docs/struts2-core/apidocs/
之后出现新类的时候直接按F1就可以在Myeclipse中查看文档
3.	Struts.xml不自动提示
a)	window – preferences – 搜索 catalog  
b)	选择key type为URI
c)	key: http://struts.apache.org/dtds/struts-2.0.dtd
d)	location: 对应的dtd文件,位于struts-core包中,解压开,指定相应位置,如:D:\share\0750_Struts2.1.6\soft\struts-2.1.6\lib\struts2-core-2.1.6\struts-2.0.dtd
4.	右击项目->java->compliance->compiler compliance level->1.6
5.	常量的配置保存在struts2-core-2.1.8.1.jar->org.apache.struts2->default.properties
6.	<constant name="struts.devMode" value="true" />:此时表示正处于开发模式,可以不用重新启动服务器而直接访问修改后的内容
一.1:Struts2流程
Struts2多实例,多线程
Servlet单实例,多线程

 

二:NameSpace

a)	namespace决定了action 的访问路径,默认为“”,可以接收所有路径的action,例如
http://localhost:8080/Test/asdfasdfas/sdgsdg/sdfsdfsd/index.action
b)	当将现有的项目拷贝出来一份以后,一定要记得,右击项目->Properties->Myeclipse->Web,将Web Context-root修改掉。
三:Action

a)	 具体视图的返回可以由用户自己定义的Action来决定
b)	 具体的手段是根据返回的字符串找到对应的配置项,来决定试图的内容
c)	 具体Action的实现可以是一个普通的Java类,里面有public String              execute()方法即可
d)	修改默认编码:windows->preference->JSP
e)	Struts2的Action在每次访问时必定会new一个,而Struts1的Action在每次访问的时候可能只有new了一个
f)	实现Action的三种方法:
1.	直接写类名称+execute()方法
2.	继承自ActionSupport类+execute()方法
3.	实现自Action接口+execute()方法
四:Path_路径问题
a)	Struts2中的路径问题是根据Action的路径而不是Jsp的路径来确定,所以尽量不要使用相对路径<br>虽然可以用Redirect方式解决,但是Redirect方式并非必要的。<br>解决方法非常简单,统一使用绝对路径(在Jsp中使用request.getContextRoot方式来拿到webapp的路径,或者使用Myeclipse自己写的) 



五:ActionMethod
1.	Action执行的时候不一定要执行execute方法,可以在配置文件中配置Action的时候用method=来制定执行哪个方法 ,也可以在在url地址中动态制定(动态方法调用DMI),还可以使用通配符来进行操作
(user是命名空间,userAdd是Actino的名称)
http://localhost:8080/Struts2_0400_Path_ActionMethod/user/userAdd
(action!method.action,user是Action的名称,userAdd是方法名)
http://localhost:8080/Struts2_0400_Path_ActionMethod/user!userAdd

六:ActionWildcard(通配符)
	使用通配符,将配置降到最低,不过,一定要遵循“约定优于配置”原则
        <action name="*_*" class="com.bjsxt.struts2.action.{1}Action">
            <result>/{1}_{2}_success.jsp</result>
        </action>

七:接收参数的方式

用Action的属性接收参数
<a href="<%=basePath%>user/user!add?name=lp&age=20">用Action的参数接收属性</a>

	private String nameString;
	private int age;
	public void setName(String name){(name的名称与参数名称一致就行了)
		this.nameString = name;
	}
用DomainModel接收参数(SSI框架中可以省去user.name中的user)
private User user;(加入setter()和getter()方法)
		public String show(){
		//User user = getUser();
		System.out.println("取得名称:"+ user.getName());
		System.out.println("取得年龄:"+ user.getAge());
		return "show";
	}

<a href="user/user!show?user.name=a&user.age=8">添加用户</a>
用ModelDriven接收参数(SSI中继承自BaseActionSupport使用此种方法)
<a href="user/user!add?name=a&age=8">添加用户</a>

//实现ModelDriven接口(记住使用泛型,否则需要类型强制转换)
public class UserAction extends ActionSupport implements ModelDriven<User>{
	
		//此处必须实例化对象,而不是使用setter和getter方法
	private User user = new User();

		@Override
		public User getModel() {
	    	return user;
	}

		public String show(){
		User model = getModel();
		System.out.println("取得名称:"+model.getName());
		System.out.println("取得年龄:"+model.getAge());
		return "show";
	}

八:简单数据验证 

简单数据验证1

Action
		if(name == null || !name.equals("admin")){
			this.addFieldError("name", "name is error");
			return ERROR;
		}
JSP,
		<s:fielderror fieldName="name" theme="simple"/>
			<br />
		<s:property value="errors.name[0]"/> 专门取得valueStack和Stack中的Context中的值
		<s:debug></s:debug>

Value Stack Contents

Object	Property Name	Property Value
com.model.Test	name	刘鹏
	age	20
com.demo.TestAction	texts	null
	model	com.model.Test@59c8b5
	actionErrors	[]
	errors	{name=[name is error!]}
	fieldErrors	{name=[name is error!]}
	errorMessages	[]
	locale	zh_CN
	actionMessages	[]
com.opensymphony.xwork2.DefaultTextProvider	texts	null

九:访问web元素(详见另外一份文档)

十:模块包含(IncludeModlus)
	Struts.xml:
		<struts>
			<include file=”login.xml”>
		</struts>
	Login.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>
    <package name="login" extends="struts-default" namespace="/login"> 
        <action name="login" class="com.bjsxt.struts2.user.action.LoginAction">
            <result>/user_login_success.jsp</result>
        </action>
    </package>
</struts>

十一:默认Action
	<struts>
    <package name="default" extends="struts-default" namespace="/"> 
        <default-action-ref name="index"></default-action-ref>
<action name="index" class="com.bjsxt.struts2.user.action.LoginAction">
            <result>/user_login_success.jsp</result>
        </action>
    </package>
    </struts>

十二:默认Result_Type
1.	Dispatcher   //显示action地址
2.	Redirect     //显示jsp地址
3.	Chain        
4.	redirectAction  
5.	freemarker
6.	httpheader
7.	stream
8.	velocity
9.	xslt
10.	plaintext
11.	tils
<struts>
<package name="resultTypes" extends="struts-default" namespace="/r"> 

 <action name="r1" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 服务器端跳转,不能跳转到Action,只能跳转到试图 -->
<result type="dispatcher">/user_login_success.jsp</result>
</action>

<action name="r2" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 客户端跳转,不能跳转到Action,只能跳转到试图 -->
<result type="redirect">/user_login_success.jsp</result>
</action>
    
<action name="r3" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 使用forward(服务器端跳转)的方式访问Action -->
<result type="chain">
	<param name="actionName">a</param>
	<param name="namespace">/a</param>
</result><!-- aaa/r1 -->
</action>

<action name="r4" class="com.bjsxt.struts2.user.action.LoginAction">
<!-- 客户端跳转,跳转到Action  -->
<result type="redirectAction">r2</result>
</action>

</package>
 </struts>

十三: Global_Results(全局结果集)
可以用于全局错误页的配置等等需要统一使用的模块
Struts.XML代码:
<package name="user" extends="struts-default" namespace="/user">
		<global-results>
			<result name="mainpage">/main.jsp</result>
		</global-results>
<action name="user" class="com.action.UserAction">
		<result name="success">/ success.jsp</result>
		<result name="error">/error.jsp</result>
	</action>
</package>

	<!-- 为在其他包中任然可以使用此结果集,继承自那个包 -->
<package name="admin" namespace="/admin" extends="user">
	<action name="admin" class="com.action.AdminAction">
		<result>/admin.jsp</result>
	</action>
</package>

UserAction代码:
	public String execute(){
		if(type==1){
			return SUCCESS;	
		}else if(type==2){
			return ERROR;
		}else {
			return "mainpage";
		}
		
	}
AdminAction代码:
	public String admin(){
		return "mainpage";
	}
十四: Dynamic_Results(动态结果集)
Action代码:

	private int type;(setter()和getter())
	private String r; (setter()和getter())

	public String execute() throws Exception {
		if(type == 1)  r="/user_success.jsp";
		else if (type == 2) r="/user_error.jsp";
		return "success";
	}
XML代码:
	  <package name="default" namespace="/" extends="struts-default">
		<action name="test" class="com.demo.TestAction">
			<result>${r}</result>
<!--由于r是action的属性,存在valuestack中,所以${r}可以取得到-->
		</action>
	</package>
十五:带参数的结果集(客户端跳转时候才用到)
XML代码:		
	<package name="default" namespace="/" extends="struts-default">
		<action name="test" class="com.demo.TestAction">
			<result type="redirect">/success.jsp?t=${type}</result>
		</action>
	</package>	<!-- 原本过程所有Action公用一个值栈(一次request只有一个值栈,服务器端forward共享一个值栈),可以直接访问type属性,现在进行客户端跳转,不共享同一个值栈了,不可以再访问到type属性,所以使用以上方式进行参数的传递 -->
		
Action代码:
private int type;(setter()和getter())
public String test(){
		return SUCCESS;
	}
JSP代码:
    <!-- s:property是从值栈中取值,XML中客户端重新发了一次请求给JSP,但是此时值栈中已经为null了,故而取不到 -->
    from valueStack:<s:property value="t"/><br> 取不出来
from actionContext:<s:property value="#parameters.t"/> 取得出来
访问地址:
http://localhost:8080/.../...?type=1

十六:OGNL(Object Graph Navigation Language对象图导航语言)
OGNL1(访问普通属性)(value stack直接取值,stack Context使用#取值)
Xml代码:
	<package name="ognl" extends="struts-default">
		<action name="ognl" class="com.lp.OgnlAction">
			<result name="success">/ognl.jsp</result>
		</action>
	</package>
Model代码:
	private String age = "";(setter()/getter())
Action代码:
	private Test test;
<!—初始化model可以自己new;也可以传参数,但此时model需要存在空构造方法 -->
<!-- 使用domainModel时候只有传入类似test.age才能将实体类实例化 -->
	private String username = "";
private String password = ""; (setter()/getter())
	public String execute(){
		HttpServletRequest request = ServletActionContext.getRequest();
		request.setAttribute("name", "liupeng");
		return SUCCESS;
	}
JSP代码:
访问值栈中action的普通属性:username=<s:property value="username"/><br>
访问值栈中model的普通属性(getter/setter):<s:property value="test.age"/>
								        <s:property value="test[‘age’]"/>
   <s:property value="test[\”age\”]"/>
<s:debug></s:debug>
访问属性范围中的普通属性:<s:property value="#request.name"/>
访问:
http://localhost:8080/OGNL/ognl!execute?username=liupeng&password=1111&test.age=10
OGNL2(访问普通属性)
Action代码:
	private Cat cat;(setter/getter)
Model代码:
	Cat.java:
		private Dog friend;(setter/getter)
	Dog.java:
		public Dog(){
		}
		private String name = "";(setter/getter)
JSP代码:
  访问值栈中model的普通属性:<s:property value="cat.friend.name"/>
访问:
http://localhost:8080/OGNL/ognl!execute?username=liupeng&password=1111&test.age=10&cat.friend.name=wanghan
OGNL3(访问普通方法)
Action代码:
	private String password = "";(set/get)
	public String m(){
		return "hello";	
	}
JSP代码:
访问值栈中action属性的普通方法:<s:property value="password.length()"/>
    	访问值栈中model的普通方法:<s:property value="cat.miaomiao()"/>
	访问值栈中action的普通方法:<s:property value="m()"/>
访问:
http://localhost:8080/OGNL/ognl!execute?password=1111
OGNL4(访问静态属性和方法)
Struts2.x访问静态属性和方法需要在XML文件中加上<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
Action代码:
	public static String STR = "static string";
	public static String s(){
		return "static method";
	}
JSP代码:
    	访问静态方法:<s:property value="@com.lp.OgnlAction@s()"/><br>
    	访问静态属性:<s:property value="@com.lp.OgnlAction@STR"/><br>
    	访问Math类的静态方法:<s:property value="@@math(2,3)"/> 
<!-- 两个@只能访问一个类的静态方法 -->
OGNL4(访问普通类的构造方法)
JSP代码:
访问普通类的构造方法:<s:property value="new com.model.Test(8)"/>
OGNL4(访问集合)
Action代码:
    注意集合作为了Action的属性存在
	private List<Test> tests = new ArrayList<Test>();
	private Set<Dog> dogs = new HashSet<Dog>();
	private Map<String, Dog> dogMap = new HashMap<String, Dog>();
	加入setter和getter方法
public OgnlAction(){
		tests.add(new Test(1));
		tests.add(new Test(2));
		tests.add(new Test(3));
		
		dogs.add(new Dog("dog1"));
		dogs.add(new Dog("dog2"));
		dogs.add(new Dog("dog3"));
		
		dogMap.put("dog100", new Dog("dog100"));
		dogMap.put("dog101", new Dog("dog101"));
		dogMap.put("dog102", new Dog("dog102"));
	}
JSP代码:
    	访问List:<s:property value="tests"/><br>
    	访问List中某个元素:<s:property value="tests[0]"/><br>
    	访问List中元素某个属性的集合<s:property value="tests.{age}"/>
    访问List中元素某个属性的集合中的特定值:<s:propertyvalue="tests[0].age"/>
<s:property value="tests.{age}[0]"/>
    
	访问Set:<s:property value="dogs"/><br>
    	访问Set中某个元素:<s:property value="dogs[1]"/><br>
    	<!-- set以上是访问不到的,因为set是无序的 -->
访问Map:<s:property value="dogMap"/>
    	访问Map中某个元素:<s:property value="dogMap.dog101"/>
					  <s:property value="dogMap['dog101']"/>
<s:property value="dogMap[\"dog101\"]"/>
    	访问Map中所有的key:<s:property value="dogMap.keys"/>
    	访问Map中所有的value:<s:property value="dogMap.values"/>
    	访问容器的大小:<s:property value="dogMap.size()"/>
OGNL4(投影)
投影或者说过滤的是集合中的属性
Action代码:
    注意集合作为了Action的属性存在
	private List<Test> tests = new ArrayList<Test>();
	加入setter和getter方法
public OgnlAction(){
		tests.add(new Test(1));
		tests.add(new Test(2));
		tests.add(new Test(3));
	}

JSP代码:
    	投影(过滤):<s:property value="tests.{?#this.age==1}.{age}"/><br>
    	投影:<s:property value="tests.{^#this.age>1}.{age}"/><br>
    	投影:<s:property value="tests.{$#this.age>1}.{age}"/><br>
    	投影:<s:property value="tests.{$#this.age>1}.{age}==null"/>
    	<!-- ^代表开头,$代表结尾,?代表过滤条件,this表示循环过程中tests对象 -->
OGNL5( 用[]访问元素)
    	[]:<s:property value="[0] "/>
<s:property value="[0].username "/>
    	<!-- 访问的是valueStack的从上往下的某个元素 -->
十七:Struts标签
1.	通用标签
a)	property
Action代码:
	private String username ;
	private String password;(set/get)
	public String execute(){
		this.addFieldError("fielderror.test", "wrong");
		return SUCCESS;
	}
JSP代码:

   property:<s:property value="username"/><br>
<!—上面username为Ognl表达式-->
   property取值为字符串:<s:property value="'username'"/><br>
property设定默认值:<s:property value="admin" default="管理员"/><br>
property设定HTML:<s:property value="'<hr/>'" escape="false"/><br>
<!-- escape=true表示不解析html;反之表示解析html -->
b)	set
I.	默认为action scope,会将值放入request和ActionConrtext中
II.	page、request、session、application
JSP代码:
    set设定adminName值(默认为request和ActionContext):<s:set var="adminName" value="username"></s:set>
    set从request取值:<s:property value="#request.adminName"/>
    set从ActionContext取值:<s:property value="#adminName"/>
    set设定范围:<s:set name="adminPassword" value="password" scope="page"></s:set>
    set从相应范围值:<%=pageContext.getAttribute("adminPassword") %><br>
    set设定var,范围为ActionContext:<s:set var="a" value="password"></s:set>
set使用#取值:<s:property value="#a"/>
访问:
http://localhost:8080/Struts-tags/tags/tags?username=liupeng&password=1111
c)	bean
 bean:<s:bean name="com.model.Tags" var="mytag">
 		   	<s:param name="userName" value="'liupeng'"></s:param>
 </s:bean>
 <!-- var要写才能在debug中看到;
    				 param的name应该写Tags的属性,value默认当成Ognl表达式处理
 		 	 -->
读取:<s:property value="#mytag.userName"/>
<!-- 如果不写var,bean标签会在执行过程中生成一个model对象放到栈顶,但在执行结束后又会消失,使用var就会将值放入ActionContext中,在其他地方也可以使用#访问 -->
   
d)	include
   	<s:set var="incPage" value="'/_include.html'"></s:set>
   	<s:include value="%{#incPage}"></s:include>
<!-- value为String类型,使用%{}将其视为Ognl表达式处理 -->
e)	param
在bean标签处体现
f)	debug
  <s:debug></s:debug>
2.	控制标签
a)	if elseif else
JSP代码:

	if elseif else:<br>
age:<s:property value="#parameters.age[0]"/><br>
 <!-- paramaters参数的集合,哪怕只有一个age,也需要精确的定位 -->
    <s:if test="parameters.age[0]<0">wrong age!</s:if><br>
<s:elseif test="#parameters.age[0]<30">tooyoung!</s:elseif><br>
<s:else>yeah!</s:else>
访问:
http://localhost:8080/Struts-tags/tags/tags? age=20
b)	iterator
JSP代码:
 遍历集合1:<br>
    	<s:iterator value="{1,2,3}">
    		<s:property/>|
    		<!-- {1,2,3会当成集合,property遍历输出} -->
</s:iterator>

遍历集合2:
<s:iterator value="#request.weiboList"  var="user">
<s:property value="#user.getId()"/>

自定义变量:<br>
    	<s:iterator value="{'aaa','bbb','ccc'}" var="x">
    		<s:property value="#x.toUpperCase()"/>
 </s:iterator>

带有status的遍历:
    	<s:iterator value="{'aaa','bbb','ccc'}" status="status">
    		<s:property/>|
    		遍历过的元素总数:<s:property value="#status.count"/>|
    		遍历过的元素索引:<s:property value="#status.index"/>|
    		当前访问的个数是偶数:<s:property value="#status.even"/>|
    		当前访问的个数是奇数:<s:property value="#status.odd"/>|
    		是first?<s:property value="#status.first"/>|
    		是last?<s:property value="#status.last"/><br>
 </s:iterator>

 遍历Map集合:<br>
    	<s:iterator value="#{1:'a',2:'b',3:'c'}">
    		<s:property value="key"/>|<s:property value="value"/>
    	</s:iterator>
    	<s:iterator value="#{1:'a',2:'b',3:'c'}" var="x">
    		<s:property value="#x.key"/>|<s:property value="#x.value"/>
 </s:iterator>
c)	subset
3.	UI标签
a)	theme(simple/xhtml(默认)/css_xhtml/ajax)
Xml代码:
	<constant name="struts.ui.theme" value="simple"></constant>
	<package name="theme" namespace="/" extends="struts-default">
		<action name="theme" class="com.action.ThemeAction">
			<result name="success">/theme.jsp</result>
		</action>
	</package>
	JSP代码:
在struts.xml中控制theme,默认为xhtml,可以设置为:simple/css_html/ajax<br>
<s:form>
    	<div class="formFieldError">
    		<s:fielderror></s:fielderror>
    	</div>
    	<s:textfield name="aaa"></s:textfield>
</s:form>

<style type="text/css">
.formFieldError ul{
		list-style-type:none
}
.formFieldError ul li{
		list-style-type:none
}
</style>
4.AJAX标签
5.$#%的区别
$用于i18n和struts配置文件
#取得ActionContext值
%{}将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用

十七:常用常量
<!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 -->
    <constant name="struts.i18n.encoding" value="UTF-8"/>
    <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理。
    如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开。 -->
    <constant name="struts.action.extension" value="do"/>
    <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
    <constant name="struts.serve.static.browserCache" value="false"/>
    <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
    <constant name="struts.configuration.xml.reload" value="true"/>
    <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
    <constant name="struts.devMode" value="true" />
     <!-- 默认的视图主题 -->
    <constant name="struts.ui.theme" value="simple" />
    <!– 与spring集成时,指定由spring负责action对象的创建 -->
    <constant name="struts.objectFactory" value="spring" />
 <!–该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false。 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
 <!--上传文件的大小限制-->
<constant name="struts.multipart.maxSize" value=“10701096"/>

十八:自定义类型转换器
HelloWordAction.Java
public class HelloWordAction {
	private Date createtime;

	public Date getCreatetime() {
		return createtime;
	}

	public void setCreatetime(Date createtime) {
		this.createtime = createtime;
	}
	
	public String execute(){
		
		System.out.println(createtime);
		return "success";
	}

}
MyDateCVT.Java
public class MyDateCVT extends DefaultTypeConverter{
	@Override  public Object convertValue(Map context, Object value, Class toType) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy|MM|dd");
		try { 
			if(toType == Date.class){//当字符串向Date类型转换时
				String[] params = (String[]) value;// Request.getParameterValues() 
				return dateFormat.parse(params[0]);
			}else if(toType == String.class){//当Date转换成字符串时
				Date date = (Date) value;
				return dateFormat.format(date);
			}
		} catch (ParseException e) {} catch (java.text.ParseException e) {
			e.printStackTrace();
		}
		return null;
		}

}
访问
http://localhost:8080/servlet/hello?createtime=2013|11|11

十八:自定义全局类型转换器
将上面的类型转换器注册为全局类型转换器:
在WEB-INF/classes下放置xwork-conversion.properties文件 。在properties文件中的内容为:
待转换的类型=类型转换器的全类名
对于本例而言, xwork-conversion.properties文件中的内容为:
java.util.Date= cn.itcast.conversion.DateConverter

十九:自定义拦截器
Action:
package com.filter;
import java.sql.Timestamp;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class LogIC implements Interceptor{

	public void destroy() {
	}
	public void init() {
	}

	public String intercept(ActionInvocation invocation) throws Exception {
		String actionName = invocation.getAction().getClass().getName();
		//入口
		System.out.println("Action execute start at"+new Timestamp(System.currentTimeMillis()));
		String result = invocation.invoke(); //保证拦截器往下执行
		//出口
		return result;
	}

}
XML:
	 <package name="hello" namespace="/" extends="struts-default">
     <interceptors>
 	         <interceptor name="LogIC" class="com.filter.LogIC" />
 	         <interceptor-stack name="LogStack">
 		 	 <interceptor-ref name="defaultStack" />
 		     <interceptor-ref name="LogIC" />
 	    </interceptor-stack>
 	</interceptors>
 	
	<action name="hello" class="com.test.HelloAction" method="execute">
		<result name="success">/hello.jsp</result>
		<interceptor-ref name="LogStack"/>
		<!--  <default-interceptor-ref name="LogStack"/> 默认的拦截器配置-->
	</action> 
</package>
因为struts2中如文件上传,数据验证,封装请求参数到action等功能都是由系统默认的defaultStack中的拦截器实现的,所以我们定义的拦截器需要引用系统默认的defaultStack,这样应用才可以使用struts2框架提供的众多功能。
如果希望包下的所有action都使用自定义的拦截器,可以通过<default-interceptor-ref name=“permissionStack”/>把拦截器定义为默认拦截器。注意:每个包只能指定一个默认拦截器。另外,一旦我们为该包中的某个action显式指定了某个拦截器,则默认拦截器不会起作用

或者使用如下方式:
	 <package name="hello" abstract="true" extends="struts-default">
     <interceptors>
 	         <interceptor name="LogIC" class="com.filter.LogIC" />
 	         <interceptor-stack name="LogStack">
 		 	 <interceptor-ref name="defaultStack" />
 		     <interceptor-ref name="LogIC" />
 	    </interceptor-stack>
 	</interceptors>
    </package>
    
    <package name="helloTwo"  extends="hello">
    	<action name="hello" class="com.test.HelloAction" method="execute">
			<result name="success">/hello.jsp</result>
		</action> 
     </package>
二十:文件或图片上传
1.	前台:  
2.	      <struts:form action="weiboAction!uploadPicture.shtml" enctype="multipart/form-data" namespace="/" method="post">  
3.	        <struts:file name="image" label="文件"></struts:file>  
4.	        <struts:submit value="上传"/>  
5.	    </struts:form>  
6.	  
7.	  
8.	后台:  
9.	    /** 
10.	     * 作者:刘鹏 
11.	     * 时间:2013-07-07 
12.	     * 描述:微博列表中的图片和文件上传显示 
13.	     * @return 
14.	     */  
15.	      
16.	/*****************以下为上传部分*******************************/  
17.	    private File image;                        //得到上传的文件  
18.	    private String imageFileName;              //得到文件的名称,写法是固定的  
19.	    private String imageContentType;           //得到文件的类型  
20.	  
21.	    public String getImageContentType() {  
22.	        return imageContentType;  
23.	    }  
24.	    public void setImageContentType(String imageContentType) {  
25.	        this.imageContentType = imageContentType;  
26.	    }  
27.	    public String getImageFileName() {  
28.	        return imageFileName;  
29.	    }  
30.	    public void setImageFileName(String imageFileName) {  
31.	        this.imageFileName = imageFileName;  
32.	    }  
33.	    public File getImage() {  
34.	        return image;  
35.	    }   
36.	    public void setImage(File image) {  
37.	        this.image = image;  
38.	    }  
39.	    public String addUI(){  
40.	        return SUCCESS;  
41.	    }  
42.	    public String uploadPicture(){  
43.	        HttpServletRequest request = ServletActionContext.getRequest();  
44.	        //保存到根目录下的Images文件夹下  
45.	                String realPath = ServletActionContext.getServletContext().getRealPath("/uploadOImages");    //取得真实路径  
46.	                System.out.println(realPath);  
47.	                System.out.println(imageFileName);  
48.	                System.out.println(imageContentType);  
49.	                  
50.	                //自动命名  
51.	                Random random = new Random(99999);  
52.	                int tempInt = random.nextInt();  
53.	                Date date = new Date();  
54.	                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");  
55.	                int last = imageFileName.lastIndexOf(".");  
56.	                String head = imageFileName.substring(0,last);  
57.	                String type = imageFileName.substring(last);  
58.	                imageFileName = simpleDateFormat.format(date) + tempInt + type;  
59.	                System.out.println("新的文件名称是:"+imageFileName);  
60.	                  
61.	                //创建父文件夹  
62.	                if(image!=null){  
63.	                File saveFile = new File(new File(realPath), imageFileName);  
64.	                if(!saveFile.getParentFile().exists()){     //如果Images文件夹不存在  
65.	                    saveFile.getParentFile().mkdirs();  //则创建新的多级文件夹  
66.	                      
67.	                }  
68.	                try {  
69.	                    FileUtils.copyFile(image, saveFile);     //保存文件  
70.	                    ActionContext.getContext().put("message", "上传成功!");  
71.	                    request.setAttribute("uploadsuccess", imageFileName);  
72.	                } catch (IOException e) {  
73.	                      
74.	                    e.printStackTrace();  
75.	                }  
76.	                }  
77.	                return "upload";  
78.	            }  
79.	      
80.	      
81.	/*****************以上为上传部分*******************************/  
82.	  
83.	后台将图片的地址保存到数据库中  
84.	    //先从数据库中将所有数据读出来,放入到request中  
85.	    request.setAttribute("weibotest", list);  
86.	  
87.	前台使用OGNL语言读取出图片地址,并且显示图片  
88.	    <s:iterator value="#request.weibotest" var="user">  
89.	        <s:property value="#user.getContent()"/>  
90.	        <img src ='<s:property value ="#user.getImage()" />' width="200">     //显示图片  
91.	    </s:iterator>  
二十一:多文件上传
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。这两个文件可以从http://commons.apache.org/下载。
第二步:把form表的enctype设置为:“multipart/form-data“,如下:
<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/xxx.action" method="post">
  <input  type="file" name="uploadImages">
  <input  type="file" name="uploadImages">
</form>
第三步:在Action类中添加以下属性,属性红色部分对应于表单中文件字段的名称:
public class HelloWorldAction{
  private File[] uploadImages;//得到上传的文件
  private String[] uploadImagesContentType;//得到文件的类型
  private String[] uploadImagesFileName;//得到文件的名称
  //这里略省了属性的getter/setter方法
  public String upload() throws Exception{
	String realpath = ServletActionContext.getServletContext().getRealPath("/images");
	File file = new File(realpath);
	if(!file.exists()) file.mkdirs();
	for(int i=0 ;i<uploadImages.length; i++){ File uploadImage = uploadImages[i];
    FileUtils.copyFile(uploadImage, new File(file, uploadImagesFileName[i]));
}
	return "success";
  }}
二十二:手工编写代码方式实现对Action中所有方法输入校验
通过重写validate() 方法实现, validate()方法会校验action中所有与execute方法签名相同的方法。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。

action:
public class Validate extends ActionSupport{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String execute(){
		return "success";
	}
	
	public void validate() {
	     if(name==null||"".equals(name)){
	    	 this.addFieldError("name", "用户名为空!");
	     }else{
	    	 if(name.length()<2||name.length()>10){
	    		 this.addFieldError("name", "用户名长度有误!");
	    	 }
	     }
	}

}
xml:
	<action name="validate" class="com.test.Validate">
		<result name="input">/index.jsp</result>
		<result name="success">/hello.jsp</result>
	</action>
jsp:
<s:fielderror/>
二十三:手工编写代码方式实现对Action中指定方法输入校验
通过validateXxx()方法实现, validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,struts2会将请求转发到名为input的result。在input视图中可以通过<s:fielderror/>显示失败信息。
action:
	public String add(){
		return "success";
	}
	public void validateAdd(){
        if(name==null||"".equals(name.trim()))  
        	this.addFieldError("name", "用户名不能为空");
}
xml:
	<action name="validate" class="com.test.Validate">
		<result name="input">/index.jsp</result>
		<result name="success">/hello.jsp</result>
	</action>
jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add

二十四:输入校验流程
1。类型转换器对请求参数执行类型转换,并把转换后的值赋给action中的属性。
2。如果在执行类型转换的过程中出现异常,系统会将异常信息保存到ActionContext,conversionError拦截器将异常信息添加到fieldErrors里。不管类型转换是否出现异常,都会进入第3步。
3。系统通过反射技术先调用action中的validateXxx()方法,Xxx为方法名。
4。再调用action中的validate()方法。
5。经过上面4步,如果系统中的fieldErrors存在错误信息(即存放错误信息的集合的size大于0),系统自动将请求转发至名称为input的视图。如果系统中的fieldErrors没有任何错误信息,系统将执行action中的处理方法。
二十五:基于XML配置方式实现对action的所有方法进行输入校验
使用基于XML配置方式实现输入校验时,Action也需要继承ActionSupport,并且提供校验文件,校验文件和action类放在同一个包下,文件的取名格式为:ActionClassName-validation.xml,其中ActionClassName为action的简单类名,-validation为固定写法。如果Action类为cn.itcast.UserAction,那么该文件的取名应为:UserAction-validation.xml。
action:
public class Validate extends ActionSupport{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String execute(){
		return "success";
	}
xml:
Validate-validation.xml:
	<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"> 

<validators>
    <field name="name">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message>用户名不能为空!</message>
        </field-validator>
    </field>
</validators>
struts.xml:同上

jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add

二十六:基于XML配置方式实现对action的制定方法进行输入校验
当校验文件的取名为ActionClassName-validation.xml时,会对 action中的所有处理方法实施输入验证。如果你只需要对action中的某个action方法实施校验,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中action的名称。
action:
public class Validate extends ActionSupport{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String execute(){
		return "success";
	}
	
	public String add(){
		return "success";
	} 
}
xml:
Validate-validate-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.3//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd"> 

<validators>
    <field name="name">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message>用户名不能为空!</message>
        </field-validator>
    </field>
</validators>
struts.xml:
			<action name="validate" class="com.test.Validate">
		<result name="input">/index.jsp</result>
		<result name="success">/hello.jsp</result>
	</action>
jsp:
<s:fielderror/>
访问:
http://localhost:8080/struts/validate!add
二十七:struts2提供的校验器列表
系统提供的校验器如下:
required (必填校验器,要求field的值不能为null)
requiredstring (必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
stringlength(字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
regex(正则表达式校验器,检查被校验的field是否匹配一个正则表达式.expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
fieldexpression(字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
email(邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地址)
url(网址校验器,要求如果field的值非空,则必须是合法的url地址)
date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
conversion(转换校验器,指定在类型转换失败时,提示的错误信息)
visitor(用于校验action中的复合属性,它指定一个校验文件用于校验复合属性中的属性)
expression(OGNL表达式校验器,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过,该校验器不可用在字段校验器风格的配置中)
二十八:校验器的使用例子
required  必填校验器
<field-validator type="required">
       <message>性别不能为空!</message>
</field-validator>
requiredstring  必填字符串校验器
<field-validator type="requiredstring">
       <param name="trim">true</param>
       <message>用户名不能为空!</message>
</field-validator>
stringlength:字符串长度校验器
<field-validator type="stringlength">
	<param name="maxLength">10</param>
	<param name="minLength">2</param>
	<param name="trim">true</param>
	<message><![CDATA[产品名称应在2-10个字符之间]]></message>
</field-validator>

email:邮件地址校验器
<field-validator type="email">
	<message>电子邮件地址无效</message>
</field-validator>
regex:正则表达式校验器
<field-validator type="regex">
     <param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
     <message>手机号格式不正确!</message>
</field-validator>

int:整数校验器
<field-validator type="int">
	<param name="min">1</param>
	<param name="max">150</param>
	<message>年龄必须在1-150之间</message>
</field-validator>
字段OGNL表达式校验器
<field name="imagefile">
	<field-validator type="fieldexpression">
		<param name="expression"><![CDATA[imagefile.length() <= 0]]></param>
		<message>文件不能为空</message>
	</field-validator>
</field>
二十九:基于XML校验的一些特点
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
1。AconClassName-validation.xml
2。ActionClassName-ActionName-validation.xml
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于action方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。
假设UserAction继承BaseAction:
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
</action>
访问上面action,系统先搜索父类的校验文件:BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索子类的校验文件: UserAction-validation.xml, UserAction-user-validation.xml。应用于上面action的校验规则为这四个文件的总和。
三十:国际化
准备资源文件,资源文件的命名格式如下:
baseName_language_country.properties
baseName_language.properties
baseName.properties
其中baseName是资源文件的基本名,我们可以自定义,但language和country必须是java支持的语言和国家。如:
中国大陆: baseName_zh_CN.properties
美国: baseName_en_US.properties
现在为应用添加两个资源文件:
第一个存放中文:itcast_zh_CN.properties
内容为:welcome=欢迎来到传智播客
第二个存放英语(美国): itcast_en_US.properties
内容为: welcome=welcome to itcast
对于中文的属性文件,我们编写好后,应该使用jdk提供的native2ascii命令把文件转换为unicode编码的文件。命令的使用方式如下:
native2ascii  源文件.properties  目标文件.properties
配置全局资源与输出国际化信息
当准备好资源文件之后,我们可以在struts.xml中通过struts.custom.i18n.resources常量把资源文件定义为全局资源文件,如下:
<constant name="struts.custom.i18n.resources" value="itcast" />
itcast为资源文件的基本名。
后面我们就可以在页面或在action中访问国际化信息:
在JSP页面中使用<s:text name=“”/>标签输出国际化信息:
<s:text name=“user”/>,name为资源文件中的key
在Action类中,可以继承ActionSupport,使用getText()方法得到国际化信息,该方法的第一个参数用于指定资源文件中的key。
在表单标签中,通过key属性指定资源文件中的key,如:
<s:textfield name="realname" key="user"/>
国际化—输出带占位符的国际化信息
资源文件中的内容如下:
welcome= {0},欢迎来到传智播客{1}
在jsp页面中输出带占位符的国际化信息
<s:text name="welcome">
  	 <s:param><s:property value="realname"/></s:param>
	<s:param>学习</s:param>
</s:text>
在Action类中获取带占位符的国际化信息,可以使用getText(String key, String[] args)或getText(String aTextName, List args)方法。
国际化—JSP中直接访问某个资源文件
struts2为我们提供了<s:i18n>标签,使用<s:i18n>标签我们可以在类路径下直接从某个资源文件中获取国际化数据,而无需任何配置:
<s:i18n name="itcast">
    <s:text name=“welcome”/>
</s:i18n>
Itcast为类路径下资源文件的基本名。
如果要访问的资源文件在类路径的某个包下,可以这样访问:
<s:i18n name=“cn/itcast/action/package">
  	<s:text name="welcome">
  		<s:param>小张</s:param>
  	</s:text>
</s:i18n>
上面访问cn.itcast.action包下基本名为package的资源文件。

实例:
properties:
csst.properties
	main.company:CSST
main.addr:haidian,Beijing,china
csst_zh_CN.properties
	main.company:中软培训
main.addr:海淀南路,北京,中国
csst_en_US.properties
main.company:&&qq
main.addr:**ss
XML:
<constant name="struts.custom.i18n.resources" value="csst" />
<action name="il8n" class="com.il8n.IL8NAction">
		<result name="success">/IL8N.jsp</result>
	</action>
action:
success
jsp:
    名称:<s:text name="main.company"/><br>
地址:<s:text name="main.addr"/>
访问:
	http://localhost:8080/struts/il8n?request_locale=en_US

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值