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

Struts2-部分知识点概述与解释

2016-09-22 19:02 246 查看
Struts2
(一)

webWork

Framework:基于请求响应(Request-Response)模式的应用。

表现逻辑结构:

1 控制器(Controll)-控制整个Framework中各个组件的协调工作。

2 业务逻辑层(Business Logic)-概念与几个能够提供服务的基础组件(真正的实现需要在Framework之上进行再次扩展)。

3 数据逻辑层(Data Logic)-包括数据逻辑与数据访问接口。

意义:可重用 模块化设计

灵活性与可配置性

ognl--表达式语言

(二)

开发步骤:详见-点击打开链接

1 新建工程

2 导入包

3 新建jsp文件

4 配置web.xml文件

5 src下新建struts.xml文件并配置

6 新建action文件(bean)

根据tomcat启动报错加入需要需要加入jar包

javassit.jar在struts2.2之后需要加入(jboss除外,已内置)

如下语句获取request域内容(与request.getAttribute类似):

username:${requestScope.username}<br/>

password:${requestScope.password}

struts基本执行原理(找到匹配信息进行处理-*逻辑)

反射

struts.xml->extends:struts-default(自带包)继承

过滤器接管请求

每次请求都会生成一个action对象

(三)

struts2的类型转换(8种原生数据类型等常见数据类型会使用内建的类型转换器实现自动转换,但对于自定义数据则需要手动转换)

action继承自ActionSupport(提供了对struts的各种支持)

内置类型转换:点击打开链接

转换器转换(Converter):点击打开链接

类型转换

1 {类型转换器converter(继承于DefaultTypeConverter->内置于ognl)->converterValue方法

StringTokenizer(分割提取字符串)->nextToken(获取分割后字符串)

return SUCCESS;

转换处理代码(hello;word转换为两个字符串):

//使用object泛指

if(User.class==toType){

//转换(从页面向后台对象转换)

String[] str=(String[])value;//将value转换为String数组

            

String firstValue=str[0];//取出字符串

//对字符串数组进行分割

StringTokenizer st=new StringTokenizer(firstValue,";");//第一个参数为待转换的字符串 第二个参数为分隔符

            

//获取分割后字符串

String username=st.nextToken();//取出第一个

String password=st.nextToken();//取出第二个

            

//生成user对象

User user=new User();

user.setUsername(username);//将转换后的字符串放入usre对象中

user.setPassword(password);;

return user;

在action包中新建UserAction-conversion.properties配置文件指定转换器

自定义的类型转换需要提供3个信息:action的名字、action中待转换的属性名以及该和属性对应的类型转换器(properties文件 converter文件)action名字通过属性文件名获得、action中待转换的属性名通过属性文件中的key;来获得,该属性的类型转换器通过key对应的类型转换器名字value获得->properties

}

jsp应用标签库:<%@ taglib prefix="s" uri="/struts-tags"%>

2 Struts2自带的类型转换(TypeConverter->继承defaultTypeConverter):

public class UserConverter2 extends StrutsTypeConverter {

@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
// TODO Auto-generated method stub
//从页面向后台转换
User user=new User();
String value=values[0];//提取字符串

StringTokenizer st=new StringTokenizer(";");//分割
user.setUsername(st.nextToken());
user.setPassword(st.nextToken());
return user;
}

@Override
public String convertToString(Map context, Object o) {
// TODO Auto-generated method stub
User user=(User)o;

String username=user.getUsername();
String password=user.getPassword();

String userInfo="username:"+username+"-password:"+password;
return userInfo;
}
}

/struts2-1/src/com/sw/struts2/UserAction-conversion.properties(配置文件-指定转换文件):

#user=com.sw.converter.UserConverter(#为注释)

3 批量转换数据类型(采用集合)->集合转换

代码:

(1)从页面到后台

@Override
public Object convertFromString(Map context, String[] values, Class toClass) {
// TODO Auto-generated method stub
//批处理
List<User> list=new ArrayList<User>();

for(String value:values){//遍历
StringTokenizer st=new StringTokenizer(value,";");
User user=new User();

user.setUsername(st.nextToken());
user.setPassword(st.nextToken());//装载

list.add(user);
}
return list;
}

(2)从后台到页面

@Override
public String convertToString(Map context, Object o) {
// TODO Auto-generated method stub
List<User> list=(List<User>)o;//强制转换

StringBuffer buffer=new StringBuffer();//拼接字符串(集合内所有字符串)
for(User user:list){//遍历
String username=user.getUsername();
String password=user.getPassword();
//拼接
buffer.append("username:").append(username).append("-passwprd:").append(password);
}
return buffer.toString();
}

4 开发时类型转换(全局转换)

xwork-conversion.properties文件:

待转换的类=转换器的名字

例如:

com.sw.bean.User=com.sw.converter.UserConverter3

excute类似于doget()与dopost()

自定义execute(除方法名外其他需一致)->不建议重写->会使代码混乱

(四)

输入校验->(客户端检验、服务器校验)

1 客户端验证

标签库:property(指定显示某个属性)

(1)validate()->验证->重写方法->在execute之前执行

<s:actionerror/>---显示action错误

Calendar->比较时间

错误提示:

this.addActionError("username size:4-6!");//放置action级别错误信息

this.addFieldError(username, "username size:4-6");//属性级别的错误消息

struts2自带标签(少用)

theme->自定义form主题

流程:

(1)首先进行类型转换(可内部转换)

(2)输入校验(执行validate方法)

(3)如上述过程中出现任何错误(类型转化错误、输入校验错误)都不会再去执行execute方法,页面转向struts.xml中该action的名为input所对应的页面

this.getFieldErrors().clear();//清空错误信息

this.getActionErrors().clear();

a 当调用getAction()方法返回Action级别的错误信息列表时,返回的实际上是集合的一个副本而不是集合本身,因此对集合副本调用clear()方法清除的依旧是副本中的元素,而并不是原集合中的元素,此时集合中的内容没有受到任何的影响。即Action级别的错误列表对于开发者来说是只读的。

b FiledError级别的错误信息底层是用LinkedHashMap实现的,该Map的key是String类型,value是List<String>类型,这就是表示一个Filed Name可以对应多条错误信息,这些错误信息都放置在List<String>集合当中。

hasActionErrors()->bool类型,检测是否有错误信息

hasFilederrors()->

ActionSupport类的addActionError()方法:

首先创建一个ArrayList对象,然后将ArrayList放到对象中

Action中自定义方法的输入校验:对于通过action的method属性所指定的自定义方法,其对应的自定义输入检验方法名为validateMyexcute(假设自定义方法名为MyExecute)->validateMyexecute优于validate

MyExecute优于execute

自定义方法先于execute方法执行。

自定义错误提示信息(对应包下action同级目录):

新建配置文件:Action名字.properties:invalid.fieldvalue.出错变量=age invalid!

struts校验框架(有效的xml文件->action同级目录下)

RegisterAction-validation.xml

可分为字段优先校验器与校验器优先校验器

(1)字段优先校验器(包含Filed)

<validators>根元素
.xml文件:
<validators>

<field name="username">
<field-validator type="requiredstring">
<message>UserName cant't be blank!</message>
</field-validator>
</field>

</validators>

中英文错误提示信息配置文件(key属性):

package_en_US.properties->英文

package_zh_CN.properties

i18n->Locale

国际化资源文件命名规则:package_语言名_国家名

例:package_zh_CN

package_en_US

(2)检验器优先校验器

.xml文件:

<!-- 校验器优先校验 -->
<validator>
<validator type="requiredstring">
<param name="fieldName">username</param>
<message>UaerName cant't be blank!</message>
</validator>

<validator type="stringlength">
<param name="fieldName">username</param>
<param name="minLength">4</param>
<param name="maxLength">6</param>
<message>UserName Size:${minLength}-${maxLength}</message>
</validator>
<validator>

两者可共同使用

struts校验框架执行的顺序:

(1)首先执行校验框架(xml文件)

(2)执行自定义的校验方法(validateMyExecute)

(3)执行validate方法

任何一个步骤出现错误就不会再向下执行

(五)

异常的处理(亦可处理校验)

处理:struts.xml文件中action下<exception-mapping>

全局的结果集:<global-results></global-results>

全局异常:<global-exception-mappings></global-exception-mappings>

局部总是优先于全局的。

局部:独有action共享

全局:所有action共享

(六)

业务逻辑处理

(1)创建service(interface)

(2)实现service(impelment)

(3)创建dao(有implement调用dao实现类)-可省略

(4)action中实现service对象

(七)

struts2底层应用的分层体系架构

action->service(interface与impelment)->dao(与数据库交互)

struts2的模型驱动(Model Driver)->将单个属性装为模型,调用模型,再去寻找单个属性?

属性驱动(action里边调用单个属性)

属性驱动与模型驱动的区别:

(1)属性驱动灵活,准确;模型驱动不灵活,因为很多时候,页面所提交过来的参数并不属于模型中的属性,也就是说页面所提交过来的参数与模型并不一致。

(2)模型驱动更加符合面向对象编程风格,使得我们获得的是对象而不是一个个离散的值。

小结:尽量使用属性驱动编写Action

(八)

服务器端代码的单元测试有两种模式:

(1)容器内测试(Jetty)->服务器

(2)Mock测试(模拟测试)->继承httpServletRequest、HttpSession、HttpServletResponse等servlet API

JMock、easyMock(代理机制->java动态代理)

Preparable(xwork下)接口:

让Action完成一些初始化工作,这些初始化工作是放在Preparable接口的prepare方法中完成的,该方法会在execute方法执行之前得到调用。

(九)

实际开发:

采取请求转发的方式完成表单内容的添加会造成内容的重复插入。

重定向:redirect

diapatcher

redirectAction->重定向到某个action

<result name="SUCCESS" type="redirectAction">action2</result>->重定向到action2

重定向并且传值(开发常用):

<action name="action1" class="com.sw.struts2.Action1">
<result name="SUCCESS" type="redirectAction">
<param name="actionName">action2</param>
<param name="username">${username}</param>
<param name="password">${password}</param>
<param name="usernameAndPassword">${usernameAndPassword}</param>

</result>
</action>

请求转发:type=chain

防止表单重复提交:

(1)通过重定向(redirect)

(2)通过Session Token(session令牌)->检验是否为第一次提交(与字符串匹配则是重复提交)

Token->struts.xml配置:

<action name="token" class="com.sw.struts2.TokenAction">

            <result name="SUCCESS">/tokenSuccess.jsp</result>

            <result name="invalid.token">/tokenErr.jsp</result>

<!-- 拦截器 -->

    <interceptor-ref name="token"></interceptor-ref>

    <interceptor-ref name="defaultStack"></interceptor-ref>

</action>

jsp配置:

<s:form action="token.action" theme="simple">

    username:<s:textfield name="username"></s:textfield><br/>

    password:<s:password name="password"></s:password><br/>

    <s:token></s:token>

<s:submit value="submit"></s:submit>

</s:form>

当客户端请求页面时,服务器通过token标签生成一个随机数,并且将该随机数放置到session中,然后改随机数向客户端;如果客户第一次提交,那么会将该随机数发往服务器端,服务器会接收到该随机数并且与session中所保存的的随机数进行比较,这时两者的值是相同的,服务器认为是第一次提交,并且将更新服务器的这个随机数值;如果此次重复提交,那么客户端发向服务器端的随机数还是之前那个,而服务器端的随机数已经发生变化,两者不同,服务器就认为这是重复提交,进而转向invalid.token所指向的结果页面。

(十)

拦截器(interceptor)

1 拦截器是struts2的核心,struts2的众多功能都是通过拦截器来实现的。

拦截器可拦截action

servlet过滤器?

拦截器必须是无状态的

步骤:

(1)新建包

(2)新建interceptor类,继承于interceptor

(3)写intercept方法

(4)配置struts.xml(定义拦截器):

<!-- 拦截器 -->

<interceptors>

    <interceptor name="theinterceptor" class="com.sw.TheInterceptor1">

<param name="test">swxctx</param>

</interceptor>

</interceptors>

与action配置(使用拦截器):

</result>

<interceptor-ref name="theinterceptor1"></interceptor-ref>

</action>

深入分析struts-default.xml ***

自定义拦截器以后,defaultStack将不再有用,需要自己定义

2 定义拦截器时可继承abstractInterceptor(该类实现了interceptor接口,并且对init和destory方法进行了实现),然后实现其抽象方法interceptor即可。

3 方法过滤拦截器(可以对指定方法进行拦截的拦截器)->MethodFilterInterceptor(abstract class)->可指定

includeMethods->表示需要拦截的方法:

<interceptor-ref name="theinterceptor3">    <param name="includeMethods">execute</param>

</interceptor-ref>

如上表示对execute进行拦截.

<param name="excludeMethods">myExecute</param>

表示不对myExecute拦截(拦截器不执行,并非myExecute不执行)

如果没有指定includeMethods参数,也没有指定exincludeMethods参数,那么所有的方法都会被拦截,也就是说所有的方法都被认为是includeMethods类型的。

如果仅仅指定includeMethods,那么只会拦截includeMethods中的方法,其让他的并不会受到干扰。

(十一)

PreResultlistener(继承于ActionInvocation)

进行登录处理

拦截器栈:将多个拦截器定义在一起

struts.xml可放置多个包。

可分为多个配置子文件。

(十二)

struts.xml

abstract->表示当前包为抽象的包。

abstract="true";

struts-default的包是abstract的,所以需要继承。

namespace:

路径分割、模块划分

(十三)

文件上传

1 采用servlet

遵循原则:

基本form->

<form action="fileUploadResult.jsp" method="post" enctype="multipart/form-data">
username:<input type="text" name="useranme">
file:<input type="file" name="file">
<input type="submit" value="上传">
</form>

读取:

<%
InputStream is=request.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String buffer=null;
//读取
while(null!=(buffer=br.readLine())){
out.print(buffer+"<br/>");
}
br.close();
is.close();
%>

进行文件上传是,必须将method属性设置为post,enctype属性必须设置为multipart/form-data

使用servlet需要使用apache组件,commons->FileUpload

选择多个文件:

file:<input type="file" name="file" multiple size="80"><br/>

选择文件上传界面:

<form action="UploadServlet" method="post" enctype="multipart/form-data">
username:<input type="text" name="useranme"><br/>
file:<input type="file" name="file" multiple size="80"><br/>
file2:<input type="file" name="file2">
<input type="submit" value="上传">
</form>

使用action处理:

public String execute() throws Exception {
// TODO Auto-generated method stub
//用于文件上传处理
String root=ServletActionContext.getRequest().getRealPath("/upload");//文件存储路径
InputStream is=new FileInputStream(file);//输入流
File destFile=new File(root,fileFileName);//文件
OutputStream os=new FileOutputStream(destFile);//输出流

byte[] buffer=new byte[400];
int length=0;
while((length=is.read(buffer))!=-1){
//写入
os.write(buffer, 0, length);
}
is.close();
os.close();

return "SUCCESS";
}

struts2在进行文件上传时,实际是通过两个步骤实现的:

(1)首先将客户端上传的文件保存到struts.multipart.saveDir(struts.properties)键所指定的目录中,如果该键所对应的目录不存在,那么就是保存到javax.servlet.context,tempdir环境变量所指定的目录中。

(2)Action中所?定义的File类型的成员变量file实际上指向的是临时目录中的临时文件,然后在服务器端通过IO的方式将临时文件写入到指定的服务器端目录中。

上传多个文件:

file1:<input type="file" name="file"><br/>

file2:<input type="file" name="file"><br/>

name相同。

OGNL(Object Graph Navigation Language):对象图导航语言

控制上传大小:

struts.properties:

struts.multipart.maxSize=1048576000

或者struts.xml:

<!-- 指定上传文件大小 -->

<constant name="struts.multipart.maxSize" value="1048576000"></constant>

优先级:

struts.properties>struts.xml

文件下载:

Action:

public class DownloadAction extends ActionSupport {
//文件下载
public InputStream getDownloadFile(){

return ServletActionContext.getServletContext().getResourceAsStream("/upload/Upload.txt");
}

@Override
public String execute() throws Exception {
// TODO Auto-generated method stub

return "SUCCESS";
}
}

struts.xml配置:

<!-- 10 Download -->
<action name="downloadFile" class="com.sw.struts2.DownloadAction">
<result type="stream">
<param name="contentDisposition">attachment;filename="Upload.txt"</param>
<param name="inputName">downloadFile</param>
</result>
</action>\


解决文件名乱码问题:

//中文乱码处理(文件名为中文)            this.filename=new String(this.filename.getBytes("gbk"),"8859_1");

(十四)

注解

stryts2可以使用struts2-convention-plugin-2.3.30.jar插件实现基于注解的配置。

Action头部:

@ParentPackage("struts-default")

@Action(value="login",result={@Result(name="SUCCESS",location="result.jsp",type="",param="")),@Result...}

@InterceptorRef(value="拦截名字")

@InterceptorRefs({@Interceptor(""),@Interceptor("")})

@ExceptionMapping(exception)

@ExceptionMappings{@ExceptionMapping(),@ExceptionMapping()}

自定义拦截器:可在struts.xml定义,在action引用

(十五)

xml与Json方式解析

ajax异步通信

json->

(1)自定义json字符串

(2)使用插件

(十六)

(1)Action(重要)->exxcute

(2)过滤器(Filter)

(3)ValueStack

(4)ActionProxy(action代理对象)

ActionInvocation

源码与帮助文档分析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  struts2 java ee