-------------------搭建struts2的开发环境-------------
1.需要jar包
struts2-core-2.x.x.jar:struts2框架的核心库
work-2.x.x.jar: xwork库类,struts2在其上构建
ognl-2.6.x.jar: 对象图导航语言,通过其读写对象的属性
freemarker-2.3.x.jar U标签的模板使用freemarker编写
commons-logging-1.1.x.jar: 支持log4J和jdk1.4+的日记记录
commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后必须加入此文件。
2. struts.xml 放SRC目录下
<?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>
</struts>
3. web.xml中加入filter配置
<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>
-------------------启动struts项目----------------
1.在struts.xml中插入
//<constant name="struts.action.extension" value="do,action"/> 定义浏览器后缀为do,action的时候,进图struts框架进行处理。不定义默认无或者action
//<constant name="struts.i18n.encoding" value="UTF-8"/> 指定编码,用于httpservletrequest的setcharacterencoding的方法
//<constant name="struts.serve.static.browserCache" value="flase"/> 设置浏览器是否缓存静态内容,默认为true,开发阶段最好关闭
//<constant name="struts.configuration.xml.reload" value="true"/> 当struts配置文件修改后是否自动重新加载,默认为false,开发阶段最好打开
//<constant name="struts.devMode" value="true"/> 开发模式下使用,可以打印更详细的错误信息
//<constant name="struts.objectFactory" value="spring"/> 与spring集成时,指定由spring负责action对象的创建
//<constant name="struts.enable.DynamicMethodlnvocation" value="false"/> 是否支持动态方法调用,默认true。
//<constant name="struts.multipart.maxSize" value="10701096"/> 页面上传总文件大小的设置
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="zz.hello" method="execute" >
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
</package>
注释:
package name:随便取,但是要唯一。
namespace : 随便取,但是要唯一。
extends: 固定struts-default。
action: 可以配置多个,每个表示一个struts
name: 随便取
class: 包名+类名
method: 方法名
2.实现类:(JSP中可以通过${}获取类中message信息)
public class hello {
private String msg;
public String getMessage() {
return msg;
}
public String execute(){
msg = "我的第一个struts2应用";
return "success";
}
}
方法:<result type=“redirect”>/WEB-INF/NewFile.jsp</result> 重定向到另外一个页面 链接后面可以跟上?username=*** 等属性。
<result type=“redirectAction”>action名字</result> 重定向到另外一个action
<result type=“redirect”> 重定向到另外一个package的一个action
<param name ="actionName">action名字</param>
<param name ="namespace">package namespace名</param>
</result>
<action name="helloworld" class="zz.hello" method="execute" > 属性注入,在newfile。jsp中显示 /images 。 在类中新建savepath方法,set/get。
<param name="savepath">/images</param>
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
-----通配符调用 在action名字后面加*号(可以加多个),然后在链接处helloword后输入什么,就放回什么方法({1}), 也可以用{1}表示类和返回的jsp名字
<action name="helloworld*" class="zz.hello" method="{1}" >
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
-----类型转换器(局部) 用来转换set接收的数据格式转换
写一个类继承 DefaultTypeConverter,重写public Object convertValue(Map<String, Object> context, Object value, Class toType) 方法。重写完之后在action包下新建一个文件
命名为 action类名-conversion.properties。 里面写上需要接受的 参数名字=带包名的转换器类名 例如birthday=cn.itcast.type.converter.DateTypeConverter
(全局) 改为在Src目录下新建 xwork-conversion.properties 里面写上需要接受的 类名=带包名的转换器类名 例如java.util.Date=cn.itcast.type.converter.DateTypeConverter
以下用时间转换为例
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
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) {}
return null;
}
---------获取ServletContext session 或者 request
1.纯粹给他们三个赋值或者查询
public String execute(){
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app
ctx.getSession().put("ses", "session范围");//往session里放入ses
ctx.put("req", "request范围");//往request里放入req
ctx.put("names", Arrays.asList("老张", "老黎", "老方"));
return "message";
}
2.获取他们三个
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("req", "请求范围属性");
request.getSession().setAttribute("ses", "会话范围属性");
servletContext.setAttribute("app", "应用范围属性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
--------实现文件上传
导包 commons-io-1.3.2.jar,FileUtils需要
<form action="${pageContext.request.contextPath}/control/employee/list_execute.action" enctype="multipart/form-data" method="post">
文件1:<input type="file" name="image"><br/>
文件2:<input type="file" name="image"><br/>
文件3:<input type="file" name="image"><br/>
<input type="submit" value="上传"/>
</form>
然后在action类里
private File[] image; //文件,如果单个文件可以去掉【】。
private String[] imageFileName; //文件名,如果单个文件可以去掉【】。
要调用的类
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
System.out.println(realpath); //打印路径,可以不要
if(image!=null){
File savedir = new File(realpath);
if(!savedir.exists()) savedir.mkdirs();
for(int i = 0 ; i<image.length ; i++){
File savefile = new File(savedir, imageFileName[i]);
FileUtils.copyFile(image[i], savefile);
}
ActionContext.getContext().put("message", "上传成功");
}
return "success";
------定义拦截器
写一个类实现Interceptor,在intercert方法中写出条件:
Object user = ActionContext.getContext().getSession().get("user");
if(user!=null) return invocation.invoke(); //如果user不为null,代表用户已经登录,允许执行action中的方法
ActionContext.getContext().put("message", "你没有权限执行该操作");
return "success";
配置文件
<package name="employee" namespace="/control/employee" extends="struts-default">
<interceptors>
<interceptor name="permission" class="cn.itcast.interceptor.PermissionInterceptor"/> //设置拦截器名字和类
<interceptor-stack name="permissionStack"> //设置拦截器站,struts默认拦截在前,自定义在后
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="permission" />
</interceptor-stack>
</interceptors>
//<default-interceptor-ref name="permissionStack" /> //默认这个包的拦截器,只能定义一个 //包里所有action使用拦截器
<global-results> //全局返回到什么视图,可以放到单独action里
<result name="success">/WEB-INF/page/message.jsp</result>
</global-results>
<action name="list_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
<interceptor-ref name="permissionStack" /> //本action采用拦截器站
</action>
</package>
--------对action指定方法进行校验。
第一种:代码校验
1.action类继承ActionSupport重写validate方法:
public void validate() { //会对action中的所有方法校验
// public void validateUpdate() {//会对update()方法校验,第一个字母大写
if(this.username==null || "".equals(this.username.trim())){
this.addFieldError("username", "用户名不能为空");
}
if(this.mobile==null || "".equals(this.mobile.trim())){
this.addFieldError("mobile", "手机号不能为空"); //如果包含FieldError信息,将会转发到input的result里
}else{
if(!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()){
this.addFieldError("mobile", "手机号格式不正确");
}
}
}
2.在配置文件新建result,在其转发的页面,可以用标签 <%@ taglib uri="/struts-tags" prefix="s"%>。 用法: <s:fielderror/>,显示错误信息。
第二种:XML配置文件校验
在action文件包下新建XML文件。命名:action类名-validation.xml,如果只要单个action,取名:action类名-action名字-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="username">
<field-validator type="requiredstring"> //校验器,有 email常用校验器,检验邮箱格式。
<param name="trim">true</param> //去除两边空格,默认为true
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手机号不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
</field>
</validators>
---------OGNL表达式 --jstl+el
在action里创建的东西,都可以用S标签或者$表达式表示出来。
当action只是把一个值存在get方法里面,那么这个值被放到context的栈顶对象,也就是OGNLvaluestack里,可以直接用$表达式在jsp页面显示。也可以用标签<s:property value="值"/>
如果值被存在session,request或者application、parameters里,则需要用标签<s:property value="#request.值"/>
用OGNL表达式创建LIST集合:
<s:set var="list" value="{'1','2','3'}"/>
<s:iterator value="#list"> //遍历集合
<s:property/><br> //打印所有集合
</s:iterator >
用OGNL表达式创建MAP集合
<s:set var="maps" value="#{'key1':90, 'key2':35, 'key3':12}"/>
<!-- s:iterator标签在迭代集合时有个特点:会把当前迭达的对象放在值栈的栈顶 -->
<s:iterator value="#maps" >
<s:property value="key"/> = <s:property value="value"/><br>
</s:iterator>
判断:
<s:if test="'foo' not in {'xxx','bar'}">
不在
</s:if>
<s:else>
在
</s:else>
----S标签--- //在struts.xml中添加默认主题 <constant name="struts.ui.theme" value="simple" />,在生成复选框等东西时,不多生成代码
<s:set name="name" value="kk"> //给定一个值放入OGN context
<s:property value="#name"/> //打印
<s:url action="hellword_add" namespace="/test"><s:param name="personid" value="#值"></s:url> //生成路径,如果value中值作为普通值打印,可以用%{#OGN}来表示
<s:checkboxlist name="list" list="{'java','Net','ror'}" value ="{'java','Net'}"/> //复选框,一开始默认标记java,net
<s:checkboxlist name="map" list="{1:'java',2:'Net',3:'ror'}" listKey="key" listvalue="value" value ="{1,2,3}"/> //map复选框,默认选中全部
//如要生成单选框,把checkboxlist改成radio即可
<s:form action="action名字" namespace="action里的namespace" method="post"> //S标签的form表单提交
姓名:<s:textfield name="name"/>
<input type="sumbit" value="发送"/>
</s:form>
--------防止表单重复提交
第一步:在表单中加入<s:token/>
<s:token/><s:submit/>
第二部:在struts.xml中action配置 拦截器<interceptor-ref name="token"/> //前最好加上默认拦截器,<interceptor-ref name="defaultStack"/>
配置一个result <result name="invalid.token">/index.jsp</result> //一旦重复提交会跳转到这个地址
三.为应用指定多个struts配置文件
<struts>
<include file ="struts-user.xml"/>
<include file ="struts-order.xml"/>
</struts>
1.需要jar包
struts2-core-2.x.x.jar:struts2框架的核心库
work-2.x.x.jar: xwork库类,struts2在其上构建
ognl-2.6.x.jar: 对象图导航语言,通过其读写对象的属性
freemarker-2.3.x.jar U标签的模板使用freemarker编写
commons-logging-1.1.x.jar: 支持log4J和jdk1.4+的日记记录
commons-fileupload-1.2.1.jar 文件上传组件,2.1.6版本后必须加入此文件。
2. struts.xml 放SRC目录下
<?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>
</struts>
3. web.xml中加入filter配置
<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>
-------------------启动struts项目----------------
1.在struts.xml中插入
//<constant name="struts.action.extension" value="do,action"/> 定义浏览器后缀为do,action的时候,进图struts框架进行处理。不定义默认无或者action
//<constant name="struts.i18n.encoding" value="UTF-8"/> 指定编码,用于httpservletrequest的setcharacterencoding的方法
//<constant name="struts.serve.static.browserCache" value="flase"/> 设置浏览器是否缓存静态内容,默认为true,开发阶段最好关闭
//<constant name="struts.configuration.xml.reload" value="true"/> 当struts配置文件修改后是否自动重新加载,默认为false,开发阶段最好打开
//<constant name="struts.devMode" value="true"/> 开发模式下使用,可以打印更详细的错误信息
//<constant name="struts.objectFactory" value="spring"/> 与spring集成时,指定由spring负责action对象的创建
//<constant name="struts.enable.DynamicMethodlnvocation" value="false"/> 是否支持动态方法调用,默认true。
//<constant name="struts.multipart.maxSize" value="10701096"/> 页面上传总文件大小的设置
<package name="itcast" namespace="/test" extends="struts-default">
<action name="helloworld" class="zz.hello" method="execute" >
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
</package>
注释:
package name:随便取,但是要唯一。
namespace : 随便取,但是要唯一。
extends: 固定struts-default。
action: 可以配置多个,每个表示一个struts
name: 随便取
class: 包名+类名
method: 方法名
2.实现类:(JSP中可以通过${}获取类中message信息)
public class hello {
private String msg;
public String getMessage() {
return msg;
}
public String execute(){
msg = "我的第一个struts2应用";
return "success";
}
}
方法:<result type=“redirect”>/WEB-INF/NewFile.jsp</result> 重定向到另外一个页面 链接后面可以跟上?username=*** 等属性。
<result type=“redirectAction”>action名字</result> 重定向到另外一个action
<result type=“redirect”> 重定向到另外一个package的一个action
<param name ="actionName">action名字</param>
<param name ="namespace">package namespace名</param>
</result>
<action name="helloworld" class="zz.hello" method="execute" > 属性注入,在newfile。jsp中显示 /images 。 在类中新建savepath方法,set/get。
<param name="savepath">/images</param>
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
-----通配符调用 在action名字后面加*号(可以加多个),然后在链接处helloword后输入什么,就放回什么方法({1}), 也可以用{1}表示类和返回的jsp名字
<action name="helloworld*" class="zz.hello" method="{1}" >
<result name="success">/WEB-INF/NewFile.jsp</result>
</action>
-----类型转换器(局部) 用来转换set接收的数据格式转换
写一个类继承 DefaultTypeConverter,重写public Object convertValue(Map<String, Object> context, Object value, Class toType) 方法。重写完之后在action包下新建一个文件
命名为 action类名-conversion.properties。 里面写上需要接受的 参数名字=带包名的转换器类名 例如birthday=cn.itcast.type.converter.DateTypeConverter
(全局) 改为在Src目录下新建 xwork-conversion.properties 里面写上需要接受的 类名=带包名的转换器类名 例如java.util.Date=cn.itcast.type.converter.DateTypeConverter
以下用时间转换为例
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
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) {}
return null;
}
---------获取ServletContext session 或者 request
1.纯粹给他们三个赋值或者查询
public String execute(){
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app
ctx.getSession().put("ses", "session范围");//往session里放入ses
ctx.put("req", "request范围");//往request里放入req
ctx.put("names", Arrays.asList("老张", "老黎", "老方"));
return "message";
}
2.获取他们三个
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("req", "请求范围属性");
request.getSession().setAttribute("ses", "会话范围属性");
servletContext.setAttribute("app", "应用范围属性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
--------实现文件上传
导包 commons-io-1.3.2.jar,FileUtils需要
<form action="${pageContext.request.contextPath}/control/employee/list_execute.action" enctype="multipart/form-data" method="post">
文件1:<input type="file" name="image"><br/>
文件2:<input type="file" name="image"><br/>
文件3:<input type="file" name="image"><br/>
<input type="submit" value="上传"/>
</form>
然后在action类里
private File[] image; //文件,如果单个文件可以去掉【】。
private String[] imageFileName; //文件名,如果单个文件可以去掉【】。
要调用的类
String realpath = ServletActionContext.getServletContext().getRealPath("/images");
System.out.println(realpath); //打印路径,可以不要
if(image!=null){
File savedir = new File(realpath);
if(!savedir.exists()) savedir.mkdirs();
for(int i = 0 ; i<image.length ; i++){
File savefile = new File(savedir, imageFileName[i]);
FileUtils.copyFile(image[i], savefile);
}
ActionContext.getContext().put("message", "上传成功");
}
return "success";
------定义拦截器
写一个类实现Interceptor,在intercert方法中写出条件:
Object user = ActionContext.getContext().getSession().get("user");
if(user!=null) return invocation.invoke(); //如果user不为null,代表用户已经登录,允许执行action中的方法
ActionContext.getContext().put("message", "你没有权限执行该操作");
return "success";
配置文件
<package name="employee" namespace="/control/employee" extends="struts-default">
<interceptors>
<interceptor name="permission" class="cn.itcast.interceptor.PermissionInterceptor"/> //设置拦截器名字和类
<interceptor-stack name="permissionStack"> //设置拦截器站,struts默认拦截在前,自定义在后
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="permission" />
</interceptor-stack>
</interceptors>
//<default-interceptor-ref name="permissionStack" /> //默认这个包的拦截器,只能定义一个 //包里所有action使用拦截器
<global-results> //全局返回到什么视图,可以放到单独action里
<result name="success">/WEB-INF/page/message.jsp</result>
</global-results>
<action name="list_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
<interceptor-ref name="permissionStack" /> //本action采用拦截器站
</action>
</package>
--------对action指定方法进行校验。
第一种:代码校验
1.action类继承ActionSupport重写validate方法:
public void validate() { //会对action中的所有方法校验
// public void validateUpdate() {//会对update()方法校验,第一个字母大写
if(this.username==null || "".equals(this.username.trim())){
this.addFieldError("username", "用户名不能为空");
}
if(this.mobile==null || "".equals(this.mobile.trim())){
this.addFieldError("mobile", "手机号不能为空"); //如果包含FieldError信息,将会转发到input的result里
}else{
if(!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()){
this.addFieldError("mobile", "手机号格式不正确");
}
}
}
2.在配置文件新建result,在其转发的页面,可以用标签 <%@ taglib uri="/struts-tags" prefix="s"%>。 用法: <s:fielderror/>,显示错误信息。
第二种:XML配置文件校验
在action文件包下新建XML文件。命名:action类名-validation.xml,如果只要单个action,取名:action类名-action名字-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="username">
<field-validator type="requiredstring"> //校验器,有 email常用校验器,检验邮箱格式。
<param name="trim">true</param> //去除两边空格,默认为true
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手机号不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
</field>
</validators>
---------OGNL表达式 --jstl+el
在action里创建的东西,都可以用S标签或者$表达式表示出来。
当action只是把一个值存在get方法里面,那么这个值被放到context的栈顶对象,也就是OGNLvaluestack里,可以直接用$表达式在jsp页面显示。也可以用标签<s:property value="值"/>
如果值被存在session,request或者application、parameters里,则需要用标签<s:property value="#request.值"/>
用OGNL表达式创建LIST集合:
<s:set var="list" value="{'1','2','3'}"/>
<s:iterator value="#list"> //遍历集合
<s:property/><br> //打印所有集合
</s:iterator >
用OGNL表达式创建MAP集合
<s:set var="maps" value="#{'key1':90, 'key2':35, 'key3':12}"/>
<!-- s:iterator标签在迭代集合时有个特点:会把当前迭达的对象放在值栈的栈顶 -->
<s:iterator value="#maps" >
<s:property value="key"/> = <s:property value="value"/><br>
</s:iterator>
判断:
<s:if test="'foo' not in {'xxx','bar'}">
不在
</s:if>
<s:else>
在
</s:else>
----S标签--- //在struts.xml中添加默认主题 <constant name="struts.ui.theme" value="simple" />,在生成复选框等东西时,不多生成代码
<s:set name="name" value="kk"> //给定一个值放入OGN context
<s:property value="#name"/> //打印
<s:url action="hellword_add" namespace="/test"><s:param name="personid" value="#值"></s:url> //生成路径,如果value中值作为普通值打印,可以用%{#OGN}来表示
<s:checkboxlist name="list" list="{'java','Net','ror'}" value ="{'java','Net'}"/> //复选框,一开始默认标记java,net
<s:checkboxlist name="map" list="{1:'java',2:'Net',3:'ror'}" listKey="key" listvalue="value" value ="{1,2,3}"/> //map复选框,默认选中全部
//如要生成单选框,把checkboxlist改成radio即可
<s:form action="action名字" namespace="action里的namespace" method="post"> //S标签的form表单提交
姓名:<s:textfield name="name"/>
<input type="sumbit" value="发送"/>
</s:form>
--------防止表单重复提交
第一步:在表单中加入<s:token/>
<s:token/><s:submit/>
第二部:在struts.xml中action配置 拦截器<interceptor-ref name="token"/> //前最好加上默认拦截器,<interceptor-ref name="defaultStack"/>
配置一个result <result name="invalid.token">/index.jsp</result> //一旦重复提交会跳转到这个地址
三.为应用指定多个struts配置文件
<struts>
<include file ="struts-user.xml"/>
<include file ="struts-order.xml"/>
</struts>