struts2马士兵笔记

Struts2 学习笔记

目录


01 Struts2-Action

一、        
Struts作用:

二、        
搭建Struts2的运行环境:

三、        
Namespace

四、        
<package>标签

五、        
Action

六、        
路径问题的说明

七、        
Action的动态调用方法

八、        
Action通配符(wildcard)的配置

九、        
Action的属性接收参数

1、      
在Action添加成员属性接受参数

2、      
域模型(Domain Model)

3、      
ModelDriven接收参数

十、        
Action属性接收参数中文问题

十一、        
简单数据验证

十二、        
访问Web元素

一、        
方法一:ActionContext方式

二、        
方式二:Ioc(控制反转)—推荐使用

三、        
方式三:获取原类型

四、        
方式四:获取原类型-控制反转

十三、        
Struts2配置文件模块化包含(include)

十四、        
默认的Action

十五、        
Action总结

02 Struts2-Result

一、        
Result类型 (type)

二、        
全局结果集(Globle Result)

三、        
动态的结果集(dynamic result)

四、        
带参数的结果集

五、        
Result总结

六、        
项目经理:

03 OGNL表达式语言

04 Struts2-Tags

Struts2标签目录

一、        
property标签

二、        
set标签

三、        
bean标签

四、        
<include>标签-少使用

五、        
If elseif else

六、        
Iterator标签

七、        
Theme

05设计约定(编码规定)

06 项目开发顺序

07 声明式异常处理

08 国际化

一、        
国际化资源文件

二、        
Java国际化

三、        
Struts2国际化

1、      
Action级别

2、      
Package级别

3、      
Application级别

四、        
资源文件中的参数处理

五、        
国际化-动态语言切换

09 自定义拦截器

10 类型转换

Struts2总结


目录

Ø  Action

n  简单数据校验

Ø  Result

Ø  常用配置文件

Ø  OGNL & ValueStack

Ø  Tags

Ø  ---------------------Project

n  类型转换、上传与下载、interceptor、防止重复提交

Ø  MVC思想深入剖析

Ø  源码解读

Ø  其他话题

01 Struts2-Action

一、Struts作用:

将请求与结果分开

二、搭建Struts2的运行环境:

1、建立Web项目;

2、建立Struts2的配置文件(struts.xml);

将Struts2的空项目中的配置文件(struts.xml)复制到项目的src目录下。

配置如下:

<!--

struts.devMode : 是否设置为开发模式 true:是开发模式,否则不是

注:在开发模式下,修改Struts的配置文件后不需要重新启动Tomcat服务器即生效。

  否则修改Struts配置文件后需要重新启动Tomcat服务器才生效。

-->

<constantname="struts.devMode"value="true"/>

<!--

namespace :对应与项目名称后面的"/"(例如Struts2_0100_Introduction后面的"/")

(http://localhost:8080/Struts2_0100_Introduction/)

-->

<packagename="default"namespace="/"extends="struts-default">

<action
name="hello">

<result>

/hello.jsp

</result>

</action>

</package>

3、复制Struts2相应的jar包及第三方包。

将空项目中lib目录中的除junit和spring-test之外的所有文件复制到项目的WebRoot/WEB-INF/lib目录下

4、修改对应的web.xml,建立struts2的filter(参考struts自带的项目),添加如下配置:

<filter>

<filter-name>struts2</filter-name>

<filter-class>

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

三、Namespace

Namespace决定了action的访问路径,默认为“”,可以接收所有路径的action,如果没有找到相应的namespace时,则使用namespace为空的action

Namespace可以写为/,或者/xxx,或者/xxx/yyy,对应的action访问路径为/index.action、/xxx/index.action、或者/xxx/yyy/index.action.

Namespace最好也用模块来进行命名。

namespace :对应与项目名称后面的"/"(例如Struts2_0100_Introduction后面的"/")

(http://localhost:8080/Struts2_0100_Introduction/)

四、<package>标签

<package>是用来解决重名的问题,例如当系统的前台和后台都有一个action名叫hello,这时就需要用package来区分。   前台<package
name="front">后台<package name="back">

struts2中的package与java的package是相同的作用的。

五、Action

具体视图的返回可以由用户自己定义的Action来决定

具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容,有三种手段:

<constantname="struts.devMode"value="true"/>

<packagename="front"extends="struts-default"namespace="/">

<action
name="index"class="com.bjsxt.struts2.front.action.IndexAction1">

<result
name="success">/ActionIntroduction.jsp</result>

</action>

</package>

注:<action>标签中的class属性是表示action的对应的类(这个类是一个普通Java类),当访问这个action时会创建
这个类成为一个对象,然后执行这个对象中的execute方法()(execute方法返回类型为String)。

第一种:Action普通Java类

publicclassIndexAction1 {

public String execute() {

return"success";

}

}

当<action>标签中class属性省略时,则默认执行com.opensymphony.xwork2.ActionSupport类中的execute方法,而这个方法返回一个字符串常量SUCCESS(常量值为:”success”).

第二种:Action实现com.opensymphony.xwork2.Action接口,这个接口中定义了一些常量和一个execute方法,我们重写execute()方法就可以了。

import com.opensymphony.xwork2.Action;

publicclass IndexAction2implements
Action {

@Override

public String execute() {

//return "success";

returnthis.SUCCESS;//SUCCESS常量值为:"success"

}

}

第三种:Action继承com.opensymphony.xwork2.ActionSupport类,而这个类又实现了com.opensymphony.xwork2.Action接口,我们重写execute()方法就可以了。

 

import com.opensymphony.xwork2.ActionSupport;

publicclass IndexAction3extends
ActionSupport {

@Override

public String execute() {

//return "success";

returnthis.SUCCESS;//SUCCESS常量值为:"success"

}

}

注:第三种Action是我们需要使用的方式,因为这个类不担实现了com.opensymphony.xwork2.Action接口,更重要的是它已经帮我封装了许多其它有用的方法。

六、路径问题的说明

struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。

解决办法非常简单,统一使用绝对路径。(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath

还有另一种方式,就是在<head>标签中,指定<base>标签值,这样就使用统一绝对路径。

<%

String path = request.getContextPath();//

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<head>

<basehref="<%=basePath%>"/>

…………

注:<base>标签:当前页面中所有连接都会在前面加上base地址。

七、Action的动态调用方法

Action执行的时候并不一定要执行execute方法,我们可以指定Action执行哪个方法:

1、   方法一(通过methed属性指定执行方法):

可以在配置文件中配置Action的时候用method=来指定执行哪个方法

<actionname="userAdd"class="com.bjsxt.struts2.user.action.UserAction"method="add">

<result>/user_add_success.jsp</result>

</action>

这样,只要在action的对象中有一个add的方法,并且返回类型为String就可以了。如果没有method属性,则默认执行execute()方法。

import com.opensymphony.xwork2.ActionSupport;

publicclass UserActionextends
ActionSupport {

public String add() {

returnSUCCESS;

}

}

2、   动态方法调用DMI(推荐)

可以在url地址中动态指定action执行那个方法。Url地址如下:

http://localhost:8080/Struts2_0500_ActionMethod/user/user!add

方法:action + ! + 方法名

注:只要Action对象中有这个方法,并且返回类型为String就可以调用。

这样Struts.xml配置文件中不需要配置methed属性。代码如下:

<actionname="user"class="com.bjsxt.struts2.user.action.UserAction">

<result>/user_add_success.jsp</result>

</action>

Action类:

publicclass UserActionextends
ActionSupport {

publicString add() {

returnSUCCESS;

}

}

总结:推荐使用第二种动态方法调用DMI,因为第一种需要大量的Action配置,后者可以在url中动态指定执行action中哪个方法。

八、Action通配符(wildcard)的配置

使用通配符,将配置量降到最低, 不过,一定要遵守"约定优于配置"的原则

1、   通配符

星号(*) 表示所有

{数字} 表示第几个通配符

例如:Student*  那么{1}代表第一个星号(*)

*_*            那么{1}代表第一个星号(*) ,{2}代表第二个星号(*)

2、   实例

<packagename="actions"extends="struts-default"namespace="/actions">

<action
name="Student*"class="com.bjsxt.struts2.action.StudentAction"method="{1}">

<result>/Student{1}_success.jsp</result>

</action>

<action
name="*_*"class="com.bjsxt.struts2.action.{1}Action"method="{2}">

<result>/{1}_{2}_success.jsp</result>

<!-- {0}_success.jsp -->

</action>

</package>

解释:第一个Action的
名称为name=”Student*”
method=”{1}”,表示所有Action以Student开始的都会执行这个Action,并且执行Student后字符为方法名的方法,例如:
访问的Action为Studentadd,会执行这个Action(Student*),并且执行add的方法.因为{1}在这里代表add,并且返回
/Studentadd_success.jsp页面。

第二个Action的名称name=”*_*” method=”{2}”
class=”…action.{1}Action”
表示所有Action中包含下划线(“_”)都会执行这个Action,例如:Teacher_add,那么会执行这个Action,并且Action对
应的类为TeacherAction,且执行Action中的add方法,返回结果页面为/Teacher_add_success.jsp,因为在这里
的{1}表示Teacher,{2}表示add

3、   匹配顺序

当匹配的Action有两个以上时,则会按匹配精确度高的那个Action,当有个相同的匹配精确度时,则按先后顺序进行。

九、Action的属性接收参数

Action中三种传递并接受参数:

1、 在Action添加成员属性接受参数

例如请求的URL地址:

http://localhost:8080/Struts2_0700_ActionAttrParamInput/user/user!add?name=a&age=8

其中传递了两个参数:name和age,其值分别为:a、8,此Action执行的是add()方法。

那我们只要在user这个Action对象中添加这两个成员属性并生成set、get方法。

publicclass UserActionextends
ActionSupport {

private Stringname;

privateintage;

public String add() {

System.out.println("name=" +name);

System.out.println("age=" +age);

returnSUCCESS;

}

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicint getAge() {

returnage;

}

publicvoid setAge(int
age) {

this.age = age;

}

}

2、 域模型(Domain Model)

就是利用对象域来进行传递和接受参数

例如请求的URL地址:

http://localhost:8080/Struts2_0800_DomainModelParamInput/user/user!add?user.name=a&user.age=8

其中,访问的是namespace=”/user” action的name=”user” Action所执行的方法method=”add”

利用对象域user来传递参数,为对象的属性赋值(user.name=a user.age=8)

注:需要一个对象user 并且这个对象需要有两个成员属性,且具有get、set方法。

然后在Action中添加一个User对象的成员属性。并且有get、set方法,就可以了。

//User对象

publicclass User {

private Stringname;

privateintage;

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicint getAge() {

returnage;

}

publicvoid setAge(int
age) {

this.age = age;

}

}

 

    //Action类

publicclass UserActionextends
ActionSupport {

private Useruser;

//private UserDTO userDTO;

public String add() {

System.out.println("name=" +user.getName());

System.out.println("age=" +user.getAge());

returnSUCCESS;

}

publicUser getUser() {

returnuser;

}

publicvoid setUser(User user) {

this.user = user;

}

}

3、 ModelDriven接收参数

使Action实现com.opensymphony.xwork2.ModelDriven<User>(在实现接口时需要使用泛型,否则使用时需要转型)中利用其getModel()方法返回对象模型,从而获得传入的参数。

例如URL如下:

http://localhost:8080/Struts2_0900_ModelDrivenParamInput/user/user!add?name=a&age=8

其:访问的是namespace=”/user” action的name=”user” Action所执行的方法method=”add”,其传入了两个参数:name=a,age=8。

参数被传入至Action后,会被ModelDriven对象根据参数名自动赋值给User对象相应的属性而生成User对象,并且由getModel()返回。那么我们在Action中就可以利用这个对象了。

注意:传入的参数名需要与对象模型中的成员属性一致。

对象模型User:

publicclass User {

private Stringname;

privateintage;

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

publicint getAge() {

returnage;

}

publicvoid setAge(int
age) {

this.age = age;

}

}

    Action对象

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

publicclass UserActionextends
ActionSupportimplements ModelDriven<User>{

private Useruser =
new User();

public String add() {

System.out.println("name=" +user.getName());

System.out.println("age=" +user.getAge());

returnSUCCESS;

}

@Override

public User getModel() {

returnuser;

}   }

十、Action属性接收参数中文问题

如果表单提交数据中有中文时,尽量使用post方式。

需要在Struts.xml配置文件中加入一个常量配置,如下:

<struts>

<constantname="struts.devMode"value="true"/>

  <constant name="struts.i18n.encoding" value="GBK" /><!-- internationalization -->

<packagename="user"extends="struts-default"namespace="/user">

<action
name="userAdd"class="com.bjsxt.struts2.user.action.UserAction"method="add">

<result>/user_add_success.jsp</result>

</action>

</package>

</struts>

但是,在Struts2 2.7之前,这个配置无效,需要其它方法设置。如下:

手动在web.xml中在Struts过滤器之前配置一个过滤器用于解决中文的问题。

十一、     简单数据验证

使用addFieldError方法和s:fieldError标签简单处理数据校验

场景:对一个用户名进行验证,如果用户名不合法,则显示给客户端查看信息。

URL请求地址:

http://localhost:8080/Struts2_1100_SimpleDataValiation/user/user!add?name=a 

分析:访问的Struts2配置,namespace=”/user” action的name=”user” Action所执行的方法method=”add”并且传入了一个参数name=a.如下:

<packagename="user"extends="struts-default"namespace="/user">

<action
name="user"class="com.bjsxt.struts2.user.action.UserAction">

<result>/user_add_success.jsp</result>

<result
name="error">/user_add_error.jsp</result>

</action>

</package>

根据配置文件可以得知action所对应的类为com.bjsxt.struts2.user.action.UserAction,并且具有两个结果集(success和error).代码如下:

import com.opensymphony.xwork2.ActionSupport;

publicclass UserActionextends
ActionSupport {

private Stringname;

public String add() {

if(name ==null || !name.equals("admin"))
{

//addFieldError
添加错误信息,可以在客户端访问到。

this.addFieldError("name","name is error");

this.addFieldError("name","name is too long");

returnERROR;

}

returnSUCCESS;

}

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

}

根据Action类代码,可以看到Action是利用Action的成员属性(name)来接受参数值,并且使用this.addFieldError()方法添加错误信息,以便前台可以访问到。

this.addFieldError(name,errorMessage);

注:此方法是使用继承了ActionSupport父类的

name:可以是傻的属性名称,但一般建议使用哪个成员属性出题了,就用那个。当前是因为name没有通过验证,所以使用name

errorMessage:添加的信息

在客户端获取这些信息,如下:

<body>

User Add Error!

<s:fielderrorfieldName="name"theme="simple"/>

<br/>

<s:propertyvalue="errors.name"/>

<s:debug></s:debug>

</body>

注:使用<s:fielderror>标题,需要使用<%@taglib>命令引用Struts2的标签库如下:

<%@tagliburi="/struts-tags"prefix="s"%>

1、<s:fielderror>标签:获取使用addFieldError()方法添加的信息。

FiledName:指定信息的名称。

Theme: 指定显示的主题。

注:使用此标签获取的错误信息,Struts强制添加了css的修饰。生成的HTML代码如下(不长用):

<ul class="errorMessage">

<li><span>name is error</span></li>

<li><span>name is too long</span></li>

</ul>

Class=”errorMessage”是Struts2已经设置好的一个css了。这个方式不方便我们自定义样式。

2、<s:debug></s:debug>:这是标签的写方式,会在页面上产生一个链接,点击后显示如下(Struts2生成的一些信息):

3、<s:property>标签:获取值堆栈属性所对应的值。

<s:propertyvalue="errors.name"/>

注:value:指定值堆栈的属性名及数据下标等。

例如:value=”a” 获取Action类的成员属性a的值

Value=”errors” 获取errors属性的对象Map值

Value=”errors.name”获取errors属性的对象Map的key为name的value

Value=”errors.name[0] 获取errors属性的对象Map的key为name的value的第一个元素的值。

注:如果获取Action Context中的Key值,需要在前面加#(井号)

例如:<s:property value=”#request”/>

十二、     访问Web元素

取得Map类型request,session,application,真实类型 HttpServletRequest, HttpSession, ServletContext的引用:

1.   前三者:依赖于容器

2.   前三者:IOC (只用这种)

3.   后三者:依赖于容器

4.   后三者:IOC

一、方法一:ActionContext方式

一般在Action类的构造方法、或execute()方法中获取。

publicclass LoginAction1extends
ActionSupport {

private Maprequest;

private Mapsession;

private Mapapplication;

public LoginAction1() {

request = (Map)ActionContext.getContext().get("request");

session = ActionContext.getContext().getSession();

application = ActionContext.getContext().getApplication();

}

public String execute() {

request.put("r1","r1");

session.put("s1","s1");

application.put("a1","a1");

returnSUCCESS;

}

}

然后在Jsp页面中获取相关web元素。

<body>

User Login Success!

<br/>

<s:propertyvalue="#request.r1"/>
|<%=request.getAttribute("r1")%><br/>

<s:propertyvalue="#session.s1"/>
|<%=session.getAttribute("s1")%><br/>

<s:propertyvalue="#application.a1"/>
|<%=application.getAttribute("a1")%><br/>

<s:propertyvalue="#attr.a1"/><br/>

<s:propertyvalue="#attr.s1"/><br/>

<s:propertyvalue="#attr.r1"/><br/>

<s:debug></s:debug>

<br/>

</body>

注:因为request、session、application对象Struts2将在放入到Action Context中,

因此需要使用#key来访问对象们。

后面的是java脚本代码的访问方式。

二、方式二:Ioc(控制反转)—推荐使用

让Action类实现RequestAware、SessionAware、
ApplicationAware接口,然后重写他们的set方法(setRequest、setSession、setApplication),通过
依赖注入、控制反转(原来自己控制,现在由别人来控制值。)

import org.apache.struts2.interceptor.ApplicationAware;

import org.apache.struts2.interceptor.RequestAware;

import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionSupport;

publicclass LoginAction2extends
ActionSupportimplements RequestAware,SessionAware, ApplicationAware {

private Map<String, Object>request;

private Map<String, Object>session;

private Map<String, Object>application;

//DI dependency injection依赖注入

//IoC inverse of control控制反转

public String execute() {

request.put("r1","r1");

session.put("s1","s1");

application.put("a1","a1");

returnSUCCESS;

}

@Override

publicvoid setRequest(Map<String, Object> request) {

this.request = request;

}

@Override

publicvoid setSession(Map<String, Object> session) {

this.session = session;

}

@Override

publicvoid setApplication(Map<String, Object> application) {

this.application = application;

}

}

在视图(JSP)页面中获取相关对象,同方式一。

三、方式三:获取原类型

获取是的HttpServletRequest/HttpSession/ServletContext

publicclass LoginAction3extends
ActionSupport {

private HttpServletRequestrequest;

private HttpSessionsession;

private ServletContextapplication;

public LoginAction3() {

request = ServletActionContext.getRequest();

session = request.getSession();

application =
session.getServletContext();

}

public String execute() {

request.setAttribute("r1","r1");

session.setAttribute("s1","s1");

application.setAttribute("a1","a1");

returnSUCCESS;

}

}

四、方式四:获取原类型-控制反转

首先需要Action实现org.apache.struts2.interceptor.ServletRequestAware接口,然后重写setServletRequest()方法,获取HttpServletRequest对象,再通过HttpServletRequest对象取昨HttpSession和ServletContext对象。

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

publicclass LoginAction4extends
ActionSupportimplementsServletRequestAware {

private HttpServletRequestrequest;

private HttpSessionsession;

private ServletContextapplication;

public String execute() {

request.setAttribute("r1","r1");

session.setAttribute("s1","s1");

application.setAttribute("a1","a1");

returnSUCCESS;

}

@Override

publicvoidsetServletRequest(HttpServletRequest
request) {

this.request = request;

this.session = request.getSession();

this.application =session.getServletContext();

}

}

十三、     Struts2配置文件模块化包含(include)

<include>标签

当Struts配置文件比较多,需要模块化划分或分开成为多个配置文件时,这个功能比较好。

则需要使用<include>标签把其它的配置文件引入到Struts.xml配置文件中就可以了。

例如:有一个login.xml配置文件如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstruts
PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<packagename="login"extends="struts-default"namespace="/login">

<action
name="login*"class="com.bjsxt.struts2.user.action.LoginAction{1}">

<result>/user_login_success.jsp</result>

</action>

</package>

</struts>

则需要在struts.xml文件中使用<include>标签将其引入就可以了。Struts.xml如下

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstruts
PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constantname="struts.devMode"value="true"/>

<include file="login.xml" />

</struts>

十四、     默认的Action

当用户访问的namespace下一个不存在的Action,则会将使用默认的Action。

使用<default-action-ref name=”name”>标签 其中 name属性指向下面已经定义的Action名称了。

<struts>

<constantname="struts.devMode"value="true"/>

<packagename="default"namespace="/"extends="struts-default">

<default-action-refname="index"></default-action-ref>

<actionname="index">

<result>/default.jsp</result>

</action>

</package>

</struts>

当前访问namespace=”/”下不存在的Action时,则返回自动转到访问/default.jsp页面。

十五、     Action总结

1、 实现一个Action的最常用的方式:从ActionSupport继承

2、 DMI动态方式的调用:!

3、 通配符配置:* {1} {2}

4、 接收参数的方式(一般属性或DomainModel来接收)

5、 简单参数验证addFieldError

a)   一般不使用Struts的UI标签

6、 访问Web元素

a)   Map类型

i.      IoC

ii.      依赖Struts2

b)   原始类型

i.      IoC

ii.      依赖Struts2

7、 包含文件配置

02 Struts2-Result

一、Result类型 (type)

1、 dispatcher

运用服务器跳转 jsp forward

不可以是Action,只可以跳转到视图

2、 redirect

客户端跳转(重定向)-url发生变化

不可以是Action,只可以跳转到视图

3、 chain

跳转到Action (forward action)

可以动用到Action

在访问Action时,Action前面不要加”/”

4、 redirectAction

客户端跳转到Action――-url发生变化

5、 freemarker

6、 httpheader

发送一个http头

7、 stream

下载

8、 velocity

9、 xslt

10、   plaintext

返回页面的源码

11、   titles

把页面分成几块,每个页面都可以动态的指定

<struts>

<constantname="struts.devMode"value="true"/>

<packagename="resultTypes"namespace="/r"extends="struts-default">

<action
name="r1">

<result
type="dispatcher">/r1.jsp</result>

</action>

<action
name="r2">

<result
type="redirect">/r2.jsp</result>

</action>

<action
name="r3">

<result
type="chain">r1</result>

</action>

<action
name="r4">

<result
type="redirectAction">r2</result>

</action>

</package>

</struts>

注:当访问不同的namespace下的Action时,则使用如下方式:

<result type="chain">

<param name="actionName">dashboard</param>//Action名称

<param name="namespace">/secure</param>//namespace值

</result>

二、全局结果集(Globle Result)

当有多个Action使用同一个结果集时,则可以使用全局结果集(Globle Result),如下:

<packagename="user"namespace="/user"extends="struts-default">

<global-results>

<result
name="mainpage">/main.jsp</result>

</global-results>

<actionname="index">

<result>/index.jsp</result>

</action>

<actionname="user"class="com.bjsxt.struts2.user.action.UserAction">

<result>/user_success.jsp</result>

<result
name="error">/user_error.jsp</result>

</action>

</package>

Action所对应的Action类如下:

UserAction

publicclass UserActionextends
ActionSupport {

privateinttype;

publicint getType() {

returntype;

}

publicvoid setType(int
type) {

this.type = type;

}

@Override

public String execute()throws
Exception {

if(type == 1)return"success";

elseif (type == 2)return"error";

elsereturn"mainpage";

}

}

UserAction返回的结果集中有”mainpage”,但是user的Action中并没有”mainpage”的Rsult,这时就会使用全局的结果庥(global-result),这人结果集中有”mainpage”

当其它不同的package需要使用这个全局的Result时,则需要使用<package>标签中的extends属性来指定继承包含全局的package就可以了。如下:

<packagename="admin"namespace="/admin"extends="user">

<actionname="admin"class="com.bjsxt.struts2.user.action.AdminAction">

<result>/admin.jsp</result>

</action>

</package>

这时package=”user”中的结果集就可以被package=”admin”中的Action使用了。

三、动态的结果集(dynamic result)

<struts>

<constantname="struts.devMode"value="true"/>

<packagename="user"namespace="/user"extends="struts-default">

<action
name="user"class="com.bjsxt.struts2.user.action.UserAction">

<result>${r}</result>

</action>

</package>

</struts>

注:${}:作用是用于在配置文件中从Value stack(值栈)中取值。

例如:${r} 表示从Value stack(值栈)中取rAction的(成员属性)的值。注意这个成员属性必需具有

注:此处的${}不是el表达式。

get/set方法。

Action类中指定了r的值。这样就动态确定了Result的值

publicclass UserActionextends
ActionSupport {

privateinttype;

private Stringr;

public String getR() {

returnr;

}

publicvoid setR(String r) {

this.r = r;

}

publicint getType() {

returntype;

}

publicvoid setType(int
type) {

this.type = type;

}

@Override

public String execute()throws
Exception {

if(type == 1)r="/user_success.jsp";

elseif (type == 2)r="/user_error.jsp";

return"success";

}

}

四、带参数的结果集

也就是向结果集传参数

服务器forward共享一个值栈(Value stack)

客户端跳转则不共享

例如:

<packagename="user"namespace="/user"extends="struts-default">

<action
name="user"class="com.bjsxt.struts2.user.action.UserAction">

<result
type="redirect">/user_success.jsp?t=${type}</result>

</action>

</package>

UserAction类:

publicclass UserActionextends
ActionSupport {

privateinttype;

publicint getType() {

returntype;

}

publicvoid setType(int
type) {

this.type = type;

}

@Override

public String execute()throws
Exception {

return"success";

}

}

因为当执行Action后,已经将Action的成员属性写入了值堆栈了,因此可以在配置文件中使用${type}取出type的值。

但是只有Action才具有值堆栈的。Jsp是没有什么值堆栈的。因为当result重新定向到/user_success.jsp?t=${type}后,是不能从值堆栈中取出t的值。但是有ActionContext的,所以可以从中取出t的值。JSP代码如下:

<body>

User Success!

from valuestack:<s:property
value="t"/><br/>

from actioncontext:<s:property
value="#parameters.t"/>

<s:debug></s:debug>

</body>

注:<s:propertyvalue="t"/>取不到值,因为jsp不是一个Action没有值堆栈。

<s:propertyvalue="#parameters.t"/>可以取出t的值,因为#方式是从ActionContext中取属性值。

ActionContext堆栈中具有parameters这个属性是用于存储传入的参数。所以可以取出。

五、Result总结

1、 常用的四种类型

a)   dispatcher(默认)

b)   redirect

c)   chain

d)   redirectAction

2、 全局结果集

a)   Global-result | extends

3、 动态结果集(了解)

a)   在Action中保存一个属性,存储具体的结果location

4、 传递参数

a)   客户端跳转才需要传递

b)   ${}表达式(不是el表达式)

六、项目经理:

1、  界面原型

2、  设计数据库

3、  使用什么框架构

4、  设计约定(硬编码) ***

项目名称、数据库名称、配置文件名称、Action、JSP……

   

03 OGNL表达式语言

Object Graph Navigation Language 对象图导航语言

<s:property value=””> 注意:  value里的内容称为ognl表达式

User.xxx 只有传入参数,才会构造对象,或者直接在action中new也可以,但是User对象必需具有无参数的构造方法。

{}大括号 在OGNL中可以表示一个集合

    OGNL表达式语言访问静态方法,需要在Struts2.xml配置文件如下:

<constantname="struts.ognl.allowStaticMethodAccess"value="true"></constant>

使用一个实例如说明OGNL表达式语言,如下:

Cat类

package com.wjt276.struts2.ognl;

publicclass Cat {

private Dogfriend;

public Dog getFriend() {

returnfriend;

}

publicvoid setFriend(Dog friend) {

this.friend = friend;

}

public String miaomiao() {

return"miaomiao";

}

}

Dog类

package com. wjt276.struts2.ognl;

publicclass Dog {

private Stringname;

public Dog() {   }

public Dog(String name) {

super();

this.name = name;

}

public String getName() {

returnname;

}

publicvoid setName(String name) {

this.name = name;

}

@Override

public String toString() {

return"dog: " +name;

}

}

S类

package com. wjt276.struts2.ognl;

publicclass S {

publicstatic StringSTR
="STATIC STRING";

publicstatic String s() {

return"static method"; }}

User类

package com. wjt276.struts2.ognl;

publicclass User {

privateintage = 8;

public User() {}

public User(int
age) {

super();

this.age = age;

}

publicint getAge() {

returnage;

}

publicvoid setAge(int
age) {

this.age = age;

}

@Override

public String toString() {

return"user" +age;

}

}

OgnlAction类

package com. wjt276.struts2.ognl;

publicclass OgnlActionextends
ActionSupport {

privateCat
cat;

private Map<String, Dog>dogMap =
new HashMap<String, Dog>();

private Set<Dog>dogs =
new HashSet<Dog>();

private Stringpassword;

private Useruser;

private Stringusername;

private List<User>users =
new ArrayList<User>();

public OgnlAction() {

users.add(new User(1));

users.add(new User(2));

users.add(new User(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"));

}

public String execute() {

returnSUCCESS;

}

publicCat getCat() {

returncat;

}

public Map<String, Dog> getDogMap() {

returndogMap;

}

public Set<Dog> getDogs() {

returndogs;

}

public String getPassword() {

returnpassword;

}

public User getUser() {

returnuser;

}

public String getUsername() {

returnusername;

}

public List<User> getUsers() {

returnusers;

}

public String m() {

return"hello";

}

publicvoid setCat(Cat cat)
{

this.cat = cat;

}

publicvoid setDogMap(Map<String, Dog> dogMap) {

this.dogMap = dogMap;

}

publicvoid setDogs(Set<Dog> dogs) {

this.dogs = dogs;

}

publicvoid setPassword(String password) {

this.password = password;

}

publicvoid setUser(User user) {

this.user = user;

}

publicvoid setUsername(String username) {

this.username = username;

}

publicvoid setUsers(List<User> users) {

this.users = users;

}

}

Struts2.xml配置文件:

<struts>

<constantname="struts.enable.DynamicMethodInvocation"value="false"/>

<constantname="struts.devMode"value="true"/>

<!--允许ognl访问静态方法
-->

<constantname="struts.ognl.allowStaticMethodAccess"value="true"></constant>

<includefile="/com/wjt276/struts2/ognl/ognl.xml"/>

</struts>

Com.wjt276.struts2.ognl.ognl.xml配置文件

<packagename="ognl"extends="struts-default">

<action
name="ognl"class="com.wjt276.struts2.ognl.OgnlAction">

<result>/ognl.jsp</result>

</action>

</package>

客户端请求的URL地址:

http://localhost:8080/Struts2_1900_OGNL/ognl.action?username=u&password=p&user.age=9

分析:此请求是访问action的name=”ognl.action”namespace=”/”
并传入了几个参数(前两个由Action的成员属性接受,后一个由Action的成员对象属性user接受。),根据Struts2配置文件得知此请求转
到/ognl.jsp页面。如下:

<ol>

<li>访问值栈中的action的普通属性: username =<s:propertyvalue="username"/></li>

<li>访问值栈中对象的普通属性(get set方法):<s:propertyvalue="user.age"/>
|<s:propertyvalue="user[‘age‘]"/>
|<s:propertyvalue="user[/"age/"]"/>
| wrong:<%--<s:property value="user[age]"/>--%></li>

<li>访问值栈中对象中的成员对象的普通属性(get set方法):<s:propertyvalue="cat.friend.name"/></li>

<li>访问值栈中对象的普通方法:<s:propertyvalue="password.length()"/></li>

<li>访问值栈中对象的普通方法:<s:propertyvalue="cat.miaomiao()"/></li>

<li>访问值栈中action的普通方法:<s:propertyvalue="m()"/></li>

<hr
/>

<li>访问静态方法:<s:propertyvalue="@[email protected]()"/></li>

<li>访问静态属性:<s:propertyvalue="@[email protected]"/></li>

<li>访问Math类的静态方法:<s:propertyvalue="@@max(2,3)"/></li>

<hr
/>

<li>访问普通类的构造方法:<s:propertyvalue="new
com.bjsxt.struts2.ognl.User(8)"
/></li><%--返回对象的toString()生成的数据--%>

<hr
/>

<li>访问List:<s:propertyvalue="users"/></li>

<li>访问List中某个元素:<s:propertyvalue="users[1]"/></li>

<li>访问List中元素某个属性的集合:<s:propertyvalue="users.{age}"/></li>

<li>访问List中元素某个属性的集合中的特定值:<s:propertyvalue="users.{age}[0]"/>
|<s:propertyvalue="users[0].age"/></li>

<li>访问Set:<s:propertyvalue="dogs"/></li>

<li>访问Set中某个元素:<s:propertyvalue="dogs[1]"/></li>

<li>访问Map:<s:propertyvalue="dogMap"/></li>

<li>访问Map中某个元素:<s:propertyvalue="dogMap.dog101"/>
|<s:propertyvalue="dogMap[‘dog101‘]"/>
|<s:propertyvalue="dogMap[/"dog101/"]"/></li>

<li>访问Map中所有的key:<s:propertyvalue="dogMap.keys"/></li>

<li>访问Map中所有的value:<s:propertyvalue="dogMap.values"/></li>

<li>访问容器的大小:<s:propertyvalue="dogMap.size()"/>
|<s:propertyvalue="users.size"/></li>

<hr
/>

<li>投影(过滤):<s:propertyvalue="users.{?#this.age==1}[0]"/></li>

<li>投影:<s:propertyvalue="users.{^#this.age>1}.{age}"/></li><%--头一个
--%>

<li>投影:<s:propertyvalue="users.{$#this.age>1}.{age}"/></li><%--最后一个--%>

<li>投影:<s:propertyvalue="users.{$#this.age>1}.{age}
== null"
/></li>

<hr
/>

<li>[]:<s:propertyvalue="[0].username"/></li><%--值堆栈中的对象(Object),从上开始的第0个至堆栈底对象
--%>

</ol>

<s:debug></s:debug>

访问后服务器返回给客户端的结果:

1.        访问值栈中的action的普通属性: username = u

2.        访问值栈中对象的普通属性(get set方法):9 | 9 | 9 | wrong:

3.        访问值栈中对象的普通属性(get set方法):

4.        访问值栈中对象的普通方法:1

5.        访问值栈中对象的普通方法:

6.        访问值栈中action的普通方法:hello


7.        访问静态方法:static method

8.        访问静态属性:STATIC STRING

9.        访问Math类的静态方法:3


10.     访问普通类的构造方法:user8


11.     访问List:[user1, user2, user3]

12.     访问List中某个元素:user2

13.     访问List中元素某个属性的集合:[1, 2, 3]

14.     访问List中元素某个属性的集合中的特定值:1 | 1

15.     访问Set:[dog: dog1, dog: dog2, dog: dog3]

16.     访问Set中某个元素:<!—没有显示是因为在Set中没有排序就不存在的用下标访问了-->

17.     访问Map:{dog102=dog: dog102, dog101=dog: dog101, dog100=dog: dog100}

18.     访问Map中某个元素:dog: dog101 | dog: dog101 | dog: dog101

19.     访问Map中所有的key:[dog102, dog101, dog100]

20.     访问Map中所有的value:[dog: dog102, dog: dog101, dog: dog100]

21.     访问容器的大小:3 | 3


22.     投影(过滤):user1

23.     投影:[2]

24.     投影:[3]

25.     投影:false


26.     []:u

27.     [Debug]

04 Struts2-Tags

Struts2标签目录

1、  通用标签

a)    Property

b)    Set

i.      默认为action scope,会将值放入request和ActionContext中

ii.      page/request/session/application

c)    bean

d)    include对中文文件支持的问题,不建议使用,如需要包含,改用jsp包含

e)    param

f)    debug

2、  控制标签

a)    If elseif else

b)    Iterator

i.      collections map enumerateon iterator array

c)    subset

3、  UI标签

a)    Theme

i.      Simple xhtml(默认) css_xhtml ajax

4、  AJAX标签

a)    补充

5、  $ # % 的区别

a)    $ 用于i18n和Struts配置文件

b)    # 取得ActionContext的值

c)    % 将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用

i.      参考<s:property>和<s:include>

一、 property标签

格式:<s:property value=””default=”” escape=”true|false”/>

如果value中的内容为object,则Struts2都会把它解析成ognl表达式

如果里面需要表示为字符串,则需要将内容用单引号括起来

1、  利用ognl表达式取值(例如:取值堆栈中的username值)

<s:propertyvalue="username"/>

2、  取值为字符串

需要将内容用单引号括起来

<s:propertyvalue="’username’"/>

3、  设置默认值-default

如果一个对象值取不到,则可以使用default设置一个默认值。

<s:propertyvalue="admin" default=”管理员”/>

4、  设定HTML-escape

是否设置返回值为HTML原代码样式

true:解析返回值的html代码 false:原封不动返回值

<s:propertyvalue="<hr/>"escape="false"/>

二、 set标签

注:var 用于设定变量名

value 变量值(可以是ognl表达式),也可以是字符串

scope 就是的作用范围 request session page application action(默认)

<li>set设定adminName值(默认为request和
ActionContext):<s:set
var="adminName"value="username"/></li>

<li>set从request取值:<s:propertyvalue="#request.adminName"/></li>

<li>set从ActionContext取值:<s:propertyvalue="#adminName"/></li>

<%--<li>set设定范围: <s:set name="adminPassword" value="password" scope="page"/></li>

<li>set
从相应范围取值: <%=pageContext.getAttribute("adminPassword") %></li>

--%>

<li>set设定var,范围为ActionContext:<s:set
var="adminPassword"value="password"scope="session"/></li>

<li>set使用#取值:<s:propertyvalue="#adminPassword"/></li>

<li>set从相应范围取值:
<s:property
value="#session.adminPassword"/></li>

三、 bean标签

定义bean,并使用param来设定新的属性值

<s:beanname="com.bjsxt.struts2.tags.Dog">

<s:paramname="name"value="‘pp‘"></s:param>

</s:bean>

定义bean,并使用一个变量(var)来接受创建的这个bean,取出值来

<s:beanname="com.bjsxt.struts2.tags.Dog"var="myDog">

<s:param
name="name"value="‘oudy‘"></s:param>

</s:bean>

拿出值:因为在actionContext中,所以使用#

<s:propertyvalue="#myDog.name"/>

当<s:bean>不指定var时,则对象相关属性会在值栈中。如果需要访问,则只能在<s:bean>标签内访问。

当<s:bean>标签结束后,则值栈就不存在这个对象了。

<s:beanname="com.bjsxt.struts2.tags.Dog">

<s:paramname="name"value="‘pp‘"></s:param>

<s:propertyvalue="name"/>

</s:bean>

四、 <include>标签-少使用

包含文件

<li>include _include1.html包含静态英文文件

<s:include
value="/_include1.html"></s:include>

</li>

<li>include _include2.html包含静态中文文件

<s:include
value="/_include2.html"></s:include>

</li>

<li>include _include1.html包含静态英文文件,说明%用法

<s:set
var="incPage"value="%{‘/_include1.html‘}"/>

<s:include
value="%{#incPage}"></s:include>

</li>

%{xxx}
强制将xxx内容转换成OGNL表达式

<-- One: -->
<s:include value="myJsp.jsp" />
<-- Two: -->
<s:include value="myJsp.jsp">
   <s:param name="param1" value="value2" />
   <s:param name="param2" value="value2" />
</s:include>
<-- Three: -->
<s:include value="myJsp.jsp">
   <s:param name="param1">value1</s:param>
   <s:param name="param2">value2</s:param>
</s:include>

五、 If elseif else

<li>if elseif else:

age = <s:propertyvalue="#parameters.age[0]"/><br/>

<s:set var="age"value="#parameters.age[0]"/>

<s:if test="#age< 0">wrong age!</s:if>

<s:elseif test="#parameters.age[0]< 20">too young!</s:elseif>

<s:else>yeah!</s:else><br/>

<s:if test="#parameters.aaa == null">null</s:if>

</li>

<s:if test="%{false}">
    <div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
    <div>Will Be Executed</div>
</s:elseif>
<s:else>
    <div>Will Not Be Executed</div>

</s:else>

六、 Iterator标签

<li>遍历集合:<br/>

<s:iterator value="{1, 2, 3}">

<s:property/> |     <!—不需要写其它的,就可以输出数组内的值-->

</s:iterator>

</li>

<li>自定义变量:<br/>

<s:iterator value="{‘aaa‘, ‘bbb‘, ‘ccc‘}"var="x">

<s:property value="#x.toUpperCase()"/> |

</s:iterator>

</li>

<li>使用status:<br/>

<s:iterator value="{‘aaa‘, ‘bbb‘, ‘ccc‘}"status="status">

<s:property/> |

遍历过的元素总数:<s:propertyvalue="#status.count"/> |

遍历过的元素索引:<s:propertyvalue="#status.index"/> |

当前是偶数?:<s:propertyvalue="#status.even"/> |

当前是奇数?:<s:propertyvalue="#status.odd"/> |

是第一个元素吗?:<s:propertyvalue="#status.first"/> |

是最后一个元素吗?:<s:propertyvalue="#status.last"/>

<br />

</s:iterator>

</li>

<li>

<s:iterator value="#{1:‘a‘, 2:‘b‘, 3:‘c‘}">

<s:property value="key"/> |<s:propertyvalue="value"/><br/>

</s:iterator>

</li>

<li>

<s:iterator value="#{1:‘a‘, 2:‘b‘, 3:‘c‘}"var="x">

<s:property value="#x.key"/> |<s:propertyvalue="#x.value"/><br/>

</s:iterator>

</li>

七、 Theme

1、  css(覆盖Struts2原来的css)

2、  覆盖单个文件

3、  定义自己的theme

4、  实战

a)    把所有主题定义为simple

b)    Fielderror特殊处理

c)    自己控制其他标签的展现

05设计约定(编码规定)

1、  原则:简单就是美

2、  库名:项目名

3、  表的命名:t_model名

4、  字段:保持和属性名一致(尽量不要起和数据库命名冲突)

5、  用层来划分包

com.wjt276.bbs.action model(bean) service dto(vo)

6、  Action: xxxAction

7、  *.*

8、  前台: /

9、  后台: /admin

10、Package: “action” adminAction

06 项目开发顺序

1、  建立界面原型

2、  建立Struts.xml

a)    确定namespace

b)    确定packge

c)    确定Action的名称

d)    确定Result

e)    将界面原型页面进行修改,匹配现有设置

f)    测试

3、  建立数据库(或实体类)

4、  建立Model层

5、  建立Service层(后面讲hibernate后再完美)

a)    此时可以使用Junit进行单元测试了

6、  着手开发

07
声明式异常处理

注:Struts2支持声明式异常处理。

    Struts2是通过拦截器(interceptor)来处理声明式异常处理。

要求在DAO、Service、Action层都需要抛出导演就可以了。其它的让Struts2来处理。详细过程如下:

实例:

如果在列表时出现错误,则方法如下:

public List<Category> list()throws SQLException{

Connection conn = DB.createConn();

String sql = "select * from _category";

List<Category> categories = new ArrayList<Category>();

PreparedStatement ps = DB.prepare(conn, sql);

ResultSet rs = null;

try {

rs = ps.executeQuery();

Category c = null;

while(rs.next()){

c = new Category();

…………

}

} catch (SQLException e) {

e.printStackTrace();

throw(e);//此处向外抛出异常,让调用它的方法知道

} finally{

DB.close(rs);

DB.close(ps);

DB.close(conn);

}

return categories;

}

然后在调用它的Action也向上抛出异常

public String list()throws SQLException{

categories =
categoryService.list();

returnSUCCESS;

}

注意重点:我们需要在Struts.xml配置文件中配置需要处理的异常就可以了。

<actionname="*-*"class="com.wjt276.bbs2009.action.{1}Action"method="{2}">

<result>/admin/{1}-{2}.jsp</result>

<result
name="input">/admin/{1}-{2}.jsp</result>

<!--  
<exception-mapping>标签是映射异常处理。表示映射哪种异常,此处是java.lang.Exception, 如果出现异常,那么它会跳转到reslut="error"的结果集,也就是/error.jsp       -->

<exception-mappingresult="error"exception="java.lang.Exception"/>

<result
name="error">/error.jsp</result>

</action>

当然,我们也可以将所有的异常使用同一个异常映射,那就是<global-exception-mappings>,需要映射的packge只需要继承此package就可以了。如下:

<packagename="bbs2009-deafult"extends="struts-default">

<global-results>

<result
name="error">/error.jsp</result>

</global-results>

<global-exception-mappings>

<exception-mappingresult="error"exception="java.lang.Exception"/>

</global-exception-mappings>

</package>

<!--后台Action的配置区 -->

<packagename="admin"namespace="/admin"extends="bbs2009-default">

<default-action-refname="index"></default-action-ref>

<action
name="index">

<result>index.html</result>

</action>

<action
name="*-*"class="com.wjt276.bbs2009.action.{1}Action"method="{2}">

<result>/admin/{1}-{2}.jsp</result>

<result
name="input">/admin/{1}-{2}.jsp</result>

<result
name="error">/error.jsp</result>

</action>

</package>

注意:如果使用全局异常映射(<global-exception-mappings>)和全局结果集(<global-results>)则需要全局结果集(<global-results>)在前。

如果局部(当前)Action、和全局结果集存在相同的<result>,则使用最近的那个结果。

总结:

1、  在Action中进行异常映射

2、  在package中进行全局异常映射

3、  使用继承共用异常映射

4、  Struts2中异常处理由拦截器实现(观察struts-default.xml)

a)    实际上Struts2的大多数功能都由拦截器实现。

08
国际化

一、  国际化资源文件

命名格式:xxx_语言_国家.properties

例如:app_en_US.properties  表示美国 英语

app_zh_CN.properties  表示中国 汉语

资源文件的编码是使用UTF-8的编码,这样中文也必需是UTF-8的格式,则需要将中文转换成UTF-8的,你可以使用propertiesEditor插件来进行输入中文。

app_en_US.properties文件内容

welcome.msg=hello world!

app_zh_CN.properties

welcome.msg=欢迎您!

二、  Java国际化

要求:资源文件要求存放在classpath的根目录下(src下)。

然后再建立一个Java类和一个main方法如下:这样就可以进行国际化处理了。

publicstaticvoid main(String[] args) {

ResourceBundle res = ResourceBundle.getBundle("app",Locale.CHINA);

System.out.println(res.getString("welcome.msg"));

}

注:java.util.ResourceBundle是加载国际化资源文件的类。利用此类的getBundle()方法加载classpath下的指定开头的文件名的国际化资源文件。并且在加载时需要指定加载哪个国家的国际人资源文件。

此实例中的ResourceBundle.getBundle("app",Locale.CHINA);表示加载以"app"开头的国际化资源文件,并且是中国的(对应的zh_CN)的。

一但国际化资源文件加载上来后,就可以使用ResourceBundle类的getSring("welcome.msg")方法获取当前内容。

三、 Struts2国际化

Struts2国际化分为:Action级别、package级别、Application级别

1、  Action级别

条件:要求国际化资源文件名的前缀同相应的Action名,并且国际化资源文件需要与相应的Action在同一个包中

例如:我们需要国际化登录页面。如下

原始代码:<body>

Login_input
<br>

<formaction="admin/Login_login">

username:<inputname="username"type="text"/><br/>

password:<inputname="password"type="password"/>

<inputtype="submit"value="login">

</form></body>

这里需要对"Login_input"、"username"、"password"、"login"进行国际化。因为登录页面的请求URL为

http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input

根据Struts2.xml的配置文件可知对应的Action为LoginAction.java.因为国际化资源文件名应是LoginAction_开头(此处为LoginAction_zh_CN.properties、LoginAction_en_US.properties)如下

注意:要求国际化资源文件需要与相应的Action在同一包中(见上第三个图),这样Struts2就可以保证当访问这个LoginAction时国际化资源文件会自动加载。我们在相应的文件中可以直接访问(利用ActionSupport类中的getText()方法。)了。

我们现在只需要将登录页面代码修改就可以了。

<body>

<s:property
value="getText(‘login.title‘)"/><br>

<formaction="admin/Login-login"method="post">

<s:propertyvalue="getText(‘login.username‘)"/><inputname="username"type="text"/><br/>

<s:propertyvalue="getText(‘login.password‘)"/><inputname="password"type="password"/>

<inputtype="submit"value="<s:propertyvalue=‘getText("login.login")‘/>">

</form>

<s:debug></s:debug>

</body>

注意:Struts2国际化是使用<s:property value=”getText()”/>来获取信息的。

格式:

<s:propertyvalue="getText(‘login.title‘,defaultValue)"/>

其中:getText()是ActionSuppot类中的方法。因为<s:property>标签只可以直接使用Action的方法。方法中的参数一:表示国际化资源文件中的标签,因为要求是字符串,所以使用单引号括起来。

参数二:当没有取出数据时,则使用这个默认的值,可以省略此参数。

总结:国际化资源文件建立完、使用标签取值后,其它都将由Struts2来完成。

2、 Package级别

Package级别的只是将国际化资源文件建立在package(包)下,要求资源文件名前缀同包名就可以了。

其它的使用同Action级别的一样。

例如:如果在com.wjt276.bbs2009.action包下建立国际化资源文件,则文件名必须以package开头

package_en_US.properties 及 package_zh_CN.properties

总结:1、包级别的资源文件名,必须以package开头

2、包级别的资源文件可以给此包中的所有Action类使用。

3、 Application级别

Application级别也只是资源文件存放的位置不同,相同的所使用的范围也不一样。

资源文件要求存放在classpath的根目录下。

国际化资源文件以任何名称开头都可以,只是需要在Struts2.xml配置文件中告诉Struts2资源文件是以什么开头的。

例如:现在以项目名为前缀:bbs2009

bbs2009_en_US.properties 及 bbs2009_en_US.properties

告诉Struts2资源文件是以什么开头的

<constantname="struts.custom.i18n.resources"value="bbs2009"/>

四、 资源文件中的参数处理

场景:如果一个登录系统,用户登录后页面提示“欢迎您,xxxx”,如果是英文:”Welcome,xxx”

正常应该如下处理:先取职欢迎信息 + 再显示登录的用户名。

<s:propertyvalue="getText(‘welcome.msg‘)"/><s:propertyvalue="username"/>

注意:但是这要就需要两个Struts2的标签来完成这件事。

资源文件中welcome.msg的值如下:

welcome.msg=欢迎您,或 
welcome.msg=Welcome,

我们还有别外一种方式解决它,只需要一个Struts2标签,只是加入一个参数,这个标签是<s:text>。具体方式如下:

首先是资源文件需要修改,如下

注意:需要在资源文件中使用{index}来表示传入参数是哪一个。这个index是从0开始

文件中的欢迎您,{0}Welcome,{0},如果第一个参数传入值为wjt276,那么页面将显示欢迎您,wjt276Welcome,wjt276

其次需要使用<s:text>标签是获取信息。如下:

<s:textname="welcome.msg">

<s:param
value="username"></s:param>

</s:text>

注意:<s:text>标签中的name中的值不需要单引号括起来,因为是OGNL表达式,而<s:property>标签中value=”getText(‘welcome.msg’)”中的值需要用单引号括起来。因为需要传一个字符串

五、 国际化-动态语言切换

在某些网站中,会发现页面中有国家语言的选择,如:中文、英语、日语等语言供您选择。

Struts2也可以实现这种动态语言切换的功能,方法非常的简单。

方法:只需要传入一个参数(参数名必需为request_locale),参数值为”语言_国家”(也就是资源文件的后缀,如zh_CN、en_US)就可以了。例:如果当前访问的页面为中文并且URL为

http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input

如果需要切换成英文,则只需要传入一个参数request_locale=en_US就可以了。URL如下

http://localhost:8080/struts2_3200_bbs2009_08/admin/Login-input?request_locale=en_US

这样当前进程的浏览器就可以访问这个网站的所有页面为英文,至到这个进程结束,因为Struts2向session中写入locale值

WW_TRANS_I18N_LOCALE=en_US

09
自定义拦截器

一般99.9%用不上

10
类型转换

publicclass MyPointConverterextends DefaultTypeConverter{

@Override

publicObject convertValue(Object value, Class toType) {

if(toType == Point.class) {

Point p = new Point();

String[] strs = (String[])value;

String[] xy = strs[0].split(",");

p.x = Integer.parseInt(xy[0]);

p.y = Integer.parseInt(xy[1]);

return p;

}

if(toType == String.class) {

return value.toString();

}

returnsuper.convertValue(value,
toType);

}

}

publicclass MyPointConverterextends StrutsTypeConverter{

@Override

public Object convertFromString(Map context,String[] values, Class toClass) {

Point p = new Point();

String[] strs = (String[])values;

String[] xy = strs[0].split(",");

p.x = Integer.parseInt(xy[0]);

p.y = Integer.parseInt(xy[1]);

return p;

}

@Override

publicString convertToString(Map context, Object o) {

//TODO Auto-generated method stub

return o.toString();

}

}

a)   三种注册方式:

i.      局部:XXXAction-conversion.properties

1.   p(属性名称) =  converter

ii.      全局:xwork-conversion.properties

1.   com.xxx.XXX(类名)= converter

iii.      Annotation

b)   如果遇到非常麻烦的映射转换

i.      request.setAttribute();

ii.      session

Struts2总结

1.         Action

a)         namespace(掌握)

b)         path(掌握)

c)         DMI(掌握)

d)         wildcard(掌握)

e)         接收参数(掌握前两种)

f)          访问request等(掌握Map IOC方式)

g)         简单数据验证(掌握addFieldError和<s:fieldError)

2.         Result

a)         结果类型(掌握四种,重点两种)

b)         全局结果(掌握)

c)         动态结果(了解)

3.         OGNL表达式(精通)

a)         # % $

4.         Struts标签

a)         掌握常用的

5.         声明式异常处理(了解)

6.         I18N(了解)

7.         CRUD的过程(最重要是设计与规划)(精通)

8.         Interceptor的原理(掌握)

9.         类型转换(掌握默认,了解自定义)

时间: 2024-10-03 23:06:45

struts2马士兵笔记的相关文章

马士兵hibernate(原始笔记)

马士兵hibernate(原始笔记) 课程内容 1        HelloWorld a)   Xml b)   annotation 2        Hibernate原理模拟 - 什么是O/R Mapping以及为什么要有O/R Mapping 3        常见的0/R框架(了解) 4        hibernate基础配置(重点) 5        ID生成策略(重点 AUTO) 6        Hibernate核心开发接口介绍(重点) 7        对象的三种状态(了

尚学堂马士兵Oracle教程笔记

检查Oracle安装 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba 然后,解除对scott用户的锁 alter user scott account unlock; 那么这个用户名就能使用了. (默认全局数据库名orcl) 1.select ename, sal * 12 from emp; //计算年薪 2.select 2*3 from dual;  //计算一个比较纯的数据用dual表 3.select sysdate from dual

[转载]马士兵Java视频教程 —— 学习顺序

书(Java核心编程)+视频..这样学感觉比较好.. 原文地址:-- 学习顺序" href="http://blog.sina.com.cn/s/blog_8a705bf701015lz5.html" target="_blank">马士兵Java视频教程 -- 学习顺序作者:习惯 第一部分:J2se学习视频内容包括: 尚学堂科技_马士兵_JAVA视频教程_JDK5.0_下载-安装-配置 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第01

马士兵感言 (转)

展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告走过的路,回忆起来是那么曲折,把自己的一些心得体会分享给程序员兄弟姐妹们,虽然时代在变化,但是很可能你也会走我已经做过的10年的路程,有些心得体会你可以借鉴一下,觉得说得有道理的你就接纳,觉得说得没道理的,你就抛弃,以下是我发自内心的,给大家的忠告,特别是针对那些小弟弟妹妹们. 01. 自己的户口档案.养老保险.医疗保险.住房公积金一定要保管好.由于程序员行业每年跳槽一次,我不隐瞒大家,我至少换过5个以上的单位,这期间跳

关于马士兵的java教学视频

多年前同时期的视频看过很多,马士兵,张孝祥,王勇,还有很多. 马士兵是唯一一个在当时看来讲课是让初学者明白的一个人,这里说的其它人不是不让别人明白,主要在这方面的体验比马士兵略差一点.尤其是在ppt上画程序执行时内存变化图,至今依然难以忘怀,时常有重温经典的冲动,所谓经典就是经过岁月的洗礼,他的那份醇香或价值依然吸引着你不断的回温.马士兵讲课的特点是嗓音清爽,抑扬顿挫,段子精美,技巧过硬,下手快,准,狠,思路直,快,精.虽然也有很多的人批评说,讲的有多处的错误,其它等等.关于错误我的看法:授课只

马士兵SVN.

下载 服务端:VisualSVN Server 和客户端:TortoiseSVN cmd,并cd 到 VisualSVN Server安装目录下的bin目录. 新建库: 1 svnadmin create H:\svn_pro 修改conf目录下的passwd,添加 : user=password,如 1 ### This file is an example password file for svnserve. 2 ### Its format is similar to that of s

局域网聊天Chat(马士兵视频改进版)

Github地址: https://github.com/BenDanChen/Chat Chat 小小的聊天系统,主要是跟着网上的马士兵老师的公开视频然后再自己反思有什么地方需要改进的地方,然后大体功能完成后又按照自己的想法进行了重构,程序比较小,只有五百行左右,实现的功能如下: 局域网聊天(需要有一个服务器,是传统的BS架构的) 进行了检测避免2B恶意刷屏(记录上次发消息时间,设定最小发送消息的间隔) 支持悄悄话,即单独的发送消息给某一个用户,使用[:to who message]的命令格式

马士兵老师设计模式课程简介

设计模式学习顺序 目录如下: 第一讲:JavaSE_Path_ClassPath(缺) 第二讲:OO 思维 第三讲:抽丝剥茧策略模式,CC接口详细解析 第四讲:Iterator-遍历容器的精灵 第五讲:工厂系列-对象生产过程自定义 第六讲:动态代理-解析Spring的AOP 更新 第七讲:ChainOfResponsibility-解析Filter和Interceptor02 第二段由于粗心,设置错误,没有开麦克风,故没有声音,很是抱歉 具体学习顺序: 设计模式系列 尚学堂科技_马士兵_设计模式

Struts2权威指南笔记

1.mvc特点包括: ① 多个视图可以对应一个模型 ② 模型返回的数据与显示逻辑分离 ③ 应用层被分隔为三层,降低了各层之间的耦合,提供了应用的可扩展性 ④ 控制层的概念也很有效,由于它把不通的模型和不同的视图组合在一起,完成不同的请求 ⑤ Mvc更符合软件工程化管理的精神 2.Struts2框架的大致处理流程: ① 浏览器发送请求,如请求/mypage.action ② 核心控制器FilterDispatcher根据请求决定调用合适的Action ③ Webwork的拦截器链自动对请求应用通用