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。

<filter>
    <filter-name>struts-prepare</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
  </filter>
  <filter>
    <filter-name>struts</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
  </filter>

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

<filter-mapping>
    <filter-name>struts-prepare</filter-name>
    <url-pattern>/main/*</url-pattern>
    <url-pattern>/inspection/*</url-pattern>
    <url-pattern>/report/*</url-pattern>
    <url-pattern>/audit/*</url-pattern>
    <url-pattern>/ajax/*</url-pattern>
    <url-pattern>/location/*</url-pattern>
    <url-pattern>/admin/*</url-pattern>
    <url-pattern>/calculation/*</url-pattern>
    <url-pattern>/conf/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>struts</filter-name>
    <url-pattern>/main/*</url-pattern>
    <url-pattern>/inspection/*</url-pattern>
    <url-pattern>/report/*</url-pattern>
    <url-pattern>/audit/*</url-pattern>
    <url-pattern>/ajax/*</url-pattern>
    <url-pattern>/location/*</url-pattern>
    <url-pattern>/admin/*</url-pattern>
    <url-pattern>/calculation/*</url-pattern>
    <url-pattern>/conf/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

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

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

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

@RequestMapping(value="/loadAssetsTransactionsByRegionTime", method=RequestMethod.GET)  
    public String loadAssetsTransactionsByRegionTime(String starttime, String endtime, HttpServletResponse response) {
        String startTime = starttime;
        String endTime = endtime;
        lineVM = new LineChartVM();
        lineVM.setTitle("Assets Transactions By Region");
        lineVM.setyAxisName("Transactions");
        Map<String, Map<String, Double>> assetRegionMap = dailyMonitoringService
                .loadAssetRegionTransactionTime(startTime, endTime);
        lineVM.setCategories(new ArrayList<String>(assetRegionMap.keySet()));
        Map<String, List<Double>> seriesMap = pivotingMap(assetRegionMap, 0D);
        List<ChartSerieVM> seriesList = new ArrayList<ChartSerieVM>();
        for (String key : seriesMap.keySet()) {
            ChartSerieVM chartSerieVM = new ChartSerieVM();
            chartSerieVM.setName(key);
            chartSerieVM.setData(seriesMap.get(key));
            seriesList.add(chartSerieVM);
        }
        lineVM.setSeries(seriesList);
        return SUCCESS;
    }

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

public class DemoAction
{
    private String name;
    private int age;
     
    public String getName()
    {
        return this.name;
    }
     
    public void setName(String name)
    {
        this.name = name;
    }
     
    public int getAge()
    {
        return this.age;
    }
     
    public void setName(int age)
    {
        this.age = age;
    }
}

 

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

public class DemoAction
{   
    public String execute()
    {
        HttpServletRequest request = ServletActionContext.getRequest();
        String name = request.getParameter("name");
        String age = request.getParameter("age");
    }
}

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

public class DemoAction
{   
    private Map<string,string> requestMap = new HashMap<string,string>();
     
    private List<user> requestList = new ArrayList<user>();
     
}</user></user></string,string></string,string>

js将参数封装到list中

var params = {};
params["requestList[0].id"] = $("#person_id").attr("value");
params["requestList[0].username"] = "aty";
params["requestList[0].password"] = "123";
params["requestList[0].age"] = 25;
params["requestList[0].address"] = "";
 
$.post(url,params);

js将参数封装到map

var params = {};
params["requestMap.id"] = $("#person_id").attr("value");
params["requestMap.username"] = "aty";
params["requestMap.password"] = "123";
params["requestMap.age"] = 25;
params["requestMap.address"] = "";
 
$.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,value>的键值对方式组合,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充分反映了面向对象的编程思想。

4、几个推荐博客:

介绍(hascode()的作用)   http://www.cnblogs.com/dolphin0520/p/3681042.html

结论:1.hashCode方法的存在是为了减少equals方法的调用次数,从而提高程序效率。

   2.在设计一个类的时候为需要重写equals方法,比如String类,但是千万要注意,在重写equals方法的同时,必须重写hashCode方法。

介绍了字符串相似度算法(在DNA对比,网页聚类等方面都有用武之地)http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2765633.html

经典的KMP算法 http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html

结论:1.http://www.ruanyifeng.com/blog/algorithm/ 这是这个作者所有关于数学和算法的帖子,都相当精彩。

 

 

  

 

  

  

 

 

 


 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值