struts2作为一个mvc框架,请求一个方法,返回一个页面,当post请求成功之后,跳转到success页面,大多数情况下能够满足我们的要求,但是web开发中ajax技术的使用是不可避免的,我们知道ajax请求大多数情况下需要的数据是json格式。我们如何让struts这个mvc框架作为一个restful服务器,提供rest api,显得尤为重要,虽然这时候不能完全体现mvc框架的职能。
struts2实现json请求,可以有两种方式:
第一种方式,如果是maven工程,那么就需要在pom.xml中加入struts2-json-plugin依赖。
org.apache.struts
struts2-core
${struts2.version}
org.apache.struts
struts2-json-plugin
${struts2.version}
编写action,其中,方法返回结果不重要,也不需要指定资源,但是返回给ajax请求的结果需要声明在action中,并提供get,set方法。我们只需要给请求结果赋值。
package com.xxx.struts.action;
import com.opensymphony.xwork2.Action;
import com.xxx.struts.entity.User;
public class ApiAction {
private User user;
public User getUser(){return this.user;}
public void setUser(User user){this.user = user;}
public String json(){
user = new User();
user.setId("1");
user.setUsername("ajax返回json");
user.setPassword("123456");
System.out.println("method get call.");
return Action.SUCCESS;
}
}
这里,我们返回的是User对象的变量user,我们需要在json()方法中给user赋值。
配置struts.xml
这样就完成了我们的一个json请求的编写,我们查看一下运行结果:
请求确实返回了json格式数据,而且json编码是utf-8。可以支持中文。
第二种方式,借助输出流,来向请求响应一个json格式的数据。
首先我们需要引入依赖包json-lib,后面我们需要JSONObject来将java pojo对象转换为json对象。
net.sf.json-lib
json-lib
2.4
jdk15
这里需要注意的是maven仓库中对json-lib的依赖描述是
这样,我们其实是无法下载到这个依赖包的,官方针对该版本提供了两个jdk版本的包,我们这里需要的是jdk15。所以还需要在依赖中加上这么一个属性:
从这个依赖图可以看到json-lib还依赖了其他的ezmorph,commons-beanutils,commons-collections,commons-lang,commons-logging,如果不是maven项目,需要将这些依赖包都加入到classpath下。
加入了依赖之后,我们编写一个BaseAction,实现方法ajax,用来将java对象转换为json对象,并输出。我们需要实现json返回请求的类可以继承该类。
package com.xxx.struts.action;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.struts2.ServletActionContext;
public class BaseAction {
public String ajax(Object out){
PrintWriter writer = null;
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("application/json;charset=utf-8");
writer = response.getWriter();
response.setDateHeader("Expires", 0);
JSONObject object = JSONObject.fromObject(out);
writer.write(object.toString());
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(writer!=null){
writer.close();
}
}
return null;
}
}
编写action类,实现返回json数据方法。
package com.xxx.struts.action;
import java.util.HashMap;
import java.util.Map;
public class UserAction extends BaseAction{
public String json(){
Map result = new HashMap();
result.put("code", 200);
result.put("msg", "success");
result.put("error", "没有错误信息");
return ajax(result);
}
}
编写完这些就可以测试,我们访问http://localhost:8080/struts/user!json.action
这种通过PrintWriter返回的方式可以不用配置struts.xml,但是需要注意一个地方,就是我们在设置返回类型和编码的时候,需要在resonse.getWriter()之前。
如果顺序颠倒,那么这种设置就不生效。默认的编码就会变为iso-8859-1,如果返回结果中带有中文,那么就会出现中文乱码,如下所示:
这种方式实现的json请求,方法实现中返回一个null视图,表示无结果视图,响应结果通过输出流输出。
这种借助response.getWriter()来获取输出流,并向请求写一个json格式数据的方式,还可以通过jackson-databind库来实现,我们再项目中加入jackson-databind,jackson-core,jackson-annotations三个jar包,如果是maven项目,可以直接在pom.xml文件中加入以下依赖。
通过jackson-databind提供的api,我们不仅可以实现返回json数据格式,还可以通过注解@IgnoreProperties指定返回实体中被过滤的字段,从而避免用户隐私或者敏感数据泄露问题。
在我们在UserAction中添加两个请求ajax的方法,代码如下:一个是用jackson,一个是用默认的输出。
public String ajaxByJackson(){
User user = new User();
user.setId("1001");
user.setUsername("csdn");
user.setPassword("md5encode");
return ajaxByJackson(user);
}
public String ajaxByDefault(){
User user = new User();
user.setId("1001");
user.setUsername("csdn");
user.setPassword("md5encode");
return ajax(user);
}
我们实现ajaxByJackson(Object obj)方法,这里面使用了jackson-databind提供的类ObjectMapper。
public String ajaxByJackson(Object obj){
PrintWriter output = null;
try {
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("application/json;charset=UTF-8");
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getWriter(), obj);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(output!=null)output.close();
}
return null;
}
我们定义一个User实体类,用来像ajax请求中传入数据。
@JsonIgnoreProperties({"password"})
public class User {
private String id;
private String username;
private String password;
...省略get,set方法
}
我们通过默认的ajax方法,返回的数据格式是json格式,但是password没有被过滤掉。
而ajaxByJaskson()方法,通过@IgnoreProperties设置过滤字段passsword后,成功过滤了password字段。