从MVC到Ajax再到前后端分离的思考

  前言

  一位小妹去面试前端,前端leader问了"什么是ajax?",答:“接收后台的数据,然后然后自己填充和渲染样式”;一位小哥去面试后台,技术经理问了“什么是ajax?”,答:“在不需重新加载整个网页的情况下,发送异步请求,返回json数据给前端”。准确答案到底是什么?Ajax到底属于前端还是属于后端?前端(或者后端)到底需不需要懂得Ajax?Ajax请求与普通的http请求有什么区别?数据库中的数据通过Ajax请求和普通请求下分别是怎么传递到前台的...等等一些问题,似乎需要静下心来理一理。

  MVC篇

  最典型的MVC就是JSP + servlet + javabean的模式,不少人的web起点应该也是这个,记得当时看到最多的问题就是JSP和Servlet区别,后来随着Struts 、Spring MVC等框架出来,MVC被谈论的更多了,越来越多的人开始想要深入学习和理解它,同时也有越来越多的问题开始围绕MVC展开。基本的概念:MVC = Model View Controller = 模型-视图-控制器,太过于概念化的东西确实不太好理解,也许框架都用了好几年,一问MVC还是会懵。不过还是Talk is cheap,下面以Spring MVC + jsp的开发过程示例,同时也是数据在普通http请求后从数据库传递到前端的过程。

  背景:ssm项目中,将数据库中TBL_PERSON表的记录全部获取,在前端以表格呈现出来,即<table>标签下(因为自己写的样式实在太丑,重点关注过程吧)

  1.Controller层关键代码

package com.mmm.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mmm.pojo.Person;
import com.mmm.service.PersonService;

@Controller
@RequestMapping("person")
public class PersonController {
    
    @Autowired
    PersonService personService;
    
        /**
     * 框架跳转页面默认是forward,也就是请求转发
     * 这里的model设置的属性,在jsp页面也能直接通过el表达式获取
     * */
    @RequestMapping(value="httplist")
    public String httplist(Model model) {
        List<Person> list = personService.selectAll();
        model.addAttribute("list", list);
        return "person/list";
    } 
    
    ......
}

  2.jsp页面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>   
    <title>Person列表</title>   
  </head>
  
  <body>
    <table>
        <tr>
            <th>姓名</th>
            <th>性别</th>
        </tr>
        <c:forEach var="i" begin="0" end="${list.size() }">
            <tr>
                <td>${list[i].name }</td>
                <td>${list[i].gender }</td>
            </tr>
        </c:forEach>
    </table>
  </body>
</html>

  3.tomcat启动项目,地址栏输入http://localhost:8081/mm-web/person/httplist,即可看到如下页面,获取到了数据库中完整数据

  Ajax篇

  传统web开发在没有应用Ajax技术的时候,往往页面是用jsp,而这也让我们看到MVC的不足,视图与控制器间的过于紧密的连接,每次请求必须经过“控制器->模型->视图”这个流程,当java脚本 + 各种表达式 + html代码 +javascript代码混杂一块的时候,简直痛不欲生,代码可读性十分差,而且给后面维护和修改代码的人带来很大阻碍。再说下Ajax,首先简单介绍下,Ajax = 异步 Javascript 和 XML,听名字不难发现,并未涉及到后端java代码,核心对象XMLHTTPRequest(可扩展超文本传输请求),通过它,我们可以在不刷新页面的情况下,发送异步请求至后台,并获取后台返回的json数据。说的简单点,就是不刷新或者跳转页面,发送请求然后拿数据,在这里,比较重要的一点,主动权是在前台这边,前台拿到数据后再根据需求去填充数据内容,渲染样式,实现页面效果。而且由于Ajax基于的Javascript属于前端脚本,并不依赖于jsp环境,页面写Html也是可以的。所以下面以Spring MVC + Ajax + jsp示例(这里的ajax采用Jquery写法,工作中一般也是应用Jquery较多,原生js写法相较繁琐一点,这里就不展示了),同时为了区别返回json数据和直接跳转页面的区别,在控制器中写了两个方法,一个用于跳转页面,但并未拿到数据,等页面载入后,通过js发起Ajax请求到控制层拿到数据,再动态填充到页面,并且无需刷新页面,所以后面我们在地址栏输入地址后,看上去像一次请求,其实一共两次。

  1.Controller层关键代码

package com.mmm.web;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mmm.pojo.Person;
import com.mmm.service.PersonService;

@Controller
@RequestMapping("person")
public class PersonController {
    
    @Autowired
    PersonService personService;
    
    /**
     * 这里接受地址栏请求,仅起到转发页面作用,并未传递到我们数据库的内容
     * */
    @RequestMapping(value="toPage")
    public String httplist() {
        return "person/list";
    } 
    
    /**
     * 这里@ResponseBody代表该方法接受请求后不是跳转页面,而是直接返回json数据
     * 注意引入json相关jar包,还有spring MVC配置中不要漏掉<mvc:annotation-driven/>
     * */
    @RequestMapping(value="ajaxlist")
    @ResponseBody
    public List<Person> ajaxlist() {
        List<Person> list = personService.selectAll();
        return list;
    } 
    
    ......
}

   2.jsp页面

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>   
    <title>Person列表</title>
    <!-- 引入Jquery -->
    <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script> 
    <!-- 编写脚本 -->
    <script type="text/javascript">
        $(function() {
            $.ajax({
                url: '${pageContext.request.contextPath}/person/ajaxlist',
                type: 'post',
                dataType: 'json',
                success: function(data) {//这里的data代表的就是返回person集合list
                    var html = "";
                    html += "<tr><th>姓名</th><th>性别</th></tr>";
                    for(var i in data){
                        html += "<tr><td>"+data[i].name+"</td><td>"+data[i].gender+"</td></tr>";
                    }
                    $("table").html(html);
                }
            });
        });
    </script>
  </head>
  
  <body>
    <table>
    </table>
  </body>
</html>

  3.tomcat启动项目,地址栏输入http://localhost:8081/mm-web/person/toPage,即可看到如下页面,同样获取到了数据库中完整数据(是两次请求)

 

  关于前后端分离

  在传统的java web项目中,应用MVC框架,Jsp想做的事太多,既有后台数据的处理手法,也要承担视图展现的职能,Java代码、Html、CSS、Javascript、各种表达式、发送请求、接收数据、页面跳转...甚至有点全能的感觉,但正是这种全能,让本该分工明确个的各单位糅杂在一起,给开发也带来了一些麻烦。使用Ajax,才真正有点分离的感觉,至少我们知道html、CSS、Js是属于前端版块,后台专注于业务逻辑和数据处理,让前台拿到结果,然后填充内容或者进行局部动态更新,渲染一下页面效果,前后端真正的交互在于这个json数据的请求和返回,而json的本质是 JS 对象的字符串表示法,是字符串,数据格式,以键值对呈现[如下图所示]。后台有一个对象转化为json的过程,反过来,json传递到前端后,应该有一个内容解析/解读的过程,要知道哪个键对应的值是代表什么含义,该怎么处理。最后,关于AJax到底属于前端还是后端,个人理解是,使用的前端技术,但主要目的是作用于前后端数据交互(请求--获取--处理的过程),然后到底前后端谁该懂得Ajax的问题,觉得只要想想自己作为前端/后端完全不懂这个的话会不会对自己形成障碍,就有自己的答案了。

  小结

  应用传统的web开发模式,成熟的框架逐步在完善,不过绝大部分框架都是针对前端或者后端,前端层出不穷的样式插件模板,后台不断更新的数据操作和技术选型,但是针对前后端交互的部分,个人觉得还有很大的提升空间。以Jsp为例,熟悉前端的(全栈?)后台开发人员操作起来会相较方便,虽然他的杂合前后端代码广受诟病,但是事实是,Jsp仍然有许多项目是采用的Jsp开发。html + Ajax + js有许多优秀的性质,也还有很多需要完善的地方。目前Ajax应用的已经比较广泛了,所以项目中往往会有两种请求混杂的情况(比较直观就是我们应用Spring MVC时,控制层里的方法,有的加了@Responsebody注解,有的则没有),可以根据项目的需要决定是否采用。

posted @ 2017-11-30 22:44  窗外天空晴朗  阅读(7846)  评论(3编辑  收藏  举报