Struts2总结

来源:互联网 发布:nba数据查询器stat 编辑:程序博客网 时间:2024/05/29 16:29
Struts2可以完成成员变量:   
1>数据类型自动转换
2>默认存储到request域对象中
3>默认为请求转发形式


使用Struts 2 开发程序的基本步骤:
1>加载Struts2 类库
2>配置web.xml文件
3>开发视图层页面
4>开发控制层Action
5>配置struts.xml文件
6>部署、运行项目


执行流程:
index.jsp --> web.xml-->StrutsPrepareAndExecuteFilter类 -->struts.xml 
--> <action name=""  class=""> --><action class类进行处理> --> <result>标签


Struts2 常用类库:
文件名                   说   明
struts2-core-xxx.jar Struts 2框架的核心类库
xwork-core-xxx.jar XWork类库,Struts 2的构建基础
ognl-xxx.jar    Struts 2使用的一种表达式语言类库
freemarker-xxx.jar Struts 2的标签模板使用类库
javassist-xxx.GA.jar 对字节码进行处理
commons-fileupload-xxx.jar 文件上传时需要使用
commons-io-xxx.jar Java IO扩展
commons-lang-xxx.jar 包含了一些数据类型的工具类


struts2五大核心jar包:
1>commons-logging.jar ————– 用于通用日志处理 
2>freemarker.jar ————– 表现层框架,定义了struts2的可视组件主题 
3>ognl.jar ————– ognl表达式语言,struts2支持该EL 
4>struts2-core.jar ————– struts2 2.0.11.2的核心库 
5>xwork.jar ————– webwork的核心库 


拦截器类:StrutsPrepareAndExecuteFilter (重点)
配置web.xml:
<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>  
//将全部请求定位到指定的Struts 2过滤器中(必须这样做)
</filter-mapping>




编写helloWorld.jsp
<div>
<h1>
<!--显示Struts Action中message的属性内容-->
<s:property value="message"/>   //输出显示语句
</h1>
</div>


<div>
<form action="helloWorld.action" method="post">
请输入您的姓名:
<input name="name" type="text" />
<input type="submit" value="提交" />
</form>
</div>


编写HelloWorldAction
public class HelloWorldAction implements Action {  //要实现Action接口
// 用户输入的姓名
private String name = "";
// 向用户显示的信息
private String message = "";
public String execute() {  //此方法为固定格式
// 根据用户输入的姓名,进行"Hello,XXXX!"的封装
this.setMessage("Hello,"+this.getName()+"!");         
// 处理完毕,返回导航结果的逻辑名
return "success";
}
//省略setter、getter方法
}


配置Struts 2配置文件(struts.xml)


<package name="default" extends="struts-default">
<action name="helloWorld"  class=“controller.HelloWorldAction">
//name属性与form表单的action属性值对应
<result name="success">/ok.jsp</result> //默认转发到ok.jsp
//与Action返回字符串对应
</action>
</package>


如何使用Struts 2实现用户登录验证?


开发控制层Action-LoginAction 


public class LoginAction implements Action {
private String username = "";
private String password = "";
public String execute() {
if(“sa".equals(username) && “123".equals(password)) {
return "success";
} else {
return "error";
}
}
}


配置Struts 2配置文件(struts.xml)


<package name="default" namespace="/" extends="struts-default">
<action name="login" class=“controller.LoginAction">
<!-- 结果为“success”时,跳转至success.jsp页面 -->
<result name="success">success.jsp</result>
<!-- 结果为"error"时,跳转至fail.jsp页面 -->
<result name="error">fail.jsp</result>
</action>
</package>


Struts 2使用session读取参数的方式(三种):
1>与Servlet API解耦的访问方式


对Servlet API进行封装
提供了三个Map对象访问request、session、application作用域
通过ActionContext类获取这三个Map对象
Object | get("request")
Map | getSession()
Map |getApplication()


ActionContext.getContext().getSession().put("bName", bookName);        


2>与Servlet API耦合的访问方式


通过ServletActionContext类获取Servlet API对象
ServletContext | getServletContext()
HttpServletResponse | getResponse()
HttpServletRequest  | getRequest()
通过request.getSession()获取session对象
通过xxx.setAttribute()和xxx.getAttribute() 功能,在不同的页面或Action中传递数据


ServletActionContext.getRequest().getSession().setAttribute("bName",               bookName);


3>通过实现sessionAware接口,重写setSession()方法


public class HaAction implements SessionAware {


private Map<String, Object> session;


private String bookName;
private int age; // 数据类型自动转换.
// 此处,会将属性值放在request域中.


//get和set方法


public String execute() {
bookName = "hello," + bookName;
System.out.println(age + 2);
System.out.println(bookName);
//ActionContext.getContext().getSession().put("bName", bookName);
//ServletActionContext.getRequest().getSession().setAttribute("bName",bookName);
session.put("xName", bookName);
return "yes";
}


@Override
public void setSession(Map<String, Object> session) {   
this.session = session;
}
}


Struts2自动实例化javabean对象,需要在xxxAction类中提供get()和set()方法来存值和取值,并且Struts2自动完成存值和取值的:
public class UserAction {
private Users user; // struts帮你new对象
// 注入!! struts拿到值,帮你塞到对象中相应的字段
public Users getUser() {
return user;
}
public void setUser(Users user) {
this.user = user;
}
public String execute() {
if (user.getUsername().equals("sa") && "123".equals(user.getPassword())) {
return "success";
}
return "no";
}
}


Struts 2的提供了表单验证机制:
继承ActionSupport类来完成Action开发,用validate()方法进行验证,且validate()方法先于execute()方法的进行。
ActionSupport类不仅对Action接口进行简单实现,同时增加了验证、本地化等支持 


public class UserAction extends ActionSupport {  //继承ActionSupport
public void validate() {  //表单验证方法,此方法格式固定
System.out.println("1");
if (username.trim().length() == 0) {
addFieldError("x", "帐号不能为空!");      //验证出错,指定错误提示信息
// 此错误要使用struts.xml中的<s:fielderror/> 标签来显示   
}
if (password.trim().length() == 0) {
addFieldError("y", "密码不能为空!");
}
}


struts.xml:
<result name="input">/index.jsp</result> 返回错误页面


Struts2的标签库分为两个部分:
1>UI标签 : 页面显示的
2>通用标签 : 逻辑判断的


 <%@ taglib prefix="s" uri="/struts-tags"%>
//需要在页面中引入Struts 2的标签库


1>UI标签 : 
1>>常用表单标签
标  签 说   明
<s:form>…</s:form> 表单标签
<s:textfield>…</s: textfield > 文本输入框
<s:password>…</s: password > 密码输入框
<s:textarea>…</s: textarea > 文本域输入框
<s:radio>…</s: radio > 单选按钮
<s:checkbox>…</s: checkbox > 多选框
<s:submit /> 提交标签
<s:reset /> 重置标签
<s:hidden /> 隐藏域标签
<s:text> 文本标签
<s:text name="username"/> 
2>>修改JSP页面


<s:fielderror/>    //显示服务器返回的错误信息   
<s:form action="login">
<s:textfield label="帐号" name="username"/>  // label属性用于显示文本  
<s:password label="密码" name="password"/>
<s:submit value="登录"/>
</s:form>


2>通用标签 : 
1>>条件标签


<s:if test="表达式">  //表达式条件为true时,执行相应的代码
    需要执行的代码
</s:if>
<s:elseif test="表达式">需要执行的代码</s:elseif>
<s:else>需要执行的代码</s:else>


2>>迭代:  用于遍历集合(只能用在集合上)


<s:iterator value="集合对象" status="status" id="name">           
    读取集合对象并输出显示
</s:iterator>


value属性
需要进行遍历的集合对象
status属性
表示当前迭代对象的一个实例
id属性
当前迭代元素的id,可直接访问元素,该参数可选


<s:iterator value="hobby">
<s:property />  //用于遍历集合中的元素   
</s:iterator>


<s:iterator begin="1" end="9" step="1" var="i">
${i}
</s:iterator>






网站登录程序运行流程图 :
login.jsp ---> 核心控制器 ---> Action ---> Result---> main.jsp


1>核心控制器
需要在web.xml中进行配置
对框架进行初始化,以及处理所有的请求
StrutsPrepareAndExecuteFilter  (org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter)


2>Action
配置Action
<action name="login" class="controller.LoginAction">


3>result
实现对结果的调用
result元素的值指定对应的实际资源位置
name属性表示result逻辑名


<result name="success">main.jsp</result>


1.  struts.xml
核心配置文件,主要负责管理Action
通常放在WEB-INF/classes目录下(提高安全性),在该目录下的struts.xml文件可以被自动加载


1>constant元素
<constant name="" value="" />
配置常量,可以改变Struts 2框架的一些行为
name属性表示常量名称,value属性表示常量值


当你修改了这个文件,必须要重新启动服务器,才可以,每次重启耗时耗力.   
进入开发模式
<constant name="struts.devMode" value="true" />
每次修改配置文件之后,服务器就能保存更改后的配置.这样服务器一直在监听这个配置文件. 所以在项目开发完毕,运行阶段,是一定要将此属性移除.避免不必要的性能开销!!!


设置字符集.utf-8. 等等常量配置. 
修改整个项目的编码方式, 过滤器 技能最好用!


<struts>
<constant name="struts.i18n.encoding" value="UTF-8"/>
</struts>


2>package元素 
<package name=""extends="">
包的作用:简化维护工作,提高重用性
包可以“继承”已定义的包,并可以添加自己包的配置
name属性为必需的且唯一,用于指定包的名称
extends属性指定要扩展的包
namespace属性定义该包中action的命名空间 ,为可选属性


假设.一个项目中. 有登录功能. 整个项目又分为前台,和后台. 前台一个人开发,后台另一个人开发. 登录功能都使用了login这个action名称. (用名称空间区分)


<package name="qian" namespace="/qian"     extends="struts-default">
<action name="login" class="controller.BeforeAction">
<result>/ok.jsp</result>
</action>
</package>


<package name="hou" namespace="/hou" extends="struts-default">
<action name="login" class="controller.AfterAction">
<result>/ok2.jsp</result>
</action>
</package>


3.Action
<action name="x" class="x">


1>
Include包含:(用于区分多个struts.xml)
<include file="struts-user.xml"/>
<include file="struts-product.xml"/>


2>Action的三种创建方式
1>>Action就是一个普通的类,
必须要写public String execute(){}
2>>实现Action接口,重写execute()方法
3>>继承ActionSupport类,也要重写execute() 
a)加入数据校验
b)国际化...


Action接口和ActionSupport类中有5个常量字符串,帮助我们做action返回
1.SUCCESS : 处理正常,返回成功后的结果
2.NONE : 处理正常,不返回任务提示
3.INPUT : 需要用户正确输入才能顺利执行
4.ERROR : 处理结果失败
5.LOGIN : 需要正确登录后才能顺利执行          


public String execute(){
System.out.println("咋滴");
return LOGIN;
}


3>Action的作用:          
1.封装数据的实际工作 (接收请求)
2.为数据转移提供场所 (转发数据)
3.框架根据返回字符串呈现响应的页面 (跳转页面)


4>Action的method属性: 


实现Action中不同方法的调用
优点:
避免动态方法调用的安全隐患
减少大量的Action配置 ,节省了类的数量.
<action name="login" class="controller.UserAction" method="login">
</action>
<action name="register" class="controller.UserAction" method="register">
</action>    //method的值为方法名


5>Action的动态方法调用:
作用:减少Action数量和类的数量.
使用:actionName!methodName.action     


<a href="hello!a">AAA</a>
<a href="hello!b">BBB</a>
<a href="hello!b.action">BBB</a>   // .action可以省略


禁用:将常量属性struts.enable.DynamicMethodInvocation设置为false 


<constant name="struts.enable.DynamicMethodInvocation" value="false"/>


在学习JDBC中,为什么使用ps的占位符? 
select * from user where name = ? and pwd = ?
取代了
select * from user where name = “+name+” and pwd = “+pwd+”
防止SQL的攻击(SQL注入!)
动态方法虽好,但不安全. 甚至极度危险.我们不仅不用,而且不让别人用. 应该把动态方法禁用!!!!


6>Action通配符 : 减少Action的数量,是另一种形式的动态方法调用
<a href="aUsersunguoan">test1</a>
<a href="bUsermike">test2</a>


<action name="*User*" class="controller.UserAction" method="{1}">
<result name="{2}">/{1}.jsp</result>  //{1}代表第一个*,{2}代表第二个*          
</action>


7>默认的Action : 没有Action匹配请求时,执行默认的Action
通过<default-action-ref … />元素配置默认Action
<!-- 引用默认的action -->
<default-action-ref name="xxx"/>           
<!-- 定义默认的action -->
<action name="xxx">
<result>404.jsp</result>
</action>


<action name="buy*" class="controller.ProductAction" method="{1}">
//省略class属性,将使用ActionSupport类   
<result name="{1}">/{1}.jsp</result>
</action>


练习:
使用同一Action处理用户登录和注册请求


练习:
增加默认Action
当出现异常错误时,执行默认Action,并跳转到错误提示页面


4.Result常用结果类型
<result name="x">/x</result>
1>结果类型
1>>dispatcher类型
默认结果类型,后台使用RequestDispatcher转发请求 


转发 : request保值,一次请求:url不变
request.getRequestDispatcher(“xxx.jsp”).forward(request,response);


2>>redirect类型 
后台使用的sendRedirect()将请求重定向至指定的URL 


重定向 : request失效, 两次请求:url改变
response.sendRedirect(“xxx.jsp”);


3>>redirectAction类型 
主要用于重定向到Action 


struts中默认为转发形式.             
转发
<result type="dispatcher">/ok.jsp</result>
重定向
<result type="redirect">/ok.jsp</result>           
重定向到action
<result type="redirectAction">chong</result>


<action name="*User" class=“controller.UserAction" method="{1}">
<result name="success" type="dispatcher">{1}_success.jsp</result>
<result name="input">{1}.jsp</result>
<result name="error">error.jsp</result>
</action>


2>动态结果
配置(开发阶段)时不知道执行后的结果是哪一个,运行时才知道哪个结果作为视图显示给用户
WEB-INF下的文件.直接访问是不可以的
真实的项目中.都会把页面保护到WEB-INF下


<action name="login" class="controller.UserAction">
<result>/WEB-INF/${lv}.jsp</result>    //这样才能访问到WEB-INF下的文件
</action>


public String execute() {   //动态结果
if (userid.equals("sa")) {
setLv("ceo");
} else if (userid.equals("admin")) {
setLv("cto");
} else {
setLv("guest");
}
return "success";
}


3>全局结果 : 返回的字符串找不到匹配,就会去全局的result中看看有没有.
作用:
实现同一个包中多个action共享一个结果


//全局结果位于package元素内
<package name="" extends="">     
<global-results>          
<result name="a">a.jsp</result>
<result name="b">b.jsp</result>
<result name="woyebuzhidao">404.jsp</result>
</global-results>
</package>     


按照模块划分开发任务..
张三就负责用户相关的功能
李四就负责商品页面展示的功能


练习:
用户登录成功,显示该用户的成绩信息






Oracle中创建自增序列:
Create sequence xx; 在jdbc的java文件中输出值


String sql = "insert into users (id,username,password)values(xx.nextval,?,?)";


一、拦截器


为什么需要拦截器 ?


早期MVC框架将一些通用操作写死在核心控制器中,致使框架灵活性不足、可扩展性降低 


Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于系统的解耦


什么是拦截器?


Struts 2大多数核心功能是通过拦截器实现的,每个拦截器完成某项功能 


拦截器方法在Action执行之前或者之后执行


拦截器栈:
从结构上看,拦截器栈相当于多个拦截器的组合
在功能上看,拦截器栈也是拦截器 
拦截器与过滤器原理很相似


为Action提供附加功能时,无需修改Action代码,使用拦截器来提供


拦截器做三阶段执行周期:           
1、做一些Action执行前的预处理
2、将控制交给后续拦截器或返回结果字符串
3、做一些Action执行后的处理


Struts 2自带拦截器:


params拦截器 
负责将请求参数设置为Action属性
servletConfig拦截器 
将源于Servlet API的各种对象注入到Action
fileUpload拦截器
对文件上传提供支持
exception拦截器
捕获异常,并且将异常映射到用户自定义的错误页面
validation拦截器 
调用验证框架进行数据验证 
workflow拦截器
调用Action类的validate(),执行数据验证


应用:
1.阻止表单的重复提交
token 令牌 拦截器解决问题
当注册用户的时候.点按钮就注册.
struts自带的拦截器的一个应用.


注意:
报空指针异常:
1>将页面表单元素全部改为strust标签元素
2>引用默认的拦截器 defaultStack
<interceptor-ref name="defaultStack"/>


配置拦截器:在struts.xml中的<packge>中配置


<action name="register" class="controller.UserAction">
<!-- 表单得不到数据,报空指针异常,引入这个默认的拦截器,否则可省略  -->
<interceptor-ref name="defaultStack"/>   
<!-- 引用拦截器 -->
<interceptor-ref name="token" />   
<!--1. 此拦截器为token拦截器,struts已经实现   -->
<result>/ok.jsp</result>
<result name="invalid.token">/nosubmit.jsp</result>         
<!--2. 拦截后返回的页面,必须要配置   -->
</action>


在form表单中指定拦截器 ,token为令牌     
<s:form> <s:token /> 
<!-- 3.必须有,实现token拦截器 -->
<s:textfield label="帐号" key="user.username" />        ?
</s:form>


token原理:
所谓的token,中文译名“令牌”。顾名思义,就是使用一种验证,验证对了,就让你继续访问action,验证错了,直接把你拦截住,交给指定的页面。验证的关键步骤就是token拦截器的原理:当浏览器访问一个带有<s:token></s:token>标签的页面时,服务器生成一个随机数,把这个随机数放入session中,也放入表单中隐藏的token属性中。显然,此时这两个随机数是相等的。而后,当你向服务器提交表单时,表单中隐藏的token属性也会传给服务器。此时如果访问的的action使用了token的拦截器(即上面配置的),那么服务器会从session中得到刚才的随机数,将其和表单的token属性比较,看两者是否相同。如果相等,表示此次访问不是重复提交,无需拦截,清空session中的随机数,接着正常访问action。如果不相等,则直接拦截,不会继续访问action,直接跳到<result name="invalid.token">指定的页面,并且session中的随机数不变。


自定义拦截器:          
1>实现Interceptor接口
void init():初始化拦截器所需资源
void destroy():释放在init()中分配的资源
String intercept(ActionInvocation ai) throws Exception实现拦截器功能
利用ActionInvocation参数获取Action状态返回结果(result)字符串        


2>继承AbstractInterceptor类           
提供了init()和destroy()方法的空实现
只需要实现intercept方法即可(常用)


案例:计算方法的执行时间
自定义拦截器:


拦截器的实现:


public class MyTime extends AbstractInterceptor {  //继承AbstractInterceptor类  
@Override
public String intercept(ActionInvocation ai) throws Exception { 
 //重写intercept()   
long l1 = System.nanoTime();    //预处理工作
//long l1=System.currentTimeMillis();   
System.out.println("开始..."+l1);
ai.invoke();      //放行,执行后续拦截器或Action
long l2 = System.nanoTime();   //后续处理工作
System.out.println("结束..."+l2);
System.out.println("方法共耗时:"+(l2-l1)+"纳秒!");
return null;
}
}


配置拦截器:
<package name="test2" extends="struts-default">
<interceptors><!-- 定义拦截器 -->
<interceptor name="mytime" class="interceptor.MyTime"/>  //定义单个拦截器
</interceptors>


<action name="test" class="controller.TestAction">
<interceptor-ref name="mytime"/>    //引用拦截器
<result>ok.jsp</result>
</action>
</package>


3.模拟查看购物车(重点)
见项目Struts2_3_test3


4.对用户添加权限控制,非登录用户不能访问信息管理页面


权限验证拦截器
public class AuthorizationInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception{
//获取用户会话信息
Map session = invocation.getInvocationContext().getSession();          
User user = (User)session.get("login");
if (user == null) {
//终止执行,返回登录页面
return Action.LOGIN;
} else {
//继续执行剩余的拦截器和Action
return invocation.invoke();
}
  }
}
在配置文件中定义拦截器并引用它
<package name="renthouse" extends="struts-default">
<interceptors>
<!--定义权限验证拦截器-->
<interceptor name="myAuthorization"
class="interceptors.AuthorizationInterceptor">
</interceptor>
<!--定义拦截器栈-->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="myAuthorization"/>
</interceptor-stack>
</interceptors>
<!-- 定义默认拦截器 -->
<default-interceptor-ref name="myStack"/>
//因为包含在默认拦截器内,所以Action中无需再引用权限拦截器
… 
</package>


二、文件上传
1.单个文件上传
Commons-FileUpload组件
Commons是Apache开放源代码组织的一个Java子项目,其中的FileUpload是用来处理HTTP文件上传的子项目
Commons-FileUpload组件特点
使用简单:可以方便地嵌入到JSP文件中,编写少量代码即可完成文件的上传功能
能够全程控制上传内容
能够对上传文件的大小、类型进行控制


环境要求
commons-fileupload-xxx.jar
commons-io-xxx.jar


2.多个文件上传


表单设置
多个File控件
name属性相同         
Action的修改
将三个属性的类型修改成数组类型


uploadContentType=控件名+ContentType
uploadFileName=控件名+FileName


//获取提交的多个文件
private File[] upload;
//封装上传文件的类型
private String[] uploadContentType;
//封装上传文件名称
private String[] uploadFileName;


表单设置:
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="fname"/>
<input type="file" name="fname"/>
<input type="file" name="fname"/>          
<button>保存</button></form>


<s:file name="upload" label="选择文件"/>       


public class Up {
// 三个属性,命名是有一定规则的
// 1.文件本身
private File[] fname;
// 2.文件类型
private String[] fnameContentType;
// 3.文件名
private String[] fnameFileName;
public String execute() {
System.out.println("开始上传!");
try {
for(int i = 0; i<fname.length;i++){
String path = ServletActionContext.getServletContext().getRealPath("/picture/"+fnameFileName[i]);
FileInputStream input = new FileInputStream(fname[i]);
FileOutputStream output = new FileOutputStream(path);
IOUtils.copy(input, output);  //调用IOUtils工具类的copy方法        
output.close();
input.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
//get()和set()方法
}
在struts.xml中配置:
<action name="upload"  class=“controller.UploadAction">
<!--通过param参数设置保存目录的路径-->
<param name="savePath">/upload</param>   //以参数方式指定保存路径


注:上传视频用FTP上传到服务器


三、下载文件
1.下载文件(可以下载电影)


stream结果类型:


stream结果类型将文件数据(通过InputStream获取)直接写入响应流相关参数的配置


名称 作用
contentType 设置发送到浏览器的MIME类型
contentLength 设置文件的大小
contentDisposition 设置响应的HTTP头信息中的Content-Disposition参数的值
inputName 指定Action中提供的inputStream类型的属性名称
bufferSize 设置读取和下载文件时的缓冲区大小


contentType类型:


文件类型 类型设置
Word application/msword
Execl application/vnd.ms-excel
PPT application/vnd.ms-powerpoint
图片 image/gif , image/bmp,image/jpeg
文本文件 text/plain
html网页 text/html
可执行文件 application/octet-stream


实现步骤
编写下载文件Action
获取InputStream输入流
配置Action
指定下载文件的类型、下载形式等


在struts.xml中配置:
<result type="stream">
<param name="contentType">application/octet-stream</param>  
//通用设置,可执行文件
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${fileName}"      
</param>
//Attachement表示以附件形式下载Filename表示下载时显示的文件名称
<param name="bufferSize">4096</param>
</result>


Action类中编写:


// 两个属性
// 1.文件流
private InputStream fileInputStream;
// 2.下载的文件名称 
private String fileName;
public String execute() {
// fielName = E:/spiderMan.exe
File f = new File(fileName);
this.fileName = f.getName();
try {
fileInputStream = new FileInputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return "success";
}
//get和set方法


index.jsp页面:


<a href="xia?fileName=E:/课件/JavaFrames笔记/Struts2_3/downloadVideo/1.exe">点击下载:1.exe
</a>     //传参文件名

一、数据类型转换              
a)原始类型和封装类型
原始类型 : 四类八种 
封装类型 : 除了原始类型.


在web应用程序中.url中传递的参数,永远是字符串类型.
其实将类型转换的是struts平台中内置的类型转换器.


b)多值类型
当数组在页面指明了下标,那么必须在action中创建时指明长度.
List很像数组,但要注意:
不需要初始化任何一个list
如果没有泛型的说明,list默认为List<String>          
如果指明泛型,struts2会自动创建与泛型想匹配的对象并注入


Struts 2内置类型转换器:
内置类型转换器 说    明
String 将int、long、double、boolean、String类型的数组或                                      者java.util.Date类型转换为字符串
boolean/Boolean 在字符串和布尔值之间进行转换
char/Character 在字符串和字符之间进行转换
date 在字符串和日期类型之间进行转换。具体输入输出格                                      式与当前的Locale相关
数组和集合 在字符串数组和数组对象、集合对象间进行转换


c)自定义类型转换器
页面传来的是string,接收会自动转为相应的数据类型.
页面传来一个时间格式,而我自定义时间格式.


自定义类型转换器要:
继承StrutsTypeConverter抽象类          


重写以下两个方法:
将一个或多个字符串值转换为指定的类型
public Object convertFromString(Map context, String[] value, Class toType)
将指定对象转化为字符串 
public String convertToString(Map context, Object object)


处理类型转换错误:
向用户输出类型转换错误的前提条件:          
1>Action要继承ActionSupport类 
2>配置input结果视图
3>页面使用Struts 2表单标签或<s:fielderror>标签
Struts 2表单标签内嵌了输出错误信息功能
普通HTML标签需使用<s:fielderror>标签输出转换错误 


步骤:
1.在src目录创建xwork-conversion.properties
转换类全名=类型转换器类全名
java.util.Date=time.MyTime
2.Action类必须继承ActionSupport
3.在src下建立资源文件. message.properties
xwork.default.invalid.fieldvalue=error!
修改所有类型的转换错误信息 
4.定制指定字段的类型转换错误信息,与Action同包下建立资源文件,ActionName.properties
invalid.fieldvalue.time=日期转换错误!
5.在Struts.xml中配置资源显示
<constant name="struts.custom.i18n.resources" value="message"/>


SimpleDateFormat[] sdf = {
new SimpleDateFormat("yyyy-MM-dd"),
new SimpleDateFormat("yyyy=MM=dd"),
new SimpleDateFormat("yyyy年MM月dd日")
}; 
sdf[i].parse(str);       //转换为Date对象


String s =new SimpleDateFormat().format((Date)o);  //转换为字符串


二、OGNL表达式
Object-Graph Navigation Language : 对象图导航语言
开源项目,取代页面中的脚本,简化数据的访问.
同EL表达式类似,但功能更为强大.
java的方式:  user.getSchool().getGrade().getBanji();
ognl的方式:  user.school.grade.banji


值栈(ValueStack)?
由Struts2框架创建的存储区域,具有栈的特点
Action的实例会被存放到值栈中
Struts2将值栈作为OGNL上下文根对象


OGNL访问值栈:
按照从上到下的顺序
靠近栈顶的同名属性会被读取


ognl访问:
a)访问javabean
user没有new,address也没有new. 都是由struts帮我们创建。


自动创建对象的前提:
1.必须要符合javabean规范的类.必须提供无参构造.
2.属性必须get和set.否则赋不上值


b)访问集合对象


<s:textfield label="所在城市" name="list2[0].address.city"/>


<s:property value="list2.empty"/><!-- false -->判断集合是否是空的,空返回true
<s:property value="list2.size"/>    <!-- 2 --> 获得集合的长度


遍历Map集合:
<s:iterator value="map">
<s:property value="key"/>     <!-- A B 键 --> 获得键
<s:property value="value.name"/>   获得值的指定属性
<s:property value="value.address.guo"/>    
</s:iterator>


ActionContext对象中有值栈对象与非值栈对象:
值栈中内容可以直接访问,访问非值栈对象需添加#前缀 
非值栈包括:
1>request  
2>session  
3>application 
4>parameters 
5>attr  全域查找


访问ActionContext的上下文
request.getParameter(“user”)   ==   #parameters.userxx   
request.getAttribute(“user”)    ==    #request.userxx==#request['userxxx'] 
session.getAttribute(“user”)     ==    #session.userxx
application.getAttribute(“user”)  ==    #application.userxx


<!-- 标签访问四大域,使用ognl的一种写法 -->
<s:property value="#session.userxx"/>
<s:property value="#session['userxx']"/>


struts2扩展标签:
1>时间格式标签
<s:date name="now" format="yyyy_MM_dd hh:mm:ss"/>


<s:date format="format"  nice="true|false"  name="name" id="id">
……
</s:date>
format属性:指定格式进行日期格式化
nice属性:该属性只有true和false两个值,用于指定是否输出指定日期与当前时间的时差,默认是false
name属性:表示当前需要格式化的日期
id属性:表示引用该元素的id值


2>超链接
定义超链接
<s:url id="dizhi" action="test">
<s:param name="name">张三</s:param>
<s:param name="age">22</s:param>
</s:url>
<!-- url直接写,会被识别为字符串 -->
<!-- %{dizhi} -->
<s:a href="%{dizhi}">去ok</s:a>            


action属性:表示指定生成URL的地址,
<s:param />表示需要传递的参数信息
name属性:表示传递的参数名称
value属性:表示传递参数所具有的值


使用超链接
<!-- url直接写,会被识别为字符串 -->
<!-- %{dizhi} -->
<s:a href="%{dizhi}">去ok</s:a>


使用OGNL标签的时候,标签中的值是具有数据类型的:


<s:url>的value是字符串类型
<s:property>的value是object类型              
所以对于字符串类型的属性,必须使用%{ } , 否则会被看成是字符串.         


private Date time;
<s:property value="time" />
<s:property>标签用于输出指定对象的属性值


3>调试标签
查看当前struts运行环境中的所有对象值的情况.
<s:debug/> 


ActionContext的组成:
值栈-ValueStack
非值栈-Stack Context


4>
<s:set name="age" value="10" scope="request"/>
<s:set>标签将一个值赋给指定范围的变量

一、验证框架
1>验证方法
1>>validate()方法
数据校验,需要的步骤:
1.继承ActionSupport
2.重写 public void validate(){}
3.<result name=”input”>指定校验失败后返回的页面         
注:execute() ,validate(), validateXxx()方法为系统自动调用


2>>validateXxx()方法
在struts.xml中配置:
<action name="login" class="controller.UserAction" method="login">


调用Action的任务方法(execute())时,validate()会默认执行,可用于验证一些通用规则。如果想为某个方法指定一些独有的验证规则,采用validateXxx()方法


//有一些特殊的验证规则,封闭到一个方法里。
public void validateLogin(){   //Xxx=指定处理请求的方法
if(user.getUsername().length()<3||user.getUsername().length()>=10)
       addFieldError("2","账号必须在3~10位之间!");
//参数一属性名,参数二错误信息
}
public void validate(){    }
public String login() {    //validateLogin()名称对应login()方法   }
三个方法的执行顺序:
validateLogin() ---> validate() ---> login() 
当 validateLogin() 与 validate() 校验不过时,不会执行login()。


2>验证框架 : 一个独立的文件


使用validate()或者validateXxx()方法时:
当验证规则复杂时,实现过程繁琐,导致Action类中代码臃肿,不符合java设计思路
因此,要使用Struts 2提供的验证框架


验证框架中的校验器:
校验器类型 校验器名称 说    明
必填校验器 required字段不能为空
必填字符串校验器 requiredstring     字段值不能为空长度要大于0
整数校验器 int 字段的整数值的范围
字符串长度校验器 stringlength字段值的长度的范围
正则表达式校验器 regex字段是否匹配一个正则表达式
字段表达式校验器 fieldexpression字段必须满足一个逻辑表达式
日期校验器 date 日期输入是否在指定的范围内
双精度校验器 double 字段值必须是双精度类型


使用验证框架的步骤:
1)编写Action,需要继承ActionSupport类
2)配置Action
<result name=”input”>指定校验失败后返回的页面           
3)编写表单
4)编写验证文件和校验规则
验证文件类型为xml格式,存放在与Action同一包中           
命名规则有两种方式
1>ClassName-validation.xml   //ClassName: Action类名
2>UserAction-user_regist-validation.xml(只校验regist方法,必须为此格式)


UserAction-validation.xml内容:
<validators>   //验证文件的根节点
<field name="user.username">
<field-validator type="requiredstring">        
<param name="trim">true</param>
<message>用户名不能为空!哈哈</message>
</field-validator>


<field-validator type="stringlength">
<param name="minLength">5</param>
<param name="maxLength">10</param>
<message>用户名长度在${minLength}和${maxLength}之间~@~!</message>
</field-validator>
</field>

<field name="user.password2">
<field-validator type="fieldexpression">
<param name="expression">password1==password2</param>
<message>两次密码必须相同~!</message>
</field-validator>
</field>


<field name="user.telephone">
<field-validator type="regex">
<param name="expression">^\d{3,4}-\d{7,8}$</param>
<message>座机格式错误</message>
</field-validator>
</field>
</validators>


注意:验证文件的dtd的导入.如果报错,可以改为绝对路径


二、国际化
国际化(Internationalization:I18N)?
使程序在不做任何修改的情况下,可以在不同国家或地区和不同语言环境下,按照当地的语言和格式习惯显示字符


本地化(Localization:L10N)
一个国际化的程序,当它运行在本地机器时,能够根据本地机器的语言和地区设置显示相应字符


Java程序的国际化思路(struts的国际化,也是基于java的国际化.只不过是struts进行了二次封装):
将程序中的提示信息、错误信息等放在资源文件中,为不同国家/语言编写对应资源文件
资源文件由很多key-value对组成,key保持不变,value随国家/语言不同而不同
这些资源文件使用共同的基名,通过在基名后面添加语言代码、国家和地区代码来进行区分
且必须要翻译.用一个文件来做为翻译的资源.


常用资源文件:
资源文件名 说    明
ApplicationResources_en.properties 所有英文语言的资源
ApplicationResources_zh.properties 所有的中文语言的资源
ApplicationResources_zh_CN.properties 针对中国大陆的、中文语言的资源
ApplicationResources_zh_HK.properties 针对中国香港的、中文语言的资源
ApplicationResources.properties 默认资源文件,如果请求的资源文   件不存在,将调用它的资源进行显


使用国际化的步骤: 
1>指定资源文件的基名及存储路径 (在struts.xml中配置)
<struts>
<constant name="struts.custom.i18n.resources" value="message"/>
<constant name="struts.i18n.encoding" value="UTF-8"/>(不常用)
</struts>


2>创建资源文件
存放位置:在src目录下,或者直接在WEB-INF/classes目录名称
china.properties
english.properties


3>实现JSP页面信息的国际化显示 


将JSP页面中的所有中文在english.properties文件中替换掉


4>实现验证错误信息的国际化显示
编写资源文件
编写验证文件
编写Action


资源文件的范围:(不重要)


1>全局资源文件 
所有包的所有Action类都可以访问
导致资源文件变得非常庞大臃肿,不便于维护  
2>包范围资源文件 
对应包下创建package_language_country.properties
处于该包及子包下的action才可以访问该文件
3>Action范围资源文件
命名格式ActionClassName_language_country.properties 
只有单个Action可以访问


查找顺序:Action---package---全局


<validators>   
<field name="user.username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message key="namenull"/>  //通过key对应错误信息
</field-validator>
</validators>


三、分页查询(重要)


CREATE TABLE stu(
id INT(10) PRIMARY KEY AUTO_INCREMENT, //mySql设置主键自增
NAME VARCHAR(20)
);
SELECT * FROM stu;
INSERT INTO stu VALUES(DEFAULT,'张三');        


sql语句: 
oracle : rownum
mysql : limit
sqlserver : between...and...


String sql = "SELECT * from stu order by id limit ?,?";
//第一个参数指定第一个返回记录行的下标,第二个参数指定返回记录行的最大数目。初始记录行的下标是 0(而不是 1)                


对象的注入
具体的见Struts2_5_test2。

原创粉丝点击