Struts2框架是WEB开发最常用的MVC框架之一,对Struts1作了很大的改进,例如去除了FormBean,屏蔽Servlet API等特征,使用OGNL导航对象图语言,简化了Action和HTML表单的开发工作。我个人觉得Struts2比Spring MVC要更好用,至少是脱离了Servlet API。
在项目中使用Struts2框架,首先需要集成该框架,集成Struts2框架有几种方法,一种是不与IOC/DI框架直接集成,一种是与IOC/DI框架集成。目前开源的IOC框架主要有Guice和Spring两种框架,这两个框架都支持与Struts2集成。本文中的示例我们将Struts2和Spring集成。
首先我们需要提供一个配置文件,我们主要配置struts2的对象实例化工厂、国际化,还有拦截器等。
配置由Spring实例化Struts2,需要Spring框架的支持
配置国际化编码
完整配置如下
/error.jsp
/error.jsp
/login
编写一个BaseAction类,主要提供分页参数和一些JSON格式转换函数,这样可以在子类中直接应用,而且不用每次都编写转换函数和分页属性。
package com.mcs.core.action;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import net.sf.json.JSONObject;
import org.apache.struts2.ServletActionContext;
import com.mcs.common.PageBean;
import com.opensymphony.xwork2.ActionSupport;
public class BaseAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
@Resource
protected PageBean pageBean;
protected int limit;
protected int start;
/**
* 将对象转换为BEAN
*
* @param clsz
* @return
*/
public T convertJSONToBean(Class> clsz) {
HttpServletRequest request = ServletActionContext.getRequest();
String json = request.getParameter("data");
JSONObject jsonObject = JSONObject.fromObject(json);
return (T) JSONObject.toBean(jsonObject, clsz);
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
}
还要编写一个pageBean对象,这个对象负责将分页信息和分页后的数据返回给客户端,由客户端的AJAX框架进行处理。使用这个pageBean对象可以直接和Ext JS框架整合,我们不用再刀耕火种的做各种数据格式转换了。
package com.mcs.common;
import java.util.List;
import org.springframework.stereotype.Component;
@Component("pageObject")
public class PageBean {
private List rows;
private int total;// 总记录数,-1表示未知
public PageBean() {
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
}
}
在struts2中编写一个Action很简单,和编写Java Bean一样,只需要类、属性和方法就可以完一个Action,编写完的Action如果不加配置的话是不起作用的,Action的配置方法有两种,一种是注解的方式,一种是配置文件的方式。在JAVA EE的开发规范中,JAVA主推注解的方式,所以后续出来的各种JAVA框架也都提供了注解配置的支持,JAVA的注解和C#中的特性原理相似,都是通过一些特殊的标注让代码实现某一特定的功能,这样可以大大简化代码量和配置文件的编写。当然注解并不是万能的,注解是一个静态参数,随JAVA代码一起被编译,而配置文件很多则是在程序运行的时候从文件中读取,所以在项目开发过程中,也可以跟据需要适当的使用一些配置文件。
使用struts2注解需要提供一个struts2的注解插件,这个插件在我们下载过来的开发包里可以找到,如下图:
另外还需要一个JSON插件,因为我们在开发过程中大部份的数据传输都是使用JSON传输的,这个插件我们也可以在struts2的开发包中找到,如下图:
将这件插件拷到你的WEB-INFO/lib目录下,就可以使用注解了。
在web.xml中配置Struts2的过滤器
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
下面介绍Struts2的常用注解:
1、@Action注解用来标注一个方法的URL、返回结果等值,其中value值是该Action的URL,在浏览器中输入该URL则可以访问到这个方法,@Result是返回结果的注解,location则是转发到的具体URL,一般都是一个JSP,当然也可以是HTML。
@Action(value="queryCardType",results={@Result(location="cardType/cardTypeList.jsp")})
2、@Result注解还可以支持JSON类型的参数返回,我们只需要将设置type=”json”,配置params参数即可。其中params中的root是键,pageObject是值,表示该JSON的根节点是从pageObject对象开始转换,pageObject对象是我们定义一个分页对象,用于和前台的Ext JS框架对应。
@Action(value="listCardType",results={@Result(type="json",params={"root","pageObject"})})
pageObject对应的JSON格式数据:
{"rows":[{"cardName":"会员卡","cardNum":"12321","discount":0,"id":"009038ef4c0bd04b014c0c7fc7d70000","maxConsumeSum":300,"maxConsumeTimes":1,"oid":"","remark":"","type":"1","validDays":1,"validMachine":null,"validSetMeal":null,"validTime":"2015-03-12T13:40:43"}],"total":1}
3、@JSON注解用来标注哪些属性不被实例化,这个可以提升页面的响应速度,另外,可以屏蔽其他框架,例如hibernate框架在序列化的时候带来的死循环异常,当然,这个注解不是必需的,我们可以使用params={"root","pageObject"}来代替@JSON注解。 3、@JSON注解用来标注哪些属性不被实例化,这个可以提升页面的响应速度,另外,可以屏蔽其他框架,例如hibernate框架在序列化的时候带来的死循环异常,当然,这个注解不是必需的,我们可以使用params={"root","pageObject"}来代替@JSON注解。
@JSON(serialize=false)//不被序列化
4、@Namespace命名空间注解用来区分不同模块的URL,在一个庞大的开发团队中,很有可能会有URL重名的情况,而加上命名空间后,重名的机率就大大降低了,并且代码结构会更加清晰,所以,大家在开发代码时候尽量加上命名空间的注解。
@Namespace("/basicOperation")
怎么样?是不是很简单,我们只用了少数几个注解就完成了Action的开发工作,当然,我们用其他的MVC框架一样可以完成我们所需要做的事情,但总的来讲,struts2框架是比较成熟的一款MVC框架,安全漏洞也相对较少,MVC框架是网站的安全门户,一旦爆发出安全漏洞,后果不堪设想。因为研究struts2框架漏洞的人很多,struts2团队也在不停的打补丁。完整的Action代码如下:
package com.mcs.basicOperation.action;
import java.util.List;
import javax.annotation.Resource;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.json.annotations.JSON;
import com.mcs.basicOperation.pojo.CardType;
import com.mcs.basicOperation.service.CardTypeService;
import com.mcs.common.PageBean;
import com.mcs.core.action.BaseAction;
@Namespace("/basicOperation")
public class CardTypeAction extends BaseAction{
/**
*
*/
private static final long serialVersionUID = 1L;
@Resource
private CardTypeService cardTypeService;
@Resource(name="pageObject")
private PageBean pageObject;
@Action(value="queryCardType",results={@Result(location="cardType/cardTypeList.jsp")})
public String queryCT(){
return "success";
}
@Action(value="listCardType",results={@Result(type="json",params={"root","pageObject"})})
public String queryListCardType(){
CardType ct=convertJSONToBean(CardType.class);
pageObject.setTotal(cardTypeService.findAllCardType(ct));
List rows = cardTypeService.queryCardType(start, limit, ct);
pageObject.setRows(rows);
return SUCCESS;
}
/**
* 根据ID查询信息
* @param id
* @return
*/
@Action(value="findCardTypeByid",results={@Result(type="json")})
public String findCardTypeByid(String id){
cardTypeService.findCardTypeByid(id);
return SUCCESS;
}
@Action(value="saveCardType",results={@Result(type="json")})
public String saveCardType(){
CardType ct=convertJSONToBean(CardType.class);
cardTypeService.saveCardType(ct);
return SUCCESS;
}
@Action(value="delCardType",results={@Result(type="json")})
public String delCardType(){
CardType ct=convertJSONToBean(CardType.class);
cardTypeService.delCardType(ct);
return SUCCESS;
}
@JSON(serialize=false)//不被序列化
public CardTypeService getCardTypeService() {
return cardTypeService;
}
public void setCardTypeService(CardTypeService cardTypeService) {
this.cardTypeService = cardTypeService;
}
public PageBean getPageObject() {
return pageObject;
}
public void setPageObject(PageBean pageObject) {
this.pageObject = pageObject;
}
}
在前台显示数据: