`

WebWork开发JSON接口最佳实践

阅读更多

背景
在以前开发中使用webwork开发的应用大多是jsp页面,随着web2.0概念的深入人心,在页面中使用了大量的ajax调用,在实践中发现服务器端和客户端交互的最好协议是使用json数据格式,因为json的数据格式在javascript中可以很好地处理,并不用做任何额外的处理就能直接被客户端javascript处理。

笔者在本文中着重要关心的是如何通过webwork来开发出优雅,且有重用性的JSON接口程序。

欠优雅的解决方案的思考
假设现在有一个需求,给一个用户id,返回json格式的数据流给客户端。当接收到这个需求我们会想些什么?

大部分人会想:

1.         恩?json数据格式是啥呀?

2.         有没有什么map工具呀能够帮我自动将java对象转换成json数据?

3.         需要改造原先写jsp的那个流程吗?

面对上面这三个问题,稍微有点开发经验的程序员都会自问自答:

1.         问题一:json数据格式,这个有什么难的去google上找找。一看便知。

2.         问题二:这个也到google上去找找,找到一个json-java.jar的包,里面有两个类JSONObject和JSONArray这两个类可以很好地解决javabean对象转换成Json文本。

3.         问题三:既然能够将java对象转换成一个json的数据流,也就是一个String值,那简单了,要只要最后把这个String值在jsp页面上输出就行了

 

于是我们会把这个需求用一下的方式来实现:

1.         写一个UserAction.java

view plaincopy to clipboardprint?
public class UserAction extends ActionSupport {  
 
    private String jsonValue;  
 
    private int userId;  
 
   
 
    private UserService userService;  
 
   
 
    public String execute() throws Exception {  
 
       User user = userService.getUser(this.getUserId());  
 
       JSONObject j = new JSONObject(user);  
 
        // 解析之后的字符串  
 
       this.jsonValue = j.toString();  
 
       return SUCCESS;  
 
    }  
  
public class UserAction extends ActionSupport {

    private String jsonValue;

    private int userId;

 

    private UserService userService;

 

    public String execute() throws Exception {

       User user = userService.getUser(this.getUserId());

       JSONObject j = new JSONObject(user);

        // 解析之后的字符串

       this.jsonValue = j.toString();

       return SUCCESS;

    }
 
 

2.         Xwork配置文件

view plaincopy to clipboardprint?
<action name="useraction"   
 
class="com.opensymphony.webwork.example.UserAction"> 
 
   <result>/json_result.jsp</result> 
 
</action> 
<action name="useraction"

class="com.opensymphony.webwork.example.UserAction">

   <result>/json_result.jsp</result>

</action>
 

 

3.         写json_result.jsp

<%@ page pageEncoding="GBK"%><%@ taglib prefix="ww" uri="/webwork" %>

<ww:property value="jsonValue" />
 


 

现在我就基本实现了返回用户Json数据流的需求。

反复看这个解决方法,在我内心深处始终有一种说不出的感觉,让我浑身不舒服,让我不安,暂时说不出是什么,毕竟已经实现了所有要实现的需求。之后,我又思索良久,终于想出了几条,不知道你同不同意我的想法。

问题:

1.         如果有一天前段工程师告诉我,他们不想用ajax方式来调用用户信息,这时我怎么办?势必要把 private String jsonValue这个成员变量从UserAction中去除掉。这样的改动会不会引起其他问题?现在说不好。按照面向对象的开闭原则来说,对修改应该是封闭的。如果要把jsonValue去掉的话显然对修改是不封闭的。

2.         json_result.jsp 这个页面的功能仅仅只是通过它将action中的一个属性输出,暂时不讨论这个jsp能否实现共用,就这个jsp来说我觉得完全是没有必要的存在的,是一个累赘。如果要在输出流中输出一些信息的话,完全可以在action中拿到outputStream,然后往这个流里面写一些东西。

那么,应该如何来解决这些问题呢?我又开始了思考。。。。。。

想了一会儿,眼前又出现了那张刚开始学MVC设计模式时候的概念图。

 

 

这张图中有三个角色View、Controller、Model,相信大家和我一样对这三个角色的意义应该非常明白了,让我们简单地来回顾一下:

1.         View:展现业务对象模型的实现层,在这里可以具体定义业务对象如何展现。

2.         Controller:可以控制如何调用业务逻辑模型,选择哪个视图(view)展现给终端客户端。

3.         Model:这个不用多说了,是业务逻辑模型,它只关心业务逻辑之间的具体业务逻辑,至于是应用在C2C呢还是B2B的应用场景它都不关心。

结合上面的例子,来分析一下吧,UserAction这个类就应该是一个标准的controller,json_result.jsp这个页面就应该是一个View(视图)。按照mvc模式的要求view和Controller是解耦的各自应该是可以独立地变化,但是我们发现如果要把json的数据格式改变成xml或者其他的数据格式的话,必须改动Controller(UserAction)了,再查查为啥必须改动controller呢?原来将定义模型如何展示规则的业务逻辑放到了action中,对了就是那段代码:

view plaincopy to clipboardprint?
。。。。。  
 
JSONObject j = new JSONObject(user);  
 
        // 解析之后的字符串  
 
this.jsonValue = j.toString();  
 
。。。。。。。。。  
  
。。。。。

JSONObject j = new JSONObject(user);

        // 解析之后的字符串

this.jsonValue = j.toString();

。。。。。。。。。
 
 

就是因为这段代码把Controller和View耦合在了一起,而且是紧紧地耦合在了一起,使得他们不能各自独立地变化。

所以现在的设计是违反mvc设计模式的。

优化、重构
知道了原因,我们就可以来着手改造了,改造的主要内容就是解耦,将controller和View解耦。

1.         首先,将JSONObject从action中移出去,将UserAction改造成如下:

public class UserAction extends ActionSupport {

    private int userId;

    private UserService userService;

    public String execute() throws Exception {

       User user = userService.getUser(this.getUserId());

       this.setUser(user);

       return SUCCESS;

    }

。。。。。。
 


2.         新添加一个webwork的Result类型

 

添加一个新的MyJsonResult继承于JSONResult(webwork2.2.7中新添加的一个类),在新的MyJsonResult中覆写父类中的方法getJSONObject();主要代码如下:

view plaincopy to clipboardprint?
public class JsonArrayResult extends JSONResult {  
 
    @Override 
 
    protected JSONObject getJSONObject(ActionInvocation invocation)  
 
           throws JSONException {  
 
       ActionContext actionContext = invocation.getInvocationContext();  
 
       Object obj = actionContext.getValueStack().findValue(  
 
              this.getJSONObjectProperty());  
 
    。。。。。。。。。。。。。。  
 
   
 
       JSONObject jo = new JavaScriptJSONObject();  
 
       jo.put("result", obj);  
 
       return jo;  
 
    }  
 
。。。。。。。。。。。。。。。。。。。。  
  
public class JsonArrayResult extends JSONResult {

    @Override

    protected JSONObject getJSONObject(ActionInvocation invocation)

           throws JSONException {

       ActionContext actionContext = invocation.getInvocationContext();

       Object obj = actionContext.getValueStack().findValue(

              this.getJSONObjectProperty());

    。。。。。。。。。。。。。。

 

       JSONObject jo = new JavaScriptJSONObject();

       jo.put("result", obj);

       return jo;

    }

。。。。。。。。。。。。。。。。。。。。
 
 

将这个新的Result配置在xwork.xml中

view plaincopy to clipboardprint?
<package name="store" extends="default" namespace="/store"> 
  <result-types>   
   <result-type name="jsonArrayResult" class="com.koubei.store.action.json.JsonArrayResult" />   
</result-types> 
</package> 
  
<package name="store" extends="default" namespace="/store">
  <result-types>
   <result-type name="jsonArrayResult" class="com.koubei.store.action.json.JsonArrayResult" />
</result-types>
</package>
 
 

3.         改造action配置

view plaincopy to clipboardprint?
<action name="useraction" class="com.opensymphony.webwork.example.UserAction"> 
<result name="success" type="jsonArrayResult"> 
  <param name="jSONObjectProperty">user</param> 
</result> 
</action> 
<action name="useraction" class="com.opensymphony.webwork.example.UserAction">
<result name="success" type="jsonArrayResult">
  <param name="jSONObjectProperty">user</param>
</result>
</action>
 

 

好了,改造完成了。这里最主要的一个东西,就是添加了一个自定义Result将json展示的业务逻辑封装到了这个Result中。改造之后符合了MVC模式的要求,Controller和View可以各自独立地变化。可以省去一个累赘的jsp文件。

结束语
   促使笔者写这篇文章的原因是笔者参加口碑的一个活动页面开发过程中,有一个返回给客户端Json数据的需求,在查看了其他同事编写的代码(本文档的未优化前的解决方案),基本上都是这样写的,结合自己以往学习MVC模式的经验,觉得有可以重构之处。

老实说这样的代码改动来说的确很小,而且对系统运行的性能也没有多大帮助,但是笔者总相信,再好的架构,再好的系统也是从一个个微小的细节组合起来的。只有将每一个细小的细节,每一个流程都处理好,都和谐地运行。才能在更高层次上做优化,正所谓聚沙成塔,就是这个道理。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mozhenghua/archive/2009/12/09/4972886.aspx

分享到:
评论

相关推荐

    WebWork.in.Action English

    - **最佳实践**:本书还提供了一系列关于如何使用 WebWork 构建高质量应用程序的最佳实践建议。这些指南涵盖了从项目结构到编码规范等多个方面。 ### 附录:WebWork 架构 - 最后的附录部分详细介绍了 WebWork 的...

    struts.rar

    在使用Struts开发时,应注意以下最佳实践:保持Action和ActionForm轻量级,合理划分Action和ActionForm的职责,避免在Action中进行过多的业务逻辑处理;使用拦截器进行通用操作,减少代码重复;充分利用框架提供的...

    struts2最新课件ppt

    通过这个课件,我们可以系统学习Struts2的各个方面,包括基础概念、配置、核心组件、最佳实践等。结合实际项目案例,将理论知识转化为实际操作技能,提升Java web开发能力。同时,了解最新的jar包和API文档,能确保...

    Struts2技术内幕 权威指南

    《Struts2技术内幕 权威指南》是一本深入探讨Struts2框架的书籍,涵盖了该框架的核心概念、设计模式以及最佳实践。书中可能包含了以下几个关键知识点: 1. **Struts2架构**:Struts2的核心架构基于拦截器...

    struts2的速成教程,充电的都来看了

    ### Struts2速成教程知识点概览 ...以上内容覆盖了Struts2框架的关键知识点,旨在帮助初学者快速掌握该框架的核心技术和最佳实践。通过学习这些知识点,开发者能够更好地利用Struts2来构建高效、稳定的Web应用程序。

    struts基础源代码以及注释

    Struts是Apache软件基金会下的一个开源项目,主要是一款基于MVC(Model-View-Controller)设计模式的Java Web应用程序框架。...同时,通过对比不同版本的源码,可以看到框架的演进过程,学习软件设计中的最佳实践。

    Struts2 技术内幕——深入解析Struts2架构设计与实现原理

    为了更好地利用Struts2的强大功能,以下是一些最佳实践建议: - **模块化设计**:将应用划分为多个逻辑上独立的模块,每个模块都可以独立部署。 - **使用Spring进行依赖注入**:Spring框架可以很好地与Struts2集成...

    java序列化

    Java序列化是Java平台中的一种标准机制,允许将对象的状态转换为字节...理解并掌握其工作原理和最佳实践对于任何Java开发者来说都是非常有价值的。同时,结合如Struts2这样的框架,可以进一步提高开发效率和代码质量。

Global site tag (gtag.js) - Google Analytics