struts2讲义----二
Struts的namespace
示例工程Struts2_0200_Namespace
Struts.xml
<struts> <constant name="struts.devMode" value="true" /> <package name="front" extends="struts-default" namespace"/front"> <action name="index"> <result>/Namespace.jsp</result> </action> </package> <package name="main" extends="struts-default" namespace=""> <action name="index"> <result>/Namespace.jsp</result> </action> </package> </struts>
Struts自定义具体视图的返回
示例工程Struts2_0300_Action
修改jsp模板字符编码:windows-preferences- JSP 修改编码为UTF-8即可
IndexAction1.java
public class IndexAction1 { public String execute() { return "success"; } } IndexAction2.java public class IndexAction2 implements Action { public String execute() { return "success"; } }
真正企业开发只用这第三种!另外两种忘记!
IndexAction3.java
public class IndexAction3 extends ActionSupport { public String execute() { return "success"; } }
<struts> <constant name="struts.devMode" value="true" /> <package name="front" extends="struts-default" namespace="/"> <action name="index" class="com.bjsxt.struts2.front.action.IndexAction1> <result name="success">/ActionIntroduction.jsp</result> </action> </package> </struts>
具体视图的返回可以由用户自己定义的Action来决定
具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
具体Action的实现可以是一个普通的java类,里面有public String execute方法即可
或者实现Action接口
不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法
如果不配置class属性,默认执行xwork框架的ActionSupport这个action,这个action就有execute这个方法,return success。
Struts路径问题
示例工程:Struts2_0400_Path
struts2中的路径问题是根据action的路径而不是jsp路径来确定,所以尽量不要使用相对路径。
虽然可以用redirect方式解决,但redirect方式并非必要。
解决办法非常简单,统一使用绝对路径。
(在jsp中用request.getContextRoot方式来拿到webapp的路径)
或者使用myeclipse经常用的,指定basePath
先点击链接http://localhost:8080/Struts2_0400_Path/path/path.action 跳转到path.jsp 页面
在path.jsp页面上有链接<a href="index.jsp">index.jsp</a>虽然在webRoot上面index.jsp和
path.jsp同级,但是点击index.jsp却跳到http://localhost:8080/Struts2_0400_Path/path/index.jsp
如果改成<a href="/index.jsp">index.jsp</a>跳到http://localhost:8080/index.jsp
因为JSP中“/”代表整个站点的根路径而不是应用的根路径。
解决方案是:永远使用绝对路径。
<% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%> <base href="<%=basePath%>" /> request.getContextPath()会拿到webapplication的名称:Struts2_0400_Path request.getScheme()拿到“http”字符串 request.getServerName()拿到“localhost” request.getServerPort()拿到“8080”
动态方法调用
<body>
Action执行的时候并不一定要执行execute方法
可以在配置文件中配置Action的时候用method=来指定执行哪个方法
也可以在url地址中动态指定(动态方法调用DMI)(推荐)
<a href="<%=context %>/user/userAdd">添加用户</a>
<a href="<%=context %>/user/user!add">添加用户</a>
前者会产生太多的action,所以不推荐使用
<struts> <constant name="struts.devMode" value="true" /> <package name="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> <action name="user" class="com.bjsxt.struts2.user.action.UserAction"> <result>/user_add_success.jsp</result> </action> </package> </struts>
Action接收参数的方式
Action有三种接收参数的方式
1. 属性接收参数
2. 用DomainModel(实体模型)接收参数
3. 用ModelDriven接收参数( 不常用 )
用Action的属性接收参数
Struts2_0700_ActionAttrParamInput
Index.jsp
<head> <base href="<%=basePath %>"/> </head>
使用action属性接收参数<a href="user/user!add?name=a&age=8">添加用户</a>
</body>
</html>
链接的意思是:执行user下面的user.action下面的add方法
怎么接受参数的呢?第一种方式.在自己的action下面定义两个属性,写好get,set方法,当new 完action的时候,会自动把这两个属性从参数里面拿过来,帮你设置好。
参数跟我们的成员变量一一对应,这时候它就会自动把我们的参数传递到我们成员变量里。这时候当我们调用add()方法时,它直接可以用了。
UserAction.java
public class UserAction extends ActionSupport {
private String name;
private int age;
public String add() {
System.out.println("name=" + name);
System.out.println("age=" + age);
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Struts.xml
<struts> <package name="user" extends="struts-default" namespace="/user"> <action name="user" class="com.bjsxt.struts2.user.action.UserAction"> <result>/user_add_success.jsp</result> </action> </package> </struts>
使用Domain Model (实体模型) 接收参数
Struts2_0800_DomainModelParamInput
<html> <body> 使用Domain Model接收参数 <a href="user/user!add?user.name=a&user.age=8">添加用户</a> </body> </html>
public class UserAction extends ActionSupport { private User user; //private UserDTO userDTO; public String add() { System.out.println("name=" + user.getName()); System.out.println("age=" + user.getAge()); return SUCCESS; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } public class User { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }
一般来说,我们输入参数不一定刚好跟我们的域模型一致,比如说:用户有name跟password两个属性,但是你输入进来的应该还有个密码确认passwordconfiguration
这时候我们要么使用属性接收,要么用DTO,或者VO
Struts2_2.1.6版本的中文问题
根据Struts文档的规定:只要在Struts.xml中配置这段话就可以解决中文乱码问题
<constant name="struts.i18n.encoding" value="GBK" />
但是2..1.6版本中这是一个Bug,没法解决中文乱码问题
解决办法是:一:升级到2.1.7之后的版本;二是:使用spring的filter,在web.xml中配置过滤
三:在web.xml中配置2.0版本的filter
<filter>
<filter-name>struts2</filter-name>
<!--<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>-->
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
Struts2文档的位置:
struts-2.1.8.1-all\struts-2.1.8.1\docs\docs
要知道Strust.xml中有哪些常量可以配置,可以进文档里面查看
例子:
struts.i18n.encoding=UTF-8 //表示默认字符集是UTF-8
struts.action.extension=action,, //后缀名可以是“action”,或者是“”空也行。
Struts模块包含
Struts.xml中:配
<include file=”login.xml”/>
相当于把文件login.xm内容l复制过来
Struts简单数据验证
示例程序:Struts2_1100_SimpleDataValiation
UserAction.java
public class UserAction extends ActionSupport {
private String name;
public String add() {
if(name == null || !name.equals("admin")) {
this.addFieldError("name", "name is error");
this.addFieldError("name", "name is too long");
return ERROR;
}
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Struts.xml
<struts> <constant name="struts.devMode" value="true" /> <package name="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> </struts>
登陆不成功的时候,该怎么样向前台传递信息呢? 这时候其实是个麻烦事,因为我们的userAction实际上是没有跟我们的Request, response属性绑在一起的;userAction访问不到我们的Request, response,ServletContext,这些都没有,在Struts2里面是采用另外一种机制。
This.addFieldError(“name”,”name is error”);
添加对于属性校验的错误信息的,错误信息的名字一般也是我们的属性名字叫做name,那么这个属性出错,后面是这个错误的具体信息:name is error!
user_add_error.jsp
<body> User Add Error! <s:fielderror fieldName="name" theme="simple"/> <br /> <s:property value="errors.name[0]"/> <s:debug></s:debug> </body>
这里调用addFieldError()之后在前面如何把它拿出来?
在这里我们用到struts2的标签
<s:fielderror fieldname=”name” theme=”simple”>
调用标签库的时候,必须这么写:
<%@taglib uri=”/struts-tags” prefix=”s”%>
Struts的标签定义是位于
如果我们去看源码的话会看到它把我们的错误信息封装成:
<url class=”errorMassage”>
<li><span>name is error!</span></li>
</url>
指定成CSS修饰,这样就给我们带来不便,这是Struts2设计不太好的地方。所以Struts2展现的标签在企业开发中应用得不多,因为它都是强制要求你必须按照它的命名规则来去定义它的各种各样的展现。
那我们应该怎么样把我们的字符串拿出来?引出下一个标签,这个标签以后会很常用:
<s:debug></s:debug>
当你写了这个标签之后在页面就会默认显示这个标签 [Debug]
点开[Debug]
Struts ValueStack(值栈) Debug
Value Stack Contents
首先:Struts2会把Action里面的属性挨着排给你放进Value Stack 来
专门有这个标签很常用s:property
<s:property value="errors.name[0]"/>
<s:property value="errors"/>
取到errors实际上是一个map:{name=[name is error, name is too long]}
那么我想取到map里面某一个key的内容:
<s:property value="errors.name"/>
[name is error, name is too long]
而这时候实际上value是一个数组,所以我要想去数组的第一项
<s:property value="errors.name[0]"/>
name is error