`
hnylj
  • 浏览: 211260 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于ajax返回值处理的思考

    博客分类:
  • ajax
阅读更多


在高手林立的javaeye舞台上,ajax实在是不值得提及的一个小东西,而现在旧事重提,就是想提提另一种ajax思维。

 

我们知道在ajax应用中,概括起来就是客户端一个异步请求,服务器端返回请求的数据,然后通过js和css更新页面显示的内容,在这个简单的过程中,略显麻烦的往往是返回的数据内容在页面的解析问题。如果只是简单的数字或string,我们用字符串返回就可以了,但当遇到返回的数据结构比较复杂时,使用字符串返回就会使得代码丑陋,难以维护,若使用xml或json格式返回会稍好一些,但这样的数据结构仍然在前端需要一定的解析处理,我觉得有时候我们把服务器端的数据直接构造好再写回到客户端会更加地简单和方便。

 

这种思路的具体做法就是,使用freemarker模板技术,把ajax请求的数据通过模板渲染好,然后将渲染好的模板数据写回到客户端,这样一来,不管你ajax请求的数据格式是何种数据结构,都交给freemarker来处理它,所以你ajax请求的是Map,List,Model,String等都没有问题,通过模板标签组织好数据,然后就当成字符串写回到客户端,对于客户端而言,我的每个ajax请求,你都是给我返回已经组织好数据结构的字符串,我不用做任何处理,就可以直接使用,这简化了前端的解析工作,相当于使用freemarker来屏蔽了这项麻烦的解析工作,而对于freemarker而言,它有很强的数据表现能力,可以循环迭代,逻辑判断等,所以数据的表现由freemarker来完成并不会很难。

 

我知道在很多项目中,常常会采用在java代码中拼凑html标签的方式将数据构造好,然后一并写向客户端,这种方式在一些开源项目中也是存在的,例如log4j,它在HTMLLayout中也是Java代码中嵌入html代码,只是这种方式不好,当html代码变更时,我们需要维护java代码,而通过模板技术,就只要维护模板就可以了。

 

然而这种思路其实也没有什么神奇的,会不会给你的开发带来便利,需要你酌情考虑,下面是这种方式一个具体使用的实例。

 

1.ajax请求处理的Action:

package com.javaeye.hnylj.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.interceptor.ServletResponseAware;

import com.javaeye.hnylj.constant.Constant;
import com.javaeye.hnylj.ftl.FreemarkerProcessor;
import com.javaeye.hnylj.model.ProductInfo;
import com.javaeye.hnylj.service.ProductService;
import com.opensymphony.xwork2.ActionSupport;

/**
 * ajax返回数据处理测试
 * 
 * @since Apr 13, 2010
 */
public class AjaxNewIdeaAction extends ActionSupport implements ServletResponseAware {

	private Logger logger = Logger.getLogger(AjaxNewIdeaAction.class);
	
	private static final long serialVersionUID = 3398440661649729663L;
	
	private HttpServletResponse response;
	
	private FreemarkerProcessor freemarkerProcessor;
	
	private ProductService productService;
	
	public void setServletResponse(HttpServletResponse response) {
		this.response = response;
	}

	public ProductService getProductService() {
		return productService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}
	
	/**
	 * ajax请求处理
	 * 
	 * @return
	 * @throws Exception
	 */
	public String ajaxRequestProductList() throws Exception {
		//获取product信息,productService由spring注入
		List<ProductInfo> productInfoList = productService.queryProductByProductId();
		logger.info("product size: " + productInfoList.size());
		Map<Object, Object> productInfoMap = new HashMap<Object, Object>();
		productInfoMap.put("productInfo", productInfoList);
		freemarkerProcessor = new FreemarkerProcessor();
		//得到渲染好的模板内容
		String result = freemarkerProcessor.init(Constant.PRODUCTINFO_TEMPLATE, productInfoMap, Constant.TEMPLATE_RELATIVE_PATH);
		response.getWriter().write(result);
		productInfoMap.clear();
		logger.info("product info ajax request successfully");
		return null;
	}
}

 

2.freemarker处理类:

package com.javaeye.hnylj.ftl;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;

import org.apache.struts2.ServletActionContext;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * Freemarker处理类
 * 
 * @since Apr 13, 2010
 */
public class FreemarkerProcessor {
	
	/**
	 * 初始化模板引擎
	 * 
	 * @param ftl 模板名称
	 * @param map 模板中需要的参数集合
	 * @param relativePath 模板相对于根路径的相对路径
	 * @throws IOException
	 * @throws TemplateException
	 */
	public String init(String ftl, Map<Object,Object> map, String relativePath) throws IOException, TemplateException {
		Configuration freemarkerCfg = new Configuration();
	    freemarkerCfg.setServletContextForTemplateLoading(ServletActionContext.getServletContext(), relativePath);
	    freemarkerCfg.setEncoding(Locale.getDefault(), "UTF-8");
	    Template template = freemarkerCfg.getTemplate(ftl);
	    template.setEncoding("UTF-8");
	    
	    StringWriter result = new StringWriter();
	    template.process(map, result);
	    return result.toString();
	}
}

 

3.页面使用: 

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>ajax</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<meta http-equiv="pragma" content="no-cache"/>
	<meta http-equiv="cache-control" content="no-cache"/>
	<meta http-equiv="expires" content="0"/>    
	<script language="JavaScript" src="${pageContext.request.contextPath}/js/jquery.js"></script>
	<script language="JavaScript" src="${pageContext.request.contextPath}/js/product.js"></script>
  </head>
  
  <body>
    <div id="main_content">
	  <div class="tab_1"><a href="/index.html">首页</a></div>
	  <div class="tab_2"><a href="javascript:showProduct('flag')">产品列表</a></div>
	  <div id="flag" class="item"></div>
    </div>
  </body>
</html>

当我们点击产品列表就会发起ajax请求。

 

4.product.js内容:

function showProduct(obj) {
	$.ajax({
		url:"/product/ajaxRequestProductList.action",
		type: "POST",
		cache: false,
		success: function(html) {
		   document.getElementById(obj).innerHTML=html;
		},
	    error: function(){
	        document.getElementById(obj).innerHTML="网络连接超时,无法显示数据!";
	        return;
	    }
	});
}

 

5.productInfo.ftl模板内容:

<div class="content">
	<#if productInfo?size != 0> 
	<#list productInfo as productInfo>
	<div class="preview">
	  <div class="preview_detail">
	  	${productInfo.productName}
	  </div>
	  <div class="preview_detail">
	  	${productInfo.productPrice}
	  </div>
	  <div class="preview_detail">
		<a href="/product/productDetail.action?productId=${productInfo.productId}">
		 ${productInfo.productPrice}
		</a>
	  </div>
	</div>
	</#list>
	<#else>    
	<div class="preview">
	  抱歉,没有找到相关信息!
	</div>
	</#if>
</div>

 

主要代码如上,省去了一些其他的代码。

在具体项目中,并不是每一个ajax都采用这种方式,推荐那些返回的数据结构比较复杂时采用这种方式,例如一个ajax的分页列表,一个ajax动态菜单树就可以使用它。另外,这种方式会不会带来性能的问题,我觉得不需要太担忧,因为它最多就是多使用了一点内存。 

 

一个Java技术交流群,一起交流,共同进步,扣扣群号:513086638

 

 

 

分享到:
评论
10 楼 walle1027 2011-01-17  
  兄弟,我们已经这么做了2年了。效果挺好的。省去了中间的数据转换。
9 楼 hnylj 2011-01-17  
oming 写道
请将Constant.PRODUCTINFO_TEMPLATE代码提交上来。谢谢


这个类里面就是几个常量,
其中
Constant.PRODUCTINFO_TEMPLATE 代表模板文件的名称,例如:index.ftl
Constant.TEMPLATE_RELATIVE_PATH 代表模板文件相对于根路径的相对路径,例如:/res/ftl
8 楼 dingchao.lonton 2011-01-17  
这种方式在互联网应用上我觉得是不行的,浪费了很多带宽,如果做企业级的应用是可以的
7 楼 oming 2011-01-17  
请将Constant.PRODUCTINFO_TEMPLATE代码提交上来。谢谢
6 楼 ld57601870 2010-12-23  
嗯,不错的想法,学到了一招。以前都是用代码拼凑。。。
5 楼 satanultra 2010-12-23  
可以用js模板,节省带宽。
4 楼 ahopedog2 2010-12-22  
可以作为返回结构的子集
3 楼 huqiji 2010-09-14  
学习了 谢谢
2 楼 amonlei 2010-04-14  
最最根本的功能就是页面的局部刷新了,
1 楼 leason 2010-04-14  
不错的想法,相当于我们所说的MVC中的V再细化,细化为渲染层(由freemarker完成)和展现层(由js完成),也可以说是把之前用js直接处理action返回的json/xml代码分离成由freemarker来渲染布局,然后再用相对简单的js代码进行展现,对于复杂的数据结构json/xml返回是个不错的选择

相关推荐

    JavaScript实例教程

    2. **函数**:JavaScript的函数是可重用的代码块,可以接受参数并返回值。函数表达式、函数声明、箭头函数和闭包都是重要的概念。在教程中,你将通过实例了解如何定义和调用函数,以及理解闭包带来的作用域和内存...

    JavaScript傻瓜指南

    它的主要功能包括处理用户交互、操作DOM(文档对象模型)、进行异步通信(AJAX)以及创建复杂的网页应用。 在学习JavaScript时,以下几个核心概念是必须要了解的: 1. 变量与数据类型:JavaScript支持基本数据类型...

    vue大型电商项目尚品汇(前台篇)day05.doc

    以下是关于 Vue 大型电商项目尚品汇(前台篇)day05 的知识点: 1. 加入购物车: 加入购物车需要接口操作, vuex 三部曲,actions 里面的操作都是 async 加 await 的操作,async 是负责这个函数的返回值只一个 ...

    jQuery初学实例代码集jQuerydemos

    jQuery,作为一个轻量级的JavaScript库,为网页开发提供了丰富的选择和便利的操作接口,使得DOM操作、事件处理、动画设计和Ajax交互变得更为简单。这个名为"jQuery初学实例代码集jQuerydemos"的资源包,显然是为了...

    xiong-yonggui-java-script-personal-file-master_javascript_

    在这个压缩包中,熊永贵可能分享了他的学习笔记、代码示例、练习项目的源码,通过深入研究这些内容,不仅可以复习JavaScript的基本知识,还能学习到作者的思考方式和编程习惯。对于初学者和有经验的开发者来说,都是...

    javascrip学习资料.rar

    这本书籍涵盖了JavaScript的基础到高级主题,包括变量、数据类型、控制结构、函数、对象、数组、DOM操作、事件处理以及Ajax等。它采用易于理解的图表和互动例子,使初学者能够快速上手,同时也为有经验的开发者提供...

    The Design and Evolution of C++

    异常处理是C++中的错误处理机制,它鼓励程序员采用统一的方式处理程序运行时可能出现的问题,而不是依赖于返回值或全局状态来检测错误。RTTI则为程序提供了在运行时检查对象类型的能力,这对于动态多态性尤其重要。 ...

    完整版 web应用开发 web网站建设实用教程 第3讲 脚本语言 JavaScript JS 语言(共64页).ppt

    实际应用中,JavaScript可用于表单验证、动画效果、Ajax异步请求等。例如,验证邮箱格式: ```javascript function validateEmail(email) { var re = /\S+@\S+\.\S+/; return re.test(email); } ``` 8. **...

    JavaScript练习

    JavaScript是一种广泛应用于网页和网络应用的脚本语言,主要负责客户端的交互和动态...在实际操作中,记得不断思考问题的本质,查阅相关资料,以及尝试多种解决方案,这样才能真正掌握JavaScript这门强大的编程语言。

    JavaScript-30-Project:纯香草JavaScript项目

    7. **AJAX**(异步JavaScript和XML):虽然标签中未提及,但AJAX是现代Web开发中的重要技术,用于在不刷新页面的情况下更新内容。 8. **动画**:使用requestAnimationFrame或setTimeout/clearTimeout实现平滑的动画...

    前端面经-校招版本.docx

    要展现你的思考能力和解决问题的能力,不仅要知道答案,还要阐述解决过程和思考逻辑。 2. **API** 了解并熟悉常见的JavaScript API,如DOM操作、Ajax请求、Promise、fetch、Map、Set等。同时,对HTTP协议的基本...

    Javascript_practicas

    3. **AJAX**:异步JavaScript和XML是用于创建动态网页的技术,允许在不刷新整个页面的情况下从服务器获取数据并局部更新页面。 4. **事件和事件处理**:JavaScript通过事件监听来响应用户的交互,如点击按钮、鼠标...

    THP_PLS_JS

    【标题】"THP_PLS_JS" 指的可能是 "THP (Thoughtful Programming) PLS (Please Love Software) JS (JavaScript)" 的一个项目或者课程名称,这可能是一个关于结合深入思考、热爱软件开发与JavaScript编程的学习资源或...

    JS-Day-2:TIY 作业 6

    6. **AJAX**:虽然这可能是稍后的课程内容,但了解基础的异步请求(如AJAX)对现代Web开发至关重要。学员可能会接触到如何使用`XMLHttpRequest`或`fetch` API来发送HTTP请求,实现页面的无刷新更新。 7. **练习和...

    Vanilla-JavaScript-Projects-Beginners

    6. **Ajax异步通信**:学习如何使用XMLHttpRequest或fetch API与服务器进行异步数据交换,实现页面的无刷新更新。 7. **JSON数据格式**:了解JSON(JavaScript Object Notation),它是数据交换的常见格式,学习...

    js代码-js练习五

    6. **AJAX**:Asynchronous JavaScript and XML,虽然现在通常不再涉及XML,但AJAX仍然是实现网页无刷新更新的重要技术,通过XMLHttpRequest对象或fetch API发送HTTP请求。 7. **ES6及以后的新特性**:包括箭头函数...

    js-exercises:JavaScript 练习

    函数可以作为一等公民,即可以在变量中存储、作为参数传递和作为返回值。 3. **对象与原型**:JavaScript中的对象是属性和方法的集合,可以通过字面量方式或构造函数创建。原型链是JavaScript实现继承的核心机制,...

    estudos-js:将我的研究存储在JavaScript中的存储库

    标题 "estudos-js" 暗示这是一个关于 JavaScript 学习和研究的项目,而描述进一步确认了这一点,它是一个存储作者在 JavaScript 领域探索的库。在这个项目中,作者可能积累了各种代码示例、实验性功能、学习笔记等,...

    chelseaCodes

    5. **异步编程**:JavaScript提供了非阻塞的异步处理方式,如回调函数、Promise和async/await,这在处理耗时操作时非常有用,避免了程序的卡死。 6. **DOM操作**:Document Object Model(DOM)是HTML和XML文档的...

    JavaScript练习:求职面试示例

    6. **AJAX和Fetch API**:用于与服务器进行异步数据交换,掌握XMLHttpRequest或更现代的Fetch API,可以实现前后端数据交互,创建动态网页。 7. **ES6+新特性**:包括箭头函数、模板字符串、解构赋值、Promise、Set...

Global site tag (gtag.js) - Google Analytics