A-A+

全面解析jquery中ajax从前端到后端的过程

2016年01月11日 前端设计 暂无评论 阅读 5 views 次

很多朋友对ajax理解不是很透彻,特别是一些没有学过编程语言的前端开发者,本文我们来全方位理解 jquery中ajax 从前端到后端 完整过程解析。

1.get方式访问浏览器时,常加参数缘由:

GET访问浏览器是等幂的,就是一个相同的URL只有一个结果[相同是指整个URL字符串完全匹配],所以第二次访问的时候如果 URL字符串没变化,浏览器是 直接拿出了第一次访问的结果。POST则认为是一个变动性访问 (浏览器认为POST的提交必定是有改变的)防止GET的等幂访问就在URL后面加上?+new Date();[总之就是使每次访问的URL字符串不一样的]。设计WEB页面的时候也应该遵守这个原则。

2.ajax方式中的get和post的区别:

Get方式:

用get方式可传送简单数据,但大小一般限制在1KB下,数据追加到url中发送(http的header传送),也就是说,浏览器 将各个表单字段元素及其数据按照URL参数的格式附加在请求行中的资源路径后面。另外最重要的一点是,它会被客户端的浏览器缓存起来,那么,别人就可以从浏览器的历史记录中,读取到此客户的数据,比如帐号和密码等。因此,在某些情况下,get方法会带来严重的安全性问题。总之,GET方式传送数据量小,处理效率高,安全性低,会被缓存,而POST反之。

Post方式:

当使用POST方式时,浏览器把各表单字段元素及其数据作为HTTP消息的实体内容发送给Web服务器,而不是作为URL地址的参数进行传递,使用POST方式传递的数据量要比使用GET方式传送的数据量大的多。

接下来,看代码中我们的前台:

我们看到前台的代码中有:

当后台收到前端的$.ajax( )中的路径时(url: "/report/loadAssetsTransactionsByRegionTime"),我们在web.xml中配置了拦截器,这部分是由Struts2的核心控制器:StrutsPrepareAndExecuteFilter来完成的,它包括两个部分StrutsPrepareFilter和StrutsExecuteFilter。

  1. <filter>  
  2.     <filter-name>struts-prepare</filter-name>  
  3.     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>  
  4.   </filter>  
  5.   <filter>  
  6.     <filter-name>struts</filter-name>  
  7.     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>  
  8.   </filter>  

如上所示,是struts2核心控制器代码在web.xml中的配置文件,映射路径一般映射到"/*",再来看下面具体的拦截动作

  1. <filter-mapping>  
  2.     <filter-name>struts-prepare</filter-name>  
  3.     <url-pattern>/main/*</url-pattern>  
  4.     <url-pattern>/inspection/*</url-pattern>  
  5.     <url-pattern>/report/*</url-pattern>  
  6.     <url-pattern>/audit/*</url-pattern>  
  7.     <url-pattern>/ajax/*</url-pattern>  
  8.     <url-pattern>/location/*</url-pattern>  
  9.     <url-pattern>/admin/*</url-pattern>  
  10.     <url-pattern>/calculation/*</url-pattern>  
  11.     <url-pattern>/conf/*</url-pattern>  
  12.     <dispatcher>REQUEST</dispatcher>  
  13.     <dispatcher>FORWARD</dispatcher>  
  14. </filter-mapping>  
  15. <filter-mapping>  
  16.     <filter-name>struts</filter-name>  
  17.     <url-pattern>/main/*</url-pattern>  
  18.     <url-pattern>/inspection/*</url-pattern>  
  19.     <url-pattern>/report/*</url-pattern>  
  20.     <url-pattern>/audit/*</url-pattern>  
  21.     <url-pattern>/ajax/*</url-pattern>  
  22.     <url-pattern>/location/*</url-pattern>  
  23.     <url-pattern>/admin/*</url-pattern>  
  24.     <url-pattern>/calculation/*</url-pattern>  
  25.     <url-pattern>/conf/*</url-pattern>  
  26.     <dispatcher>FORWARD</dispatcher>  
  27. </filter-mapping>  

struts中核心是Action和拦截器,struts2的action必须放在一个指定的包空间下定义。struts.xml文件中package元素用于定义包配置。struts2框架有两个核心配置文件,其中struts.xml文件主要负责管理应用中的Action映射,及Action处理结果和物理资源之间的映射关系。除此之外,Struts2框架还包含了一个struts.properties文件,该文件主义了Struts2框架的大量常量属性。但通常推荐也是在struts.xml文件中来配置这些常量属性。

  1. <!-- 定义处理请求URL为dailyMonitoringAction的Action -->  
  2. <action name="loadAssetsTransactionsByRegionTime" class="dailyMonitoringAction" method="loadAssetsTransactionsByRegionTime">            
  3.   <!-- 定义处理结果字符串和资源之间的映射关系 ,该action中指定了返回的type为json-->  
  4.     <result name="success" type="json">  
  5.       <!-- 指定json返回的域 -->  
  6.         <param name="includeProperties">*</param>  
  7.     </result>  
  8. </action>  

然后我们再看Action中,可以采用SpringMVC的方式来传递参数,也可以使用struts2的方式来传递参数,如下是使用SpringMVC的方式来传递数据。

  1. @RequestMapping(value="/loadAssetsTransactionsByRegionTime", method=RequestMethod.GET)    
  2.     public String loadAssetsTransactionsByRegionTime(String starttime, String endtime, HttpServletResponse response) {  
  3.         String startTime = starttime;  
  4.         String endTime = endtime;  
  5.         lineVM = new LineChartVM();  
  6.         lineVM.setTitle("Assets Transactions By Region");  
  7.         lineVM.setyAxisName("Transactions");  
  8.         Map<String, Map<String, Double>> assetRegionMap = dailyMonitoringService  
  9.                 .loadAssetRegionTransactionTime(startTime, endTime);  
  10.         lineVM.setCategories(new ArrayList<String>(assetRegionMap.keySet()));  
  11.         Map<String, List<Double>> seriesMap = pivotingMap(assetRegionMap, 0D);  
  12.         List<ChartSerieVM> seriesList = new ArrayList<ChartSerieVM>();  
  13.         for (String key : seriesMap.keySet()) {  
  14.             ChartSerieVM chartSerieVM = new ChartSerieVM();  
  15.             chartSerieVM.setName(key);  
  16.             chartSerieVM.setData(seriesMap.get(key));  
  17.             seriesList.add(chartSerieVM);  
  18.         }  
  19.         lineVM.setSeries(seriesList);  
  20.         return SUCCESS;  
  21. }  

或者,我们可以使用Struts2来解决这个问题,我们以http://127.0.0.1:8080/demo/index.jsp?name=aty&age=20为例,struts2的action中获取请求参数值,总的来说有2种方式:第一种在action中定义同名变量,提供get/set方法

  1. public class DemoAction  
  2. {  
  3.     private String name;  
  4.     private int age;  
  5.        
  6.     public String getName()  
  7.     {  
  8.         return this.name;  
  9.     }  
  10.        
  11.     public void setName(String name)  
  12.     {  
  13.         this.name = name;  
  14.     }  
  15.        
  16.     public int getAge()  
  17.     {  
  18.         return this.age;  
  19.     }  
  20.        
  21.     public void setName(int age)  
  22.     {  
  23.         this.age = age;  
  24.     }  
  25. }  

又或者,使用手动获取HttpServletRequest,然后调用request.getParameter()

  1. public class DemoAction  
  2. {     
  3.     public String execute()  
  4.     {  
  5.         HttpServletRequest request = ServletActionContext.getRequest();  
  6.         String name = request.getParameter("name");  
  7.         String age = request.getParameter("age");  
  8.     }  
  9. }  

这2种方式有什么差别呢?很显然是成员变量和局部变量的区别。我们知道一个action可以定义多个public方法,用来处理不同的前台请求。如 果同一个请求参数,会被多个方法使用,那么就适合用第一种方式;如果一个请求参数,仅仅只会被一个方法使用,就适合使用第二种方式。原则就是:保证同一个 参数名称在action代码中只出现一次(避免重复),而且变量的作用范围要尽可能的小(代码内聚)。将http请求参数封装到实体类的方式,可以参考struts2的模型驱动http://blog.csdn.net/li_tengfei/article/details/6098145。下面我们看下,如何将参数封装到Map和List中。

  1. public class DemoAction  
  2. {     
  3.     private Map<string,string> requestMap = new HashMap<string,string>();  
  4.        
  5.     private List<user> requestList = new ArrayList<user>();  
  6.        
  7. }</user></user></string,string></string,string>  

js将参数封装到list中

  1. var params = {};  
  2. params["requestList[0].id"] = $("#person_id").attr("value");  
  3. params["requestList[0].username"] = "aty";  
  4. params["requestList[0].password"] = "123";  
  5. params["requestList[0].age"] = 25;  
  6. params["requestList[0].address"] = "";  
  7.    
  8. $.post(url,params);  

js将参数封装到map

  1. var params = {};  
  2. params["requestMap.id"] = $("#person_id").attr("value");  
  3. params["requestMap.username"] = "aty";  
  4. params["requestMap.password"] = "123";  
  5. params["requestMap.age"] = 25;  
  6. params["requestMap.address"] = "";  
  7.    
  8. $.post(url,params);  

可以看到使用Map接收http请求参数, 和使用实体类没有差别,在js和java端的做法也都是相同的。

补充几个知识点:

1、springMVC和struts2的对比 (参考:http://blog.csdn.net/gstormspire/article/details/8239182)

我们采用struts2时采用的传统的配置文件的方式,并没有使用传说中的零配置。spring3 mvc可以认为已经100%零配置了(除了配置spring mvc-servlet.xml外)。

第一,机制:spring mvc的入口是servlet,而struts2是filter(这里要指出,filter和servlet是不同的。以前认为filter是 servlet的一种特殊),这样就导致了二者的机制不同,这里就牵涉到servlet和filter的区别了。

第二,性能:spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法, 粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,把request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通过setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。

第三,参数传递:struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。

第四,设计思想上:struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。

第五,spring mvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上spring3 mvc就容易实现restful url。struts2是类级别的拦截,一个类对应一个request上下文;实现restful url要费劲,因为struts2 action的一个方法可以对应一个url;而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3 mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间 也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦。

故,总结如下:“struts2是类级别的拦截, 一个类对应一个request上下文,springmvc是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上 spring3 mvc就容易实现restful url 。而struts2的架构实现起来要费劲,因为struts2 action的一个方法可以对应一个url。而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。spring3mvc的方法之间基本上独立的,独享request response数据,请求数据通过参数获取,处理结果通过ModelMap交回给框架。方法之间不共享变量,而struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的。这不会影响程序运行,却给我们编码 读程序时带来麻烦。由于Struts2需要针对每个Request进行封装,把Request,Session等Servlet生命周期的变量封装成一个一个Map,供给每个Action使用,并保证线程安全。所以在原则上,是比较耗费内存的。

2、JSTL在项目中的使用:JSTL(JSP Standard Tag Library,JSP标准标签库),是一个不断完善的开放源代码的JSP标签库。

3、java中Map接口的使用:map接口按照的键值对方式组合,key是索引,本身也是对象,这点是区别于数组的。1,2,3,4...(数组的索引只能是下标)使用的时候,一般选择的是Map接口的子类,而不直接使用Map接口。(Collection容器中包含Set和List接口,Set中又包含HashSet,List中包含LinkedList和ArrayList;单独的Map接口中只有HashMap)。

Java 中某些最常用的类。 最常用的集合类是List 和 接口Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形,其中的数据有顺序且可以重复。而Set中数据无顺序且不可以重复。

先来看我们的Object类中的两个方法在Map接口中的覆盖实现:equals(obj)方法,用于比较指定对象与此Map的等价性;hascode()方法,返回此Map的哈希吗。(那么问题来了,java中使用hashcode()方法有什么用呢?使用hascode()方法用于比较两个对象是否相等,当两个对象的hascode()值不相等的时候,那么两个对象肯定不相等;如果两个对象的hascode()方法相等,再进一步比较equals()方法,由于hascode()的值是int,比较它们速度回更快,所以可以提升比较的时候的效率);

每个java对象都有一个唯一的标识,object类中的hash方法就是直接返回对象的这个内部id号,与string的hash方法是不同的,object的hash方法能够用来区分不同的对象.因为原始的object对象没有任何有意义的值可用来计算哈希。唯一的id充分反映了面向对象的编程思想。

标签:

给我留言