strust2框架
1 概述
struts2是一个实现MVC的框架、
struts2不是struts1的升级版本,在WebWork框架技术基础之上。
struts2核心拦截器,struts2框架的核心功能都是依靠拦截器实现的。
2 MVC
MVC模型视图控制器
1M : javaBean 实现业务逻辑,数据访问,实体类,持久化类,工具类。
2V : JSP 显示数据,JSTL+EL
3C : Servlet 实现M与V之间的调度。(核心)
2.1 一个控制器当中做三件事
1接收用户请求,并获取请求数据。
2调用M层的业务逻辑。实现业务功能。
3页面导航到V层。
struts2框架就是对控制器进行了规范和统一。对一个控制器当中的三件事做了下个规范。
3 struts2的执行基本流图
3.1 开发人员只要完成三个部分的编写
1struts.xml文件:struts2执行的配置文件。现在使用注解比较多
2编写Action类。是使用struts2框架进行开发的核心类。(类似于Servlet)
3导航,在struts2中有一个叫Result对象,这个对象就是导航器对象,只要在Action中返回一个String类型的值,就可以直接影响到一个Result对象。实现页面的导航。
3.2开发过程说明三件事件
1参数都有哪些
2调用哪个业务
3导航页面
4 开发的第一个struts2工程
4.1 创建工程并导入struts2框架
4.2 配置struts2的核心过滤器
现在所有后缀为.action的请求都将提交给struts2框架处理。
4.3 编写Action类
Action是Struts2框架的核心组件,开发时就主要编写Action类。
而在Struts2框架中,对于Action类的要求非常简单。
1无参
2返回字符串类型
|
public class UserAction extends ActionSupport { public String login() throws Exception { return super.execute(); } } |
4.4 注册Action类
在struts.xml文件中注册UserAction类的login方法。
|
<struts> <!-- 包,组织Action, name属性,extends=值固定, namespace="URL",以后访问当前包下的Action时,必须先访问包。 --> <package name="user" extends="struts-default" namespace="/user"> <!-- action,核心组件 nameAction的访问名称,class是类,method类中的方法名称 --> <!-- ?当想访问这个Action时,URL=“/user/login.action” --> <action name="login" class="com.no8.actions.UserAction" method="login"> <!-- 当前Action的导航,name是方法的返回值。 --> <result name="ok">/ok.jsp</result> <result name="nook">/error.jsp</result> </action> </package> </struts> |
4.5 编写jsp页面
|
<form action="${pageContext.request.contextPath }/user/login.action" method="post"> 用户名:<input name="username" value=""><br> 密 码:<input name="password" value=""><br> <input type="submit" value="登录"> </form> |
4.6 编写后台模型层
业务规则:只要用户名与密码一致就认为登录成功!
|
public class UserSerivce { public boolean isLogin(String username,String password){ return username.equals(password); } } |
4.7 编写核心Action的功能
一个Action就是一个控制器。
1接收用户请求的参数
|
public class UserAction extends ActionSupport { private String username; private String password; //set/get方法 public String login() throws Exception { System.out.println(username); System.out.println(password); return "nook"; } } |
2调用后台业务逻辑
|
public String login() throws Exception { System.out.println(username); System.out.println(password); UserSerivce userSerivce= new UserSerivce(); boolean bool = userSerivce.isLogin(username, password);
return "nook"; } |
3页面导航,返回注册时配置的导航器的name属性
|
public String login() throws Exception { System.out.println(username); System.out.println(password); UserSerivce userSerivce = new UserSerivce(); boolean bool = userSerivce.isLogin(username, password); if (bool) { return "ok"; } else { return "nook"; } } |
5 练习:使用struts2+Hibernate框架实现注册功能
6 Struts2的配置文件
6.1 struts2框架的属性配置
struts.properties文件是由程序员编写。
default.properties文件是由框架提供,默认的struts2框架的属性配置。
default.properties文件:能看不能改
lib->struts2->strutscore->org.apache.struts->default.properties
struts.properties文件:程序员编写,用来修改默认的struts2框架的属性配置。
现在基本不在使用这个文件。因为在struts.xml文件中可以实现同样的功能
struts.xml文件:核心配置文件,可以修改Struts2框架的属性配置。
|
<struts> <!-- 用来修改default.properties文件中对于struts2框架的配置 --> <constant name="struts.i18n.encoding" value="utf-8" /> |
6.2 struts2框架的配置文件
struts.xml文件:程序员编写的struts2的核心配置文件
struts-default.xml文件:struts2框架提供的配置文件,这里配置了struts2框架的所有核心功能。
struts-default.xml文件:
lib->struts2->strutscore->struts-default.xml文件
在这文件中配置了“struts-default”的package
7 struts2的注解
|
@ParentPackage("struts-default") @Namespace("/useranno") public class UserAnnoAction { private Integer userId; @Action(value = "findbyid", results = { @Result(name = "ok", location = "/ok.jsp"), @Result(name = "nook", location = "/error.jsp") }) public String findById() { UserSerivce userSerivce = new UserSerivce(); Users user = userSerivce.findById(userId); if (user != null) { return "ok"; } else { return "nook"; } } //set&get方法 |
|
@ParentPackage("struts-default") 表示继承struts-default。固定值。 |
|
@Namespace("/useranno") 为类设置访问的URL |
|
@Action(value = "findbyid", value是为方法设置访问的URL |
|
@Action(value = "findbyid", results = { @Result(name = "ok", location = "/ok.jsp"), @Result(name = "nook", location = "/error.jsp") }) results是个数组,表示多个导航器 |
|
@Result(name = "ok", location = "/ok.jsp") 一个导航器注解,name表示的方法返回值。location表示导航的路径 |
7.1 Result导航器的类型
7.1.1 在struts-default.xml文件中配置的导航类型
7.1.2 type="dispatcher" 转发,默认值。
7.1.3 type="redirect" 重定向
7.1.4 type="redirectAction" 重定向到下一个Action
7.1.5 type="chain" 转发到下一个Action
7.2 在chain和redirectAction时的处理
在chain和redriectAction进行下一个Action的导航时,分两种情况处理
1同一个包(package)的其他的Action
只要指定Action的name属性
2不同包(@Namespace)的Action
要使用参数设置的方式:
1namespace :不同包的name属性
2actionName : 不同包的Action的name属性
先看XML文件的方式:
基于注解方式的导航类型的设置
同一个包的其他的Action
|
@ParentPackage("struts-default") @Namespace("/goods") public class GoodsAction { @Action(value = "findall", results = { @Result(name = "ok", location = "/index.jsp") } ) public String findAll() { System.out.println("findall()"); return "ok"; } @Action(value="save" , results={ @Result(name="ok",type="redirectAction",location="findall") }) public String save() { System.out.println("save"); return "ok"; } } |
不同包中的Action
|
@ParentPackage("struts-default") @Namespace("/user") public class UserAction { @Action(value="login",results={ @Result(name="ok",type="redirectAction", params={"namespace","/goods","actionName","findall"} ) }) public String login(){ System.out.println("login"); return "ok"; } } |
8 接收用户请求参数
在struts2框架中一共提供三种方式实现接收用户请求的参数。
8.1 属性驱动方式
直接在Action类中设置属性,保证属性的名称与请求的参数名称一致。就可以实现自动将参数保存到属性中。
|
public class UserAction extends ActionSupport { private String username; private String password; private String userAddress; private String userPhone; |
|
<form> <input name="username"> </form> |
8.2 使用域模型方式
1创建域模型对象
|
public class Goods implements java.io.Serializable { // Fields private Integer goodsId; private GoodsType goodsType; private String goodsName; private Float goodsPrice; private Integer goodsNum; private String goodsImg; private Timestamp goodsDate; |
2在Action类中使用域模型创建接收请求参数的实例并实例化
|
@ParentPackage("struts-default") @Namespace("/goods") public class GoodsAction { // 域模型对象 private Integer id ; private Goods goods = new Goods(); private GoodsType goodsType = new GoodsType(); //set&get方法 |
3在jsp页面上的表单上格式
格式:实例名.属性名
|
<form action="goods/save.action" method="post"> <input type="hidden" name="id"> goodsname:<input type="text" name="goods.goodsName"><br> goodsprice:<input type="text" name="goods.goodsPrice"><br> goodsnum:<input type="text" name="goods.goodsNum"><br> goodstype:<select name="goodsType.typeId"> <option value="1">家用电器</option> <option value="2">数码产品</option> </select> <input type="submit" value="save"> </form> |
8.3 使用模型驱动方式
1 在Action类中实现接口ModelDriven<T>。
|
@ParentPackage("struts-default") @Namespace("/user") public class UserAction implements ModelDriven<Users> { |
2 在Action类中重写getModel方法并返回模型对象
|
@ParentPackage("struts-default") @Namespace("/user") public class UserAction implements ModelDriven<Users> { private Users user = new Users(); @Override public Users getModel() { return user; } |
3 在JSP页面上不会再影响name="值" , 值 必须与模型对象的属性一致。
|
<form action="${pageContext.request.contextPath }/user/reg.action" method="post"> 用户名:<input name="userName" value=""><br> 密码:<input name="userPass" value=""><br> 地址:<input name="userAddress" value=""><br> 电话:<input name="userPhone" value=""><br> <input type="submit" value="注册"> </form> |
9 访问ServletAPI
在WEB开发时,使用Servlet的类。HttpServletRequest,HttpSession
但是struts2框架中,将Action与SerlvetAPI进行了解耦合的设计。
9.1 struts2框架中提供了两种访问serlvetAPI 的方法
1解耦合方式
就是在Action中不使用ServletAPI,但是实现相同的功能。
2耦合方式
就是在Action中直接使用ServletAPI。
9.2 与Servlet解耦合方式
在struts2框架中封装了三个Map集合来代替HttpSession,HttpServletRequest和ServletContext的使用
但是这三个Map集合只代替了其中保存数据的功能。保存数据:setAttribute(Key,value)
这三个Map集合中由struts2框架提供的。要想获得这个三个Map要使用ActionContext类。
9.2.1 ActionContext类
Action运行的上下文对象,就是环境对象。可以从个对象的方法中获得三个Map集合对象。
1 获得ActionContext类的实例
通过ActionContext类的静态方法getContext方法获得的实例
ActionContextactionContext = ActionContext.getContext();
2 获得代替HttpServletRequest(请求)的Map集合
Map<String,Object>reqMap = (Map<String, Object>) actionContext.get("request");
3 获得代替HttpSession(会话)的Map集合
Map<String,Object> sessMap= actionContext.getSession();
4 获得代替ServletContext(应用程序)的Map集合
Map<String,Object>appMap = actionContext.getApplication();
9.2.2 Struts2提供了三个接口的方式获得三个Map集合对象
1 org.apache.struts2.interceptor.ApplicationAware接口
public void setApplication(Map<String,Object> application)
2 org.apache.struts2.interceptor.RequestAware接口
publicvoid setRequest(Map<String, Object> request)
3 org.apache.struts2.interceptor.SessionAware接口
publicvoid setSession(Map<String, Object> session)
|
@ParentPackage("struts-default") @Namespace("/interface") public class InterfaceAction implements SessionAware { private Map<String,Object> sessMap ; @Override public void setSession(Map<String, Object> arg0) { this.sessMap = arg0; } @Action(value="add",results={ @Result(name="ok",location="/ok.jsp",type="redirect") }) public String add(){ this.sessMap.put("user", "peterSun"); return "ok"; } } |
9.3 与Servlet耦合的方式
耦合的方式就是在Action中直接访问ServletAPI。直接使用Servlet的对象。
9.3.1 ServletActionContext类
通过这个类的静态方法来获得真正的ServlerAPI中的各个对象
9.3.2 struts2提供了二个接口可以获得ServletAPI
1 org.apache.struts2.interceptor.ServletRequestAware接口
publicvoid setServletRequest(HttpServletRequest request)
2 org.apache.struts2.util.ServletContextAware接口
publicvoid setServletContext(ServletContext context)
|
@ParentPackage("struts-default") @Namespace("/interface") public class InterfaceAction implements SessionAware,ServletRequestAware { private Map<String,Object> sessMap; private HttpServletRequest request; @Override public void setServletRequest(HttpServletRequest arg0) { request = arg0; } @Override public void setSession(Map<String, Object> arg0) { this.sessMap = arg0; } @Action(value="add",results={ @Result(name="ok",location="/ok.jsp",type="redirect") }) public String add(){ this.sessMap.put("user", "peterSun"); ServletContext app = ServletActionContext.getServletContext(); app.setAttribute("user", "Sun"); return "ok"; } } |
10 补遗
10.1 Action的结构
在struts2的Action上没有规范。
类上没有规范(必须继承,必须实现接口)
类的方法有规范:
1public
2public String
3public String xxx()
在struts2中还是有关于Action的结构。
一般开发时Action类会继承ActionSupport类。
ActionSupport类有一个接口叫Action接口。
Action接口是所有Action类的规范。
Action接口中只有一个抽象方法:execute()
这个方法也是默认的方法。
|
<struts> <package name="demo" extends="struts-default" namespace="/demo"> <action name="demo1" class="com.no8.action.TestAction" /> </package> </struts> |
|
这种情况下默认调用execute方法 |
|
@Action(value="demo1") public class TestAction extends ActionSupport { } |
|
这种情况下默认调用execute方法 |
Action接口中有5个常量。
这5个常量也是开发中使用的最频繁的5个常量。
其中有一个叫success的常量。字符串值 “success”默认值。导航的默认值。
|
@Action(value="demo1",results={ @Result(location="/index.jsp") }) public class TestAction extends ActionSupport { @Override public String execute() throws Exception { return ActionSupport.SUCCESS; } } |
11 手动校验
11.1 在Action类中重写validate()和编写validateXxx()方法
11.1.1 重写validate()-ActionSupport类
|
@Override public void validate() { System.out.println("validate!$%^&^%$#%^$"); } |
validate方法是一个校验规则方法。
在struts2框架中为手动校验做了一系列的规范。有自己的调用规则。
validate方法,这个方法就是struts2框架进行校验的方法,通过给Action为中的每一个方法的校验规则方法。
validate方法的作用,在struts2框架调用Action方法之前会先调用validate方法,通过validate方法的执行结果判断校验时否成功。如果成功就继续调用Acton的业务方法。否则进行页面导航,不再调用Action的业务方法。
在struts2中使用校验框架时一般都要继承ActionSupport类。
特点:所有业务方法调用之前统一调用validate方法。
不Action中不同的业务方法应该有不同的校验规则。不能只用使用一个validate方法。
11.1.2编写validateXxx()
因为validate方法是一个通用的方法,所有业务都会调用的方法,在不同业务时不能体现不同的数据校验规则。
针对每一个业务方法都有不同的校验规则时使用validateXxx方法。
Xxx--表示的是业务方法的名称。名称就是对应业务方法的名称。
|
public void validateReg() {//这个校验方法只针对reg业务 System.out.println("validateReg!$%^&^%$#%^$"); } public void validateLogin() { System.out.println("validateLogin!$%^&^%$#%^$"); } |
11.2 在方法中使用addFieldError()方法保存校验错误信息
validate方法是一个没有返回值的方法。public void validate()
在struts2框架中有一个错误容器。在调用完validate方法之后,struts2框架会判断错误容器是否为空(is empty)。
如果容器为emtpy则表示校验成功,可以调用业务方法。
所以我们在validate方法中如果发现校验有错误,我们只要将错误信息添加到错误容器。
addFieldError()方法就是将错误信息添加到错误容器。
这个方法ActionSupport已经写好了。我们只要调用就可以。
|
public void validateReg() { System.out.println("validateReg!$%^&^%$#%^$"); if(users.getUsername()==null || "".equals(users.getUsername())){ //将错误信息添加到错误容器 this.addFieldError("username", "用户名不能为空!"); } if(users.getPassword()==null || "".equals(users.getPassword())){ this.addFieldError("password", "密码不能为空!"); }else if (users.getPassword().length()<6){ this.addFieldError("password", "密码长度不能小于6位!"); } } |
11.3 Action的配置信息中要加入name=“input”视图,确定错误显示页面
validate方法可以将错误信息添加到错误容器。struts2框架调用完成validate方法会自动验证错误容器是否为空。
如果为空说明校验成功,调用业务方法。
如果不为空说明校验失败,自动页面导航。自动按业务方法的input的导航器进行导航。
为业务方法指定一个name="input"的视图。
11.4 在jsp页面中使用fielderror标签输出错误消息
fielderror标签是struts2框架提供的一组标签库中一个专门用于显示校验错误信息的标签
|
<%@ taglib prefix="s" uri="/struts-tags" %> |
|
<s:fielderror/>显示所有错误信息 |
|
<s:fielderror fieldName="username"/>显示一个错误信息 |
11.4.1 异常提示
问:<s:fielderror/>这个标签是谁的?struts2框架的。所以应该于struts2框架对这个标签进行处理。
所以reg.jsp页面是不是应该让struts2框架也进行加载。
|
<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> |
12 Struts2框架提供校验框架
12.1 编写校验规则文件
12.1.1 同Action类在一个目录下
如果我们要为UserAction类中的业务方法编写校验规则文件
这个文件的位置必须放在com.no8.action下面。
12.1.2 校验规则的文件名称
1UserAction-validation.xml
通用于UserAction类中所有方法的校验规则文件
2UserAction-reg-validation.xml(推荐)
用于UserAction类中reg业务方法的校验规则文件
12.1.3 校验规则文件的格式
在工程的struts2的jar包中找到规则的规范dtd文件
xwork-core-2.1.jar-> xwork-validator-1.0.3.dtd
|
<!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=""> <field-validator type=""> <message></message> </field-validator> </field> </validators> |
12.1.4 每一个节点的作用
1<field name=""> 用来指定需要校验的属性字段
2<field-validator type="?"> 用来指定校验规则的内置校验器
3 <message></message>用来指定错误信息
|
<validators> <field name="repassword"> <field-validator type="requiredstring"> <message>确认密码不能为空!</message> </field-validator> </field> <field name="users.username"> <field-validator type="requiredstring"> <message>用户名不能为空!</message> </field-validator> </field> </validators> |
|
<form action="${pageContext.request.contextPath }/user/reg.action" method="post"> 用户名:<input type="text" name="users.username" value="" > <s:fielderror fieldName="users.username" theme="simple"/><br> 密码:<input type="password" name="users.password" value=""> <s:fielderror fieldName="password"/><br> 确认密码:<input type="password" name="repassword" value=""> <s:fielderror fieldName="repassword"/><br> <input type="submit" value="注册"> </form> |
12.2 常用的内置校验器
12.2.1 stringlength:字符串长度
1maxLength : 最大长度
2minLength : 最小长度
3trim : 去空格
|
<field name="repassword"> <field-validator type="requiredstring"> <message>确认密码不能为空!</message> </field-validator> <field-validator type="stringlength"> <param name="minLength">4</param> <param name="maxLength">8</param> <param name="trim">true</param> <message>密码长度大于${minLength}位小于${maxLength}位</message> </field-validator> </field> |
12.2.2 int : 类型校验器
12.2.3 email : 邮箱校验器
12.2.4 regex : 正则表达式校验器
12.2.5 fieldexpression :字段比较器校验器
|
<validators> <field name="repassword"> <field-validator type="requiredstring"> <message>确认密码不能为空!</message> </field-validator> <field-validator type="stringlength"> <param name="minLength">4</param> <param name="maxLength">8</param> <param name="trim">true</param> <message>密码长度大于${minLength}位小于${maxLength}位</message> </field-validator> <field-validator type="fieldexpression"> <param name="expression">repassword.equals(users.password)</param> <message>两次密码不一致!</message> </field-validator> </field> <field name="users.username"> <field-validator type="requiredstring"> <message>用户名不能为空!</message> </field-validator> </field> <field name="users.email"> <field-validator type="email"> <message>邮箱格式不正确!</message> </field-validator> </field> <field name="users.phone"> <field-validator type="regex"> <param name="expression">\d{11}</param> <message>手机格式不正确!</message> </field-validator> </field> </validators> |
13 练习:实现商品上传功能
要求:1 使用struts2的校验实现服务器端验证
2 JSP页面使用日历控件输入日期
3 商品应该有的属性:
名称,价格,出厂日期,到期时间(大于出厂日期),
数量(整数),产品地,二维码(只能四位数字)
14 拦截器(了解)
14.1 token拦截器:
作用:防止表单重复提交
token令牌。每次在表单提交时,带一个编号过来(令牌),如果再次请求时编号没有发生变化,服务器就认为是重复提交。
14.2 使用步骤
1在jsp页面的表单上使用struts2的标签加入token令牌。web.xml文件
|
<form action="" method="post"> <s:token/>
</form> |
2在注册Aciton时指定引用拦截器
|
<package extends="struts-default" name="goods" namespace="/goods"> <action name="save" class="com.no8.action.GoodsAction" method="save"> <result>/ok.jsp</result> <interceptor-ref name="token"/><!-- 引用token拦截器 --> <!-- 当你有指定拦截器时,默认就不启作用,手动指定引用默认拦截器 --> <interceptor-ref name="defaultStack"/> </action> </package> |
3当表单重复提交时,会自动按invalid.token导航跳转
|
<action name="save" class="com.no8.action.GoodsAction" method="save"> <result>/ok.jsp</result> <result name="invalid.token">/token.jsp</result> |
14.3 execAndWait拦截器
1在Aciton注册上加入execAndWait拦截器
2为execAndWait拦截器配置导航name="wait"
|
<action name="save" class="com.no8.action.GoodsAction" method="save"> <result>/ok.jsp</result> <result name="wait">/wait.jsp</result> <!-- 当你有指定拦截器时,默认就不启作用,手动指定引用默认拦截器 --> <interceptor-ref name="defaultStack" /> <interceptor-ref name="execAndWait" /> </action> |
3在jsp页面上使用struts2标签实现自动跳转
|
<meta http-equiv="refresh" content="5;url=<s:url includeParams="all"/>"> |
|
请求已发送,请耐心等着。5秒之后自动跳转, 如果没有跳转请点<A href="<s:url includeParams="all"/>">这里</A><br> |
15 自定义拦截器
15.1 步骤1:编写自定义的拦截器类
1实现Interceptor接口
2继承AbstractInterceptor类(使用)
|
public class StringInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { return "ok"; } } |
|
intercept方法返回值类型是String,这个地方返回一个字符串也表示按result导航进行跳转,与Action类中的方法的返回值的作用是一样的。 |
|
return invocation.invoke(); 返回invocation.invoke()时调用后面的内容,理解时当成Filter中的放行就可以了。 |
15.2 步骤2:在struts2框架中注册这个拦截器
|
<package name="my-struts-default" extends="struts-default" abstract="true"> <interceptors> <interceptor name="stringInterceptor" class="com.no8.interceptor.StringInterceptor" /> <interceptor-stack name="stringStack"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="stringInterceptor" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="stringStack" /> </package> |
15.3 步骤3:在需要使用的Action中引用这个拦截器
|
<package extends="my-struts-default" name="goods" namespace="/goods"> <action name="save" class="com.no8.action.GoodsAction" method="save"> <result>/ok.jsp</result> <result name="StringInterceptor">/str.jsp</result> <interceptor-ref name="defaultStack" /> <interceptor-ref name="stringInterceptor" /> </action> </package> |
15.4 实现对敏感字的过滤功能
|
public class StringInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("StringInterceptor"); Object obj = invocation.getAction(); if(obj instanceof GoodsAction){ GoodsAction goodsAction = (GoodsAction) obj; String goodsName = goodsAction.getGoodsName(); goodsAction.setGoodsName(goodsName.replace("夜总会", "***")); } return invocation.invoke(); } } |
15.5 基于注解的方式
|
@ParentPackage("my-struts-default") @Namespace("/goods") public class GoodsAction extends ActionSupport { @Action(value="save" ,results={ @Result(name=SUCCESS ,location="/ok.jsp") }, interceptorRefs={ @InterceptorRef("defaultStack"), @InterceptorRef("stringInterceptor") } ) public String save() throws Exception { System.out.println(goodsName); return super.execute(); } private String goodsName; |
16 struts2整合JSON
做为一个现在使用的很多的JSON。已经导入到struts2框架jar文件中。
16.1 Struts2中对json的支持
16.2 查看一个支持的插件文件
struts2-json-plugin-2.2.1.jar文件
16.3 在一个Action类中使用JSON
|
@ParentPackage("json-default") @Namespace("/goods") public class GoodsAction extends ActionSupport { private String jsonText; //用来存放返回的json文本的 @Action(value="save" ,results={ @Result(name=SUCCESS , type="json" , params={"root","jsonText"}) }, interceptorRefs={ @InterceptorRef("defaultStack"), @InterceptorRef("json") } ) public String save() throws Exception { System.out.println(goodsName); JSONObject jsonObject = new JSONObject(); jsonObject.put("username", "peter"); jsonObject.put("isEmpty", true); this.jsonText = jsonObject.toString(); return SUCCESS; } |
|
<script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript"> $(function(){ $.ajax({ url:"goods/save.action", type: "post", data: {"goodsName":"pt"}, dataType:"json", success:function(data){ alert(data); var jsonobj = eval("("+data+")"); alert(jsonobj.isEmpty); if(jsonobj.isEmpty){ alert("用户名可用!"); }else{ alert("用户名不可用!"); } } }); }); </script> |
17 练习:实现struts2整合JSON的异步刷新
17.1 数据库模型
17.2 创建工程并导入struts2和Hibernate框架
17.3 返回映射,和Filter,和Listener
17.4 编写业务方法,提供查询所有商品和按类型查询商品功能
1GoodsDAO.java
|
public List findAll() { log.debug("finding all Goods instances"); try { String queryString = "from Goods order by goodsprice desc"; Query queryObject = getSession().createQuery(queryString); return queryObject.list(); } catch (RuntimeException re) { log.error("find all failed", re); throw re; } } |
2GoodsService.java
|
public class GoodsService { private GoodsDAO goodsDAO = new GoodsDAO(); private TypesDAO typesDAO = new TypesDAO(); public List<Goods> findAll(){ return this.goodsDAO.findAll(); } public List<Goods> findByTypeId(Integer typeId){ return this.typesDAO.findById(typeId).getGoodses(); } } |
17.5 编写Action类返回json文本
|
@ParentPackage("json-default") @Namespace("/goodsjson") public class GoodsByJsonAction extends ActionSupport { @Action(value="find",results={ @Result(type="json",params={"root","jsontext"}) },interceptorRefs={ @InterceptorRef("defaultStack"), @InterceptorRef("json") } ) public String find(){ GoodsService goodsService = new GoodsService(); List<Goods> goodsList = null; if(goodsTypeId == -1){ goodsList = goodsService.findAll(); }else{ goodsList = goodsService.findByTypeId(goodsTypeId); } JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(new String[]{"goodses"}); JSONArray jsonarr = JSONArray.fromObject(goodsList,jsonConfig); this.jsontext = jsonarr.toString(); System.out.println(jsontext); return SUCCESS; } private String jsontext; private int goodsTypeId; public int getGoodsTypeId() { return goodsTypeId; } public void setGoodsTypeId(int goodsTypeId) { this.goodsTypeId = goodsTypeId; } public String getJsontext() { return jsontext; } public void setJsontext(String jsontext) { this.jsontext = jsontext; } }
|
注意:当使用json进行Java对象转换时,要做两件事
1破坏双向映射
2关闭lazy加载
17.6 编写jsp页面上的ajax-使用jQuery
|
<script type="text/javascript" src="js/jquery-1.11.1.js"></script> <script type="text/javascript"> $(function(){ $("#goodsType").change(function(){ $.ajax({ url:"goodsjson/find.action", type: "post", data: {"goodsTypeId":$("#goodsType").val()}, dataType:"json", success:function(data){ alert(data); var jsonarr = eval("("+data+")"); $("#databody").text(""); for(var i=0;i<jsonarr.length;i++){ var trobj = $("<tr>"); $("#databody").append(trobj); var goodsid_tdobj = $("<td>"); goodsid_tdobj.css("color","red").css("font-size","72px"); goodsid_tdobj.text(jsonarr[i].goodsid); trobj.append(goodsid_tdobj); var goodsname_tdobj= $("<td>"); goodsname_tdobj.text(jsonarr[i].goodsname); trobj.append(goodsname_tdobj); var types_tdobj= $("<td>"); types_tdobj.text(jsonarr[i].types.typename); trobj.append(types_tdobj); } } }); });
$("#goodsType").change(); }); </script> |
|
<select id="goodsType" name="goodsType" > <option value="-1">所有类型</option> <c:forEach items="${applicationScope.typeList }" var="type"> <option value="${type.typeId}">${type.typename}</option> </c:forEach> </select> <table> <thead> <tr> <th>商品编号</th> <th>商品名称</th> <th>类型名称</th> </tr> </thead> <tbody id="databody"> </tbody> </table> |
18 Struts2文件上传
18.1 基本流程
1编写JSP页面
|
<form action="upload/up.action" method="post" enctype="multipart/form-data"> <input type="file" name="goodsImg"><br> <input type="submit" value="上传"> </form> |
2在接收的Action类中使用File类型的变量接收
|
@ParentPackage("struts-default") @Namespace("/upload") public class UpLoadAction extends ActionSupport { private File goodsImg; //set&get
|
3在文件上传的业务方法中使用流操作实现文件复制
|
@Action(value = "up", results = { @Result(location = "/index.jsp") }) public String up() { // IO操作 try { InputStream is; is = new FileInputStream(goodsImg); OutputStream os; os = new FileOutputStream("d:/a.jpg"); byte[] bytes = new byte[1024]; int len = -1; while ((len = is.read(bytes)) != -1) { os.write(bytes, 0, len); } is.close(); os.close(); } catch (Exception e) { e.printStackTrace(); } return SUCCESS; } |
18.2 获取上传时文件的更多信息
1String xxxFileName 获得文件的真实名称
2String xxxContentType 获得文件的文件类型,mime协议
|
@ParentPackage("struts-default") @Namespace("/upload") public class UpLoadAction extends ActionSupport { private File goodsImg; private String goodsImgFileName; private String goodsImgContentType; //set&get方法
|
18.3 限制文件上传的类型与大小
Struts2支持在fileUpload拦截器上设置参数来进行限制。
1allowedTypes:指定允许上传的文件的类型,如果存在多种类型,以逗号隔开。
注意:这里添的不是文件的扩展名,而是对应的ContentType。 .jpg --- image/gif
2maximumSize:指定允许上传的文件的最大字节数。
3allowedExtensions:指定允许上传的文件的扩展名。 .jpg
不满足参数条件,则跳转input的<result>
|
@Action(value = "up", results = { @Result(location = "/index.jsp"), @Result(name = INPUT, location = "/input.jsp") }, interceptorRefs = { @InterceptorRef(value = "fileUpload", params = { "allowedExtensions", ".jpg" }), @InterceptorRef(value = "defaultStack") }) public String up() { } |
18.4 一次性上传多个文件
|
<form action="upload/up.action" method="post" enctype="multipart/form-data"> <input type="file" name="goodsImg"><br> <input type="file" name="goodsImg"><br> <input type="submit" value="上传"> </form> |
|
@ParentPackage("struts-default") @Namespace("/upload") public class UpLoadAction extends ActionSupport { private List<File> goodsImg; private List<String> goodsImgFileName; private List<String> goodsImgContentType; |
|
@ParentPackage("struts-default") @Namespace("/upload") public class UpLoadAction extends ActionSupport { private File[] goodsImg; private String[] goodsImgFileName; private String[] goodsImgContentType; |