您的位置:首页 > 编程语言 > Java开发

Struts2的一些基本用法笔记

2018-03-11 10:22 393 查看
4000

Struts2基本
——————————————————————————————————
Struts2的常量配置方法(常量默认值在struts2-core-版本号.jar下org/apache/struts/default.porperties中可找到)
1、配置struts.xml(常用)
例如在struts.xml中指定资源文件
<struts>
…..
<constant name=”struts.custom.il8n.resources”value=”Name”>
…..
</struts>
2、修改struts.properties
3、配置web.xml
 
Struts2框架有特定的加载配置常量的顺序,后加载的同名常量将被覆盖,先后顺序struts.xml >   struts.properties     >   web.xml
另外在struts.xml中可以通过<includefile=”fileName.xml”/>导入其他配置文件,这可以使struts.xml不会太庞大杂乱,能对其进行模块管理
————————————————————————————————————————————————
实现Action
Aciton是struts的核心,主要对用户请求进行逻辑处理
Action类不需要继承任何的struts基类或者实现任何接口
对请求而言,Action可以没有对应的实例变量,但需要包含变量名对应的getter/setter
但Action有一个默认的实现类ActionSupport,该类继承了Action、Validateable接口,通过继承ActionSupport会使开发更加规范和简单
同时ActionSupport类也是没有定义处理类(<class=””>)的action默认处理类
————————————————————————————————————————————————
 
访问ServletAPI
 
通过ActionContext访问Servlet API
主要通过ActionContext实现,可以通过该类的getContext()静态方法获取实例
通过该类实例可以访问/修改application、session、request范围的属性
 
这里有一个问题是一般获取表单请求参数(不是request属性)时,getParameters()的返回是一个Map(String,Parameter)类型
使用map.get(key).getValue() | getMutipleValues()才能获取请求参数值,因为参数值有可能是一个数组,因此被封装成了parameter类型
使用请求参数对应的getter可以直接获得参数值,另外,在Action中应该尽量使用ActionContext访问ServletAPI
 
ActionContext
类似的ServletAPI
Object get(Object key)
void put(String key,Object value)
Object request.getAttribute(String key)
void setAttribute(String key,Object value)
Map getParameters()
Map request.getParameterMap()
Object getSession().get(Object key)
void setSession(Map session)
Object session.getAttribute(String key)
void session.setSession(String key ,Object value)
Object getApplication().get(Object key)
void setApplication(Map application)
Object servletcontext.getAttribute(String key)
void servletcontext.setAttribute(String key ,Object value)
 
 
通过接口访问ServletAPI
主要有三个接口:
ServletContextAware、ServletRequestAware、ServletResponseAware,分别对应ServletContext、HttpServletRequest、HttpServletResponse
分别需要实现形如public void setA(A a)的方法,从传入方法的参数中就可以拿到对应实例。
 
通过ServletActionContext类静态方法访问Servlet API
getPageContext()、getRequest()    、getResponse()     、getServletContext(),分别对应PageContext、HttpServletRequest、HttpServletResponse、ServletContext
使用较通过接口访问方便,且多了一个可访问的PageContext,但这使Action与Servlet产生耦合,各有利弊
————————————————————————————————————————————————
 
 
关于struts.xml中packag 的name和namespace属性
name不代表某个包,而是代表一个action模块
namespace命名空间,代表一个处理范围
如”/aaaa”命名空间下的action只处理/aaaa/xxxx.action的请求(通过查找name=”xxxx”的Action处理),根命名空间 “/” 只处理”/xxxx.action”的请求,命名空间只处理一个级别的请求,不论自身有多少级,如:
“/aaaa/bbbb/cccc”只处理”/aaaa/bbbb/cccc/xxxx.action”
所有的请求在所属的命名空间找不到对应的action时跳转到默认空间查找
 
————————————————————————————————————————————————
 
动态调用Action方法
 
通过DMI(Dynamic Method Invocation)处理
在JavaScript脚本直接修改action参数直接指向被调用的方法

function login(){
//获取页面首个表单
form0 = document.forms[0];
//修改该表达的action参数
//指向了名为login 动作下的register方法
form0.action = "login!register";
}

 
通过配置通配符调用
在struts.xml中的<action/>标签行可以指定该Action调用的方法,格式为method=”methodName”,可以调用指定Action类下名为methodName的方法
同一个<action />下可以通过使用 通配符+{N} 定义通用处理规则:
例如:
<action name=”*_Index”class=”……..” method=”{1}”>….</action>
表示该action适用于所有形如xxxx_Index的请求,且调用指定Action类的“xxxx”方法,通配符可扩展到N个,{N}表达式也可以用在result、class参数中
 
使用动态调用应当遵循类似于异常捕捉的组织方法,name=”*”一般应当放在最后一个action中
————————————————————————————————————————————————
 
关于处理结果<result>
 
Action的处理结果<result/>
默认:<result type=”dispatcher”,name=”success”>…</result>
通常简化为<result name=”Name”>…</result>
result支持的结果类型type一共有十个,这里仅记录几个比较常用的
dispatcher: <result type=”dispatcher”>/location</result>
redirect:<result    type=”redirect”>/location</result>
redirectAction:<result    type=”redirectAction”><paramname=”actionName”>ActionName</param><paramname=”namespace”>NameSpace</param></result>
配置全局结果(以及相关内容——异常捕获):<package>
<!—配置全局处理结果-->
<global-results>
<result name=”Name”>/location</result>
</global-results>
<!—配置全局异常捕获,可以与全局处理结果一起使用,构成异常处理-->
<global-exception-mappings>
<!—exception-mapping标签也可以作action的子标签,对局部action有效-->
<exception-mapping exception=”ExeceptionName” result=”Name”/>
<exception-mappin……/>
<action>…</action>
</package>
————————————————————————————————————————————————
Struts2的输入校验
 
分为字段校验器配置方式和非字段校验器配置方式,这里使用前者
服务器端校验:
方式一:
建立validator文件,格式为ActionName-validation.xml,ActionName为对应该validator的Action,应该被保存在与该Action相同的路径下
注意,服务器端校验失败将默认返回”input”逻辑视图<validators>
<field name="name1">
<!--必填字符串校验,short-circuit="true"设置为短路校验,
该校验规则检验失败将不再检测该表单域后续校验,
实际意义为失败后只显示一个Message而不是多个-->
<field-validator type="requiredstring" short-circuit="true">
<param name="trim">true</param>
<!--Message将显示在被校验表单域的附近-->
<message>Message1</message>
</field-validator>
<!--正则表达式校验,该模式可以实现大部分校验功能-->
<field-validator type="regex">
<param name="regex"><![CDATA[(正则表达式)]]></param>
<message>Message2</message>
</field-validator>
</field>

<field name="name2">
....
</field>
</validators> -->
方式二:
通过注解校验
对需要校验的Action变量的setter方法进行注解//必填字符串校验
private String username;
@RequiredStringValidator(message="message1")
//正则表达式校验
@RegexFieldValidator(regex="正则表达式",message="message2")
public void setUsername(String username){
this.username = username;
}
方式三:
手动校验,自定义校验规则
实际上大多数的规则都能通过正则表达式校验实现,这里不做记录

客户端校验:
这里是基于Struts2的客户端校验配置,主要通过JavaScript实现
也可以通过在页面嵌入纯JavaScript实现
被校验的表单应该使用sruts2标签生成,表单头应当配置 validate=”true” ,例如:<s:form action="login" validate="true">
<s:textfield name="username" key="user"/>
<s:textfield name="password" key="pwd"/>
<s:submit value="ok"/>
</s:form>
————————————————————————————————————————————————
Struts2控制文件上传/下载
 
上传部分(基于Jakarta):
JSP表单:

应当使用Struts2的标签库
<s:form action="uploadAction" enctype="multipart/form-data">
<s:textfield name="title" label="filename"/>
<s:file name="upload" label="find in file system..."/>
<s:submit value="upload"/>

对应Action://省略package/import

public class Upload extends ActionSupport{
private static final long serialVersionUID = 3482281919022527170L;

private String title;
//一个upload表单域对应三个属性
private File upload;
private String uploadContextType;
private String uploadFileName;
//实际本地保存路径
private String savepath;
//省略一些setter/getter

@Override
public String execute() throws IOException {
FileOutputStream fos = new FileOutputStream(getSavepath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] byt = new byte[1024];
int len ;
while((len = fis.read(byt)) != -1) {
fos.write(byt,0,len);
}
fos.close();
fis.close();
return Action.SUCCESS;
}

public void setSavepath(String savepath) {
this.savepath = savepath;
}

public String getSavepath() {
//注意这里的实际保存路径
String temp = ServletActionContext.getServletContext().getRealPath(savepath);
System.out.println(temp);
return temp;
}

}
初始化Action成员变量:
<param name=”savepath”>/upload</param>
上传过滤:
方式一:
手动实现
通过初始化Action成员变量传入允许的contentType,手动重写Action类validate方法实现过滤
方式二:
拦截器实现过滤

通过配置fileUpload拦截器的allowedTypes和maximumSize实现类型和大小过滤,具体代码在后边拦截器部分给出
下载部分:
通过配置result的类型可以实现Struts2控制的下载行为:<action name="downloadAction" class="ryo.struts.download.Download">
<param name="path">/WEB-INF/image/1.jpg</param>
<!--result类型为stream-->
<result type="stream">
<param name="contentType">image/jpg</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">filename="1.jpg"</param>
<param name="bufferSize">2048</param>
</result>
<result name="login">/WEB-INF/login.jsp</result>
</action>
使用自带权限控制的Action类控制下载:package ryo.struts.download;

import java.io.InputStream;
import java.util.Map;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class Download extends ActionSupport{

private static final long serialVersionUID = -1085631150568157686L;

private String path;

@Override
public String execute() {
Map<String, Object> session = ActionContext.getContext().getSession();
String user = (String)session.get("user");
if(user!=null) {
return Action.SUCCESS;
}
return Action.LOGIN;
}

public InputStream getInputStream() {
return ServletActionContext.getServletContext().getResourceAsStream(path);
}

public String getPath() {
return path;
}

public void setPath(String path) {
this.path = path;
}

}

在welcome页面使用超链接跳转至指定的下载行为:<a href=”${pageContext.request.contextPath}/downloadAction.action}”>down</a>
这个链接将执行downloadAction,超链接格式应该为:<a href=”${pageContext.request.contextPath}/nameSpace/actionName.action}”>text</a>
 
 
————————————————————————————————————————————————
 
Struts2拦截器
 
配置拦截器:
在struts.xml中可以配置拦截器以及拦截器栈<interceptors>
<!--自定义拦截器-->
<interceptor name="interceptor1" class="ryo.sturts.interceptor.MyInterceptor">
</interceptor>
<!--自定义拦截器栈-->
<interceptor-stack name=...>
<interceptor-ref name="栈中第一个拦截器名"/>
.....
</interceptors>
<action...>
<interceptor-ref name="拦截器名或拦截器栈名">
<param name="参数名">值</param>
</interceptor-ref>
<!--需要显式调用默认拦截器栈,或者将默认拦截器加入到自定义拦截器栈中-->
<interceptor-ref name="defaultStack"/>
</action>


例如,使用自带的文件上传拦截器实现文件上传拦截:失败将返回input逻辑视图
<action...>
<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/png,image/jpg,image/jpeg</param>
<param name="maximumSize">2048</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
...
...
</action>


配置默认拦截器:
default-interceptor-ref作为package子标签进行配置,方式大同小异,对该包下所有没有配置拦截器的action有效
自定义拦截器类:

通过实现Interceptor接口或继承AbstractInterceptor开发自定义拦截器 自定义拦截器:package ryo.struts.interceptor;

import java.util.Map;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor{
private static final long serialVersionUID = 6821994655329549436L;

@Override
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext context = ActionContext.getContext();
Map<String, Object> session = context.getSession();
System.out.println((String)session.get("user"));
if(session.get("user") != null) {
return invocation.invoke();
}
return Action.LOGIN;
}

}

struts.xml相关配置
<interceptors>

<interceptor name="authority" class="ryo.sturts.interceptor.MyInterceptor"/>

<interceptor-stack name="mystack">
<interceptor-ref name="authority"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>


<action name="uploadAction" class="ryo.struts.upload.Upload">
<interceptor-ref name="mystack"/>
<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/png,image/jpg,image/jpeg</param>
<param name="maximumSize">125000</param>
</interceptor-ref>
<param name="savepath">/upload</param>
<result name="success">/WEB-INF/welcome.jsp</result>
<result name="input">/WEB-INF/upload.jsp</result>
<result name="login">/WEB-INF/login.jsp</result>
</action>
但我在测试中发现该自定义的权限控制拦截器并没有起效,甚至程序根本就没有跑进该拦截器,但后续的文件上传拦截器却有效这个问题膈应了一整天了,换成Interceptor接口实现的方式也没用,对比了网上很多的demo以及手上的资料还是没能发现哪里不对…
 
 
 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: