十一、 简单数据验证
使用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.如下:
<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>
根据配置文件可以得知action所对应的类为com.bjsxt.struts2.user.action.UserAction,并且具有两个结果集(success和error).代码如下:
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
private String name;
public String add() {
if(name == null || !name.equals("admin")) {
//addFieldError 添加错误信息,可以在客户端访问到。
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;
}
}
根据Action类代码,可以看到Action是利用Action的成员属性(name)来接受参数值,并且使用this.addFieldError()方法添加错误信息,以便前台可以访问到。
this.addFieldError(name, errorMessage);
注:此方法是使用继承了ActionSupport父类的
name:可以是傻的属性名称,但一般建议使用哪个成员属性出题了,就用那个。当前是因为name没有通过验证,所以使用name
errorMessage:添加的信息
在客户端获取这些信息,如下:
<body>
User Add Error!
<s:fielderror fieldName="name" theme="simple"/>
<br />
<s:property value="errors.name"/>
<s:debug></s:debug>
</body>
注:使用<s:fielderror>标题,需要使用<%@taglib>命令引用Struts2的标签库如下:
<%@taglib uri="/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:property value="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
一般在Action类的构造方法、或execute()方法中获取。
public class LoginAction1 extends ActionSupport {
private Map request;
private Map session;
private Map application;
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");
return SUCCESS;
}
}
然后在Jsp页面中获取相关web元素。
<body>
User Login Success!
<br />
<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />
<s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
<s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />
<s:property value="#attr.a1"/><br />
<s:property value="#attr.s1"/><br />
<s:property value="#attr.r1"/><br />
<s:debug></s:debug>
<br />
</body>
注:因为request、session、application对象Struts2将在放入到Action Context中,
因此需要使用#key来访问对象们。
后面的是java脚本代码的访问方式。
让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;
public class LoginAction2 extends ActionSupport implements 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");
return SUCCESS;
}
@Override
public void setRequest(Map<String, Object> request) {
this.request = request;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
@Override
public void setApplication(Map<String, Object> application) {
this.application = application;
}
}
在视图(JSP)页面中获取相关对象,同方式一。
获取是的HttpServletRequest/HttpSession/ServletContext
public class LoginAction3 extends ActionSupport {
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
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");
return SUCCESS;
}
}
首先需要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;
public class LoginAction4 extends ActionSupport implements ServletRequestAware {
private HttpServletRequest request;
private HttpSession session;
private ServletContext application;
public String execute() {
request.setAttribute("r1", "r1");
session.setAttribute("s1", "s1");
application.setAttribute("a1", "a1");
return SUCCESS;
}
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
this.session = request.getSession();
this.application = session.getServletContext();
}
}
十三、 Struts2配置文件模块化包含(include)
<include>标签
当Struts配置文件比较多,需要模块化划分或分开成为多个配置文件时,这个功能比较好。
则需要使用<include>标签把其它的配置文件引入到Struts.xml配置文件中就可以了。
例如:有一个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{1}">
<result>/user_login_success.jsp</result>
</action>
</package>
</struts>
则需要在struts.xml文件中使用<include>标签将其引入就可以了。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.devMode" value="true" />
<include file="login.xml" />
</struts>
十四、 默认的Action
当用户访问的namespace下一个不存在的Action,则会将使用默认的Action。
使用<default-action-ref name=”name”>标签 其中 name属性指向下面已经定义的Action名称了。
<struts>
<constant name="struts.devMode" value="true" />
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index"></default-action-ref>
<action name="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、 包含文件配置