<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
/*
filter-mapping>
<struts>
<package name="default" namespace="/user" extends="struts-default">
<action name="regist" class="cn.itcast.action.RegistAction">
<result name="input">/success.jspresult>
action>
package>
struts>
访问路径 /user/regist.action
name 包名称,在struts2的配置文件文件中 包名不能重复 ,name并不是真正包名,只是为了管理Action
namespace 和 action的name属性,决定 Action的访问路径 (以/开始 )
extends 继承哪个包,通常开发中继承 struts-default 包 (struts-default包在 struts-default.xml定义 )
继承struts-default包后,可以使用 包中定义拦截器和结果类型
action元素配置默认值
package 的namespace 默认值‘’‘’
action 的class 默认值 ActionSupport 类
result 的 name 默认值 success
1) 默认Action , 解决客户端访问Action不存在的问题 ,客户端访问Action, Action找不到,默认Action 就会执行
2) 默认处理类 ,客户端访问Action,已经找到匹配元素,但是元素没有class属性,执行默认处理类
* 在struts-default.xml 配置默认处理类 ActionSupport
1) struts2 默认常量 在 default.properties 中配置
2) 开发者自定义常量
struts.xml
格式 : <constant name="struts.devMode" value="true" />
struts.properties
格式 : struts.devMode = true
web.xml
格式 :
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
param>
<param-name>struts.devModeparam-name>
<param-value>trueparam-value>
param>
filter>
3) 常用常量
----- 相当于request.setCharacterEncoding("UTF-8"); 解决post请求乱码
--- 访问struts2框架Action访问路径 扩展名 (要求)
struts.action.extension=action, 默认以.action结尾扩展名 和 不写扩展名 都会分发给 Action
false不缓存,true浏览器会缓存静态内容,产品环境设置true、开发环境设置false
提供详细报错页面,修改struts.xml后不需要重启服务器
Action可以是 POJO ((PlainOldJavaObjects)简单的Java对象) —- 不需要继承任何父类,实现任何接口
* struts2框架 读取struts.xml 获得 完整Action类名
* obj = Class.forName(“完整类名”).newInstance();
* Method m = Class.forName(“完整类名”).getMethod(“execute”); m.invoke(obj); 通过反射 执行 execute方法
编写Action 实现Action接口
Action接口中,定义默认五种 逻辑视图名称
public static final String SUCCESS = “success”; // 数据处理成功 (成功页面)
public static final String NONE = “none”; // 页面不跳转 return null; 效果一样
public static final String ERROR = “error”; // 数据处理发送错误 (错误页面)
public static final String INPUT = “input”; // 用户输入数据有误,通常用于表单数据校验 (输入页面)
public static final String LOGIN = “login”; // 主要权限认证 (登陆页面)
五种逻辑视图,解决Action处理数据后,跳转页面
编写Action 继承ActionSupport (推荐)
在Action中使用 表单校验、错误信息设置、读取国际化信息 三个功能
1) 在配置 元素时,没有指定method属性, 默认执行 Action类中 execute方法
2)使用通配符* ,简化struts.xml配置
添加客户
删除客户
struts.xml
--- {1}就是第一个* 匹配内容
访问Action中指定方法,不进行配置
1) 在工程中使用 动态方法调用 ,必须保证 struts.enable.DynamicMethodInvocation = true 常量值 为true
2) 在action的访问路径 中 使用 “!方法名”
页面
添加商品
配置
执行 ProductAction 中的 add方法
在struts2 中 Action API 已经与 Servlet API 解耦合 (没有依赖关系 )
* Servlet API 常见操作 : 表单提交请求参数获取,向request、session、application三个范围存取数据
actionContext = ActionContext.getContext();
1) actionContext.getParameters(); 获得所有请求参数Map集合
2) actionContext.put(“company”, “传智播客”); / actionContext.get(“company”) 对request范围存取数据
3) actionContext.getSession(); 获得session数据Map,对Session范围存取数据
4) actionContext.getApplication(); 获得ServletContext数据Map,对应用访问存取数据
1.要求action类必须实现提定接口。
ServletContextAware : 注入ServletContext对象
ServletRequestAware :注入 request对象
ServletResponseAware : 注入response对象
2.重定接口中的方法。
private HttpServletRequest request;
3.声明一个web对象,使用接口中的方法的参数对声明的web对象赋值.
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
ServletActionContext.getRequest() : 获得request对象 (session)
ServletActionContext.getResponse() : 获得response 对象
ServletActionContext.getServletContext() : 获得ServletContext对象
ServletActionContext.getPageContext().getSession(); //获取session等对象
页面:
用户名 "text" name="username" />
Action :
public class RegistAction1 extends ActionSupport {
private String username;
public void setUsername(String username) {
this.username = username;
}
}
页面:
用户名 "text" name="user.username" />----- 基于OGNL表达式的写法
Action:
public class RegistAction2 extends ActionSupport {
private User user;
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
页面:
用户名 "text" name="username" />
Action :
public class RegistAction3 extends ActionSupport implements ModelDriven<User> {
private User user = new User(); // 必须手动实例化
public User getModel() {
return user;
}
}
1) 封装数据到Collection 对象
页面:
产品名称 "text" name="products[0].name" />
Action :
public class ProductAction extends ActionSupport {
private List products;
public List getProducts() {
return products;
}
public void setProducts(List products) {
this.products = products;
}
}
2) 封装数据到Map 对象
页面:
产品名称 "text" name="map['one'].name" />
======= one是map的键值
Action :
public class ProductAction2 extends ActionSupport {
private Map map;
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
步骤一: 封装数据
步骤二: 实现校验Action ,必须继承ActionSupport 类
步骤三: 覆盖validate方法,完成对Action的业务方法 数据校验通过代码逻辑判断参数是否有效,如果参数非法 , this.addFieldError (ActionSupport提供)workflow拦截器 跳转回 input页面
步骤四: 在jsp中 通过 s:fieldError 显示错误信息
validate方法会对Action中所有业务方法进行校验,如果只想校验某一个方法 : validate方法名()
位置:xml文件要与action类在同一个包下
名称:action类名-validation.xml(针对某个方法效验UserAction-regist-validation.xml)
<validators>
<field name="username">
<field-validator type="requiredstring">
<message>用户名不能为空--------message>
field-validator>
<field-validator type="stringlength">
<param name="maxLength">10param>
<param name="minLength">6param>
<message>用户名必须在${minLength}-${maxLength}位之间message>
field-validator>
field>
<field name="age">
<field-validator type="int">
<param name="min">10param>
<param name="max">40param>
<message>年龄必须在${min}--${max}之间message>
field-validator>
field>
<field name="birthday">
<field-validator type="date">
<param name="min">1974-01-01param>
<param name="max">2004-12-31param>
<message>生日必须在${min}年到${max}年之间message>
field-validator>
field>
<field name="email">
<field-validator type="email">
<message>邮箱格式不正确message>
field-validator>
field>
<field name="url">
<field-validator type="url">
<message>url不能这空,类似于http://www.baidu.commessage>
field-validator>
field>
<field name="telphone">
<field-validator type="regex">
<param name="regexExpression">param>
<message>电话号码必须是135xxxxxxxxmessage>
field-validator>
field>
<field name="repassword">
<field-validator type="fieldexpression">
<param name="expression">param>
<message>两次密码输入不一致message>
field-validator>
field>
validators>
内建校验器
* required (必填校验器,要求被校验的属性值不能为null)
* requiredstring (必填字符串校验器,要求被校验的属性值不能为null,并且长度大于0,默认情况下会对字符串去前后空格)
* stringlength (字符串长度校验器,要求被校验的属性值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格)
* regex (正则表达式校验器,检查被校验的属性值是否匹配一个正则表达式,expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true)
* int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值)
* double(双精度浮点数校验器,要求field的双精度浮点数必须在指定范围内,min指定最小值,max指定最大值)
* fieldexpression (字段OGNL表达式校验器,要求field满足一个ognl表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过)
* email(邮件地址校验器,要求如果被校验的属性值非空,则必须是合法的邮件地址)
* url(网址校验器,要求如果被校验的属性值非空,则必须是合法的url地址)
* date(日期校验器,要求field的日期值必须在指定范围内,min指定最小值,max指定最大值)
Action处理请求后, 返回字符串(逻辑视图名), 需要在struts.xml 提供 元素定义结果页面
1、 局部结果页面 和 全局结果页面
<action name="result" class="cn.itcast.struts2.demo6.ResultAction">
<result name="success">/demo6/result.jspresult>
action>
<global-results>
<result name="success">/demo6/result.jspresult>
global-results>
2、 结果页面跳转类型
result标签
1.name 与action中的method的返回值匹配,进行跳转.
2.type 作用:是用于定义跳转方式
dispatcher:它代表的是请求转发,也是默认值。它一般用于从action跳转到页面。
chain:它也相当于请求转发。它一般情况下用于从一个action跳转到另一个action。
hello
redirect:它代表的是重定向 它一般用于从action跳转到页面
redirectAction: 它代表的是重定向 它一般用于从action跳转另一个action。
hello
stream:代表的是服务器端返回的是一个流,一般用于下载。
<s:fieldError/>
<s:fielderror fieldName="">展示特定名称的错误信息.
properties文件命名 : 基本名称语言(小写)国家(大写).properties
编写3个property文件
message.properties
name=tom
messages_zh_CN.properties //中国中文
name=汤姆
messages_en_US.properties //美国英文
name=tom
1.针对于action类
位置:与action类在同一个包下.
名称:ActionClassName.properties.
这个配置文件只对当前action有效。
2.针对于package下所有action
位置:在指定的包下
名称:package.properties
1.在action类中使用
前提:action类要继承ActionSupport类。
getText(String name)就可以获取配置文件中对应名称的值。
2.在validation.xml文件中使用
3.在jsp页面上使用
s:text name=”名称” 如果没有使用s:i18n name=”“来指定,会从全局配置文件中获取。
如果要从某一个配置文件中获取,通过name属性来指定, 包名.配置文件名称 .
<s:i18n name="cn.itcast.action.package">
<s:text name="nameerror"/>
s:i18n>
1.action中怎样使用
xxxx.property
msg=hello world {0}
action
this.getText("msg",new String[]{"tom"})
结果就是 hello world tom
2.jsp页面上怎样使用
xxxx.property
msg=hello world {0}
张三
结果就是 hello world 张三
struts2中在struts-default.xml文件中声明了所有的拦截器。
而struts2框架默认使用的是defaultStack这个拦截器栈。
在这个拦截器栈中使用了18个拦截器。简单说,struts2框架
在默认情况下,加载了18个拦截器。
注意:只要显示声明使用了一个拦截器。那么默认的拦截器就不在加载。
模型驱动
文件上传
参数解析封装
类型转换错误
请求参数校验
拦截跳转 input 视图
struts.xml
<interceptors>
<interceptor name="my" class="cn.itcast.intercept.MyInterceptor">
interceptor>
<interceptor name="bookInterceptor" class="cn.itcast.intercept.BookInterceptor">
<param name="includeMethods">add,update,deleteparam>
interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="bookInterceptor">interceptor-ref>
<interceptor-ref name="defaultStack" />
interceptor-stack>
interceptors>
<action name="demo1" class="cn.itcast.action.Demo1Action">
<result name="login">/login.jspresult>
<interceptor-ref name="myStack" />
action>
action
public class BookInterceptor extends MethodFilterInterceptor {
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// 1.得到session中的user
User user = (User) ServletActionContext.getRequest().getSession().getAttribute("user");
if (user == null) {
BookAction action = (BookAction) invocation.getAction(); // 得到当前拦截的action对象。
action.addActionError("权限不足,请先登录");// 存储错误信息
return Action.LOGIN;
}
return invocation.invoke();
}
}
关于valueStack内部结构详解URL
http://blog.csdn.net/qq32933432/article/details/51568939
this.addFieldError("msg", "字段错误信息");
this.addActionError("Action全局错误信息");
this.addActionMessage("Action的消息信息");
在jsp中使用 struts2提供标签 显示消息信息
<s:fielderror fieldName="msg"/>
<s:actionerror/>
<s:actionmessage/>
使用值栈
valueStack.push(products);
哪些数据默认会放入到值栈 ???
1)每次请求,访问Action对象 会被压入值栈 ——- DefaultActionInvocation 的 init方法 stack.push(action);
* Action如果想传递数据给 JSP,只要将数据保存到成员变量,并且提供get方法就可以了
2)ModelDriven 接口 有一个单独拦截器
在拦截器中 ,将model对象 压入了 值栈 stack.push(model);
* 如果Action 实现ModelDriven接口,值栈默认栈顶对象 就是model对象
1) # 的 使用
------------> ActionContext().getContext().getRequest().get("name");
#request
#session
#application
#attr
#parameters
在root中查找name属性
查询元素时,从root的栈顶元素 开始查找, 如果访问指定栈中元素
访问栈中第二个元素name属性
访问第二个元素对象
遍历集合只要name属性
value="products.{name}" var="pname">
value="#pname"/>
遍历集合只要price大于1500商品
value="products.{?#this.price>1500}" var="product">
value="#product.name"/> --- value="#product.price"/>
只显示价格大于1500 商品名称
value="products.{?#this.price>1500}.{name}" var="pname">
value="#pname"/>
经常结合 struts2 标签用来生成 select、checkbox、radio
使用#构造map集合 遍历
<s:iterator value="#{'name':'aaa','age':'20', 'hobby':'sport' }" var="entry">
key : <s:property value="#entry.key"/> , value: >
s:iterator>
2) %的使用
对于s:property标签,它的value属性会被默认做为ognl.
用法一: 结合struts2 表单使用, 通过%通知struts, %{}中内容是一个OGNL表达式,进行解析
用法二: 设置ognl表达式不解析 %{‘ognl表达式’}
3)$
的使用
用法一 :用于在国际化资源文件中,引用OGNL表达式 在properties文件 msg=欢迎您${#request.username}
在页面
* 自动将值栈的username 结合国际化配置信息显示
用法二 :在Struts 2配置文件中,引用OGNL表达式
${contentType}
{contentType} 读取值栈中contentType数据,在Action提供 getContentType 因为Action对象会被压入值栈, contentType是Action属性,从值栈获得
结论: #使用ognl表达式获取数据,% 控制ognl表达式是否解析 ,$ 用于配置文件获取值栈的数据
OGNL 在jsp 结合 struts2 标签库 使用 ,
执行 ognl表达式
调用 实例方法 : 对象.方法() —-
调用 静态方法 : @[类全名(包括包路径)]@[方法名] —
使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true
1、 在jsp 通过
生成令牌号
生成表单隐藏域
将令牌号保存到Session
2、 通过struts2 提供 tokenIntercetor 拦截器 完成请求中令牌号 和 session中令牌号 比较
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
<action name="token" class="cn.itcast.struts2.TokenAction">
<result>/index.jspresult>
<interceptor-ref name="defaultStack">interceptor-ref>
<interceptor-ref name="token">interceptor-ref>
action>
3、 当表单重复提交时,token拦截器自动跳转 result name=”invalid.token”
通过 显示错误信息
覆盖重复提交信息 struts.messages.invalid.token=您已经重复提交表单,请刷新后重试
在struts2的lib包下 struts2-json-plugin-2.3.15.1.jar。
1.
2.设置视图
这样设置后,会将valueStack栈顶数据变成json。
对于我们的程序,也就是会将action对象转换成json。
p
如果没有设置,可以理解成将整个action都转换成json的数据。也就是
在action中提供的getXxx方法,就是json中的一个属性。
如果设置了root,那么,只将指定数据转换成json.
还可以通过json插件的interceptor完成.
设置只展示products的name属性
products\[\d+\]\.name