springMVC+maven+mybatis+mysql入門

(六)利用ajax和后臺(tái)交互

這一小節(jié),我們主要實(shí)現(xiàn)頁面和后臺(tái)簡(jiǎn)單的數(shù)據(jù)交互,初步掌握這個(gè)交互流程

頁面主要采用ajax技術(shù)往后臺(tái)發(fā)數(shù)據(jù),后臺(tái)就使用上一節(jié)我們寫好的工程代碼(五)最簡(jiǎn)單的springMVC后臺(tái)程序
關(guān)于jquery,ajax這些基礎(chǔ)理論,這里就不多講了,簡(jiǎn)單使用的話,沒什么難度,有需求的請(qǐng)自行百度。

首先,為了這一節(jié)的講解,我們需要新建一些文件和目錄。
1.引入jquery*
這個(gè)簡(jiǎn)單,只需要到j(luò)query官網(wǎng)去把jquery.js文件下回來,引入代碼即可。這里我們?cè)?src/main/webapp 下創(chuàng)建一個(gè)resources文件夾,在這個(gè)文件夾下邊,創(chuàng)建一個(gè)jquery文件夾,把從官網(wǎng)下回來的jquery.js拷貝到這里面,我這里用的是 jqery-3.3.1.js
2.創(chuàng)建一個(gè)hello目錄,在里面創(chuàng)建一個(gè)hello.js和hello.css兩個(gè)文件,暫時(shí)保持空文件,后面再來添加內(nèi)容。
3.在WEB-INF下面創(chuàng)建一個(gè)pages文件夾,然后在這個(gè)文件夾里,創(chuàng)建一個(gè)hello.jsp。
創(chuàng)建完成后,目錄結(jié)構(gòu)如下:


目錄結(jié)構(gòu).png

這里我們?yōu)榱搜菔?,做了一個(gè)比較完整的結(jié)構(gòu),hello.jsp是我們需要訪問的頁面,hello.js提供腳本支持,hello.css提供樣式支持,常規(guī)工程也基本就是這樣了,可能就是目錄結(jié)構(gòu)的差異

好了,現(xiàn)在我們?cè)谔顚憙?nèi)容,具體細(xì)節(jié)暫時(shí)不討論,jsp相關(guān)的知識(shí)點(diǎn)請(qǐng)自行百度學(xué)習(xí)。
首先,hello.jsp的代碼如下

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>HelloJsp</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <script type="text/javascript" src="<%=basePath%>resources/jquery/jquery-3.3.1.js"></script>
    <script type="text/javascript" src="<%=basePath%>resources/hello/hello.js">
    
    </script>
    <script type="text/javascript">
    var basePath = "<%=basePath%>";
    </script>
    <link rel="stylesheet" type="text/css" href="<%=basePath%>resources/hello/hello.css">
    
  </head>
  
  <body>
    This is my first jsp page. <br>
    
    <br/>
    my hello
    <br/>
    <div class="mydiv">
        <input id="myInput"></input>      
        <button class="mybutton" id="getButton">Get</button>
    </div>
  </body>
</html>

這個(gè)頁面部分代碼是自動(dòng)生成的時(shí)候留下的,先不管它,就這樣寫滿足我們的需求即可
其中的

    <script type="text/javascript" src="<%=basePath%>resources/jquery/jquery-3.3.1.js"></script>
    <script type="text/javascript" src="<%=basePath%>resources/hello/hello.js">

引入了jquery和js
然后,我們?cè)陧撁嫔袭嬃艘粋€(gè)輸入框和一個(gè)按鈕

<div class="mydiv">
        <input id="myInput"></input>      
        <button class="mybutton" id="getButton">Get</button>
    </div>

后面的學(xué)習(xí)和測(cè)試,都是圍繞這個(gè)輸入框和按鈕來進(jìn)行。

然后,hello.js這樣寫

$("document").ready(function(){ 
    $("#getButton").click(function(){
        let id = $("#myInput").val();
        $.ajax({
            url:basePath+"/firstGet/"+id,
            type:'GET',
            dataType:'text',
            contentType:'application/json',
            success:function(result){
                $("#myInput").val(result);
            }
        })      
    }); 
});

簡(jiǎn)單的,典型的,基于jquery的一個(gè)js代碼。
點(diǎn)擊button,向后端服務(wù)器發(fā)送一個(gè)get請(qǐng)求,然后將后端的返回值,填寫到輸入框。
至于ajax的相關(guān)問題,請(qǐng)大家自行百度學(xué)習(xí),這里寫的是很簡(jiǎn)單的。

好了,然后我們?cè)趆ello.css中加入內(nèi)容

.mydiv{
    display:flex;
    flex-direction:column;
    width:400px;
    height:600px;
}
.mybutton{
    width:100px;
}

不擅長寫樣式,簡(jiǎn)單的寫一下,達(dá)到演示的目的即可。

好,我們的頁面文件已經(jīng)準(zhǔn)備好了,現(xiàn)在修改一下后端代碼。

在上面ajax中,我們發(fā)出去的請(qǐng)求是

url:basePath+"/firstGet/"+id,

在controller中要處理的uri就是 /firstGet/{id} 其中的{id}指的就是我們從input獲取到的id,這個(gè)是目前流行的restful風(fēng)格的寫法,按照以前的寫法已經(jīng)改是/firstGet/id?id=xxx這樣,我們順應(yīng)潮流,按照流行的方式來,當(dāng)然,正是項(xiàng)目肯定不能取 firstGet 這樣的名字,這里為了演示,不用太嚴(yán)謹(jǐn)。
controller需要處理這個(gè),DemoController 代碼修改后如下:

package com.springstart.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;


@Controller
public class DemoController {

    @RequestMapping(value="/hello",method=RequestMethod.GET)
    public String myFirstController(){
        System.out.println("some one call MyFirstController");
        return "hello";
    }
    
    @ResponseBody
    @RequestMapping(value="/firstGet/{id}",method=RequestMethod.GET)
    public String myFirstGet(@PathVariable("id") String id){
        System.out.println("from page id:"+id);
        return "Right "+id;
    }   
}

在新的方法上,多了一個(gè)注解 @ResponseBody 這個(gè)是注解的作用是把返回值寫入 HTTP response body 中,便于ajax接收,這也是使用ajax發(fā)送請(qǐng)求接收數(shù)據(jù)的常規(guī)方式。
好了,代碼完成了,加載到tomcat中,跑起來試試。
在瀏覽器中,輸入
http://localhost:8080/springstart/hello
將會(huì)把hello.jsp這個(gè)頁面展示給我們

hello.png

感覺不對(duì)呢,我們寫的css明明是 flex-column,沒有生效呢
在輸入框中輸入一個(gè)數(shù)字,然后點(diǎn) Get,沒有反應(yīng)
這個(gè)時(shí)候,需要進(jìn)行頁面調(diào)試了,在Chrome或者Firefox中按F12(IE不怎么用不知道),調(diào)出調(diào)試頁面,在console一欄可以看到報(bào)錯(cuò)了
error.png

沒找到j(luò)query,css,js文件
這個(gè)就是涉及一個(gè)問題,我們?cè)趙eb.xml中對(duì)DispatcherServlet設(shè)置的攔截規(guī)則是/,表示攔截一切請(qǐng)求,那么對(duì)靜態(tài)資源的請(qǐng)求,也會(huì)被攔截,這樣就找不到對(duì)應(yīng)的controller來處理,從而報(bào)了404找不到的錯(cuò)誤。
對(duì)于這個(gè)問題,比較簡(jiǎn)潔的解決辦法有兩個(gè)
1.在resources/config/mymvc.xml中添加一個(gè)配置

<mvc:default-servlet-handler />

這句話的內(nèi)在意思比較復(fù)雜,完全可以寫一篇文章來說明,需要深入了解的自行百度,就這樣配置后,就可以訪問到靜態(tài)資源了。
2.在resources/config/mymvc.xml中添加一個(gè)配置

<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>

這個(gè)配置直接定位到resources,resources下面的文件都被注冊(cè)為資源,這樣servlet就會(huì)處理了。這個(gè)配置方式定位精確,resources之外的靜態(tài)資源,依然不能訪問。

上面兩個(gè)方法都有效,以實(shí)際需求為準(zhǔn)。
加上這個(gè)配置之后,重新啟動(dòng)tomcat,依然訪問
http://localhost:8080/springstart/hello
結(jié)果。。。訪問不了了。。。
因?yàn)樵黾恿松厦娴呐渲煤?,默認(rèn)加載的來處理注解@RequestMapping的handler就沒有了,這樣就無法處理這個(gè)注解,也就無法將http請(qǐng)求URI對(duì)應(yīng)到我們的controller上面去
需要增加一個(gè)注解

<mvc:annotation-driven />

啟用對(duì) @RequestMapping的處理,這樣就可以了,而這個(gè)配置,一般在spring mvc項(xiàng)目中,都是需要的。

目前到這里,mymvc.xml的內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc.xsd
                        http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <context:component-scan base-package="com.springstart.*"></context:component-scan>
    <mvc:annotation-driven />
    <mvc:default-servlet-handler />
    
    <!-- <mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>  -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

這樣,啟動(dòng)tomcat,就可以訪問到hello.jsp了


hello.png

設(shè)定的flex樣式,也生效了,按f12,沒有報(bào)錯(cuò)。
在輸入框輸入字符串,點(diǎn)擊 Get,輸入框會(huì)回顯Right加上輸入的字符串。
最基本的一個(gè)交互功能完成。

前面我們寫的ajax里面有一個(gè)

type:'GET',

表示我們這個(gè)請(qǐng)求是一個(gè)get請(qǐng)求
在controller中,我們對(duì)應(yīng)的處理方法有注解method=RequestMethod.GET,就是處理GET的請(qǐng)求。
關(guān)于請(qǐng)求的類型,大致常規(guī)的有 GET POST PUT DELETE,還有一些其他的,常規(guī)的開發(fā)過程很難用到,暫時(shí)不談。
一般說來
GET 表明根據(jù)請(qǐng)求鏈接,從服務(wù)器獲取一定的信息
DELETE 表明刪除一定信息
POSTPUT不好區(qū)分,都是給服務(wù)端發(fā)送信息過去,服務(wù)端的處理方式有一些差異。
POST 每次給過來的信息都會(huì)存起來,POST兩次,就存兩條記錄
PUT 每次給過來的信息以更新方式存起來,不管執(zhí)行多少次,只影響一條記錄。

這里就要引入一個(gè)概念 冪等,在http請(qǐng)求這一塊, 冪等表達(dá)的就是同一個(gè)請(qǐng)求,不管執(zhí)行多少次,對(duì)服務(wù)器的影響都是相同的,或者指一次和多次請(qǐng)求某一個(gè)資源應(yīng)該具有同樣的結(jié)果。
舉例來說
GET ,get一個(gè)name=Jack的人的id,只要沒有人修改數(shù)據(jù)庫,不管我們執(zhí)行多少次,返回的id都是一樣的,這是 冪等
DELETE,delete name=Jack,執(zhí)行1次或多次,數(shù)據(jù)庫里這條記錄都會(huì)被刪除,這是 冪等
PUT ,put表示更新,將name=Jack的年齡變更為20歲,不管執(zhí)行多少次,數(shù)據(jù)庫里這個(gè)人的年齡都會(huì)變成20,這是 冪等
POST,執(zhí)行1次后數(shù)據(jù)庫多一條記錄,執(zhí)行2次后,數(shù)據(jù)庫多兩條記錄,這個(gè)不是冪等

好了,這些都是理論和常規(guī)用法。你當(dāng)然也可以用get達(dá)到post的效果,這就非主流啦。
另外,頁面開發(fā)這一塊還涉及到瀏覽器版本問題,有些舊版本的瀏覽器不支持除GETPOST以外的方法,這一點(diǎn)在實(shí)際項(xiàng)目中可能需要考慮。

我們這里增加一個(gè)POST方法的演示,跟get方法很類似,只是數(shù)據(jù)不放在請(qǐng)求鏈接里。
首先在jsp頁面增加一個(gè)post按鈕

<div class="mydiv">
        <input id="myInput"></input>      
        <button class="mybutton" id="getButton">Get</button>
        <button class="mybutton" id="POSTButton">POST</button>
    </div>

在js中,增加對(duì)post按鈕的處理

$("#POSTButton").click(function(){
        let id = $("#myInput").val();
        $.ajax({
            url:basePath+"/firstPost",
            data:id,
            type:'POST',
            dataType:'text',
            contentType:'application/json',
            success:function(result){
                $("#myInput").val(result);
            }
        })      
    }); 

在controller中增加一個(gè)處理這個(gè)post請(qǐng)求的方法

@ResponseBody
@RequestMapping(value="/firstPost",method=RequestMethod.POST)
public String myFirstPost(@RequestBody String msg){
    System.out.println("from page msg:"+msg);
    return "Good "+msg;
}

這里我們?cè)趨?shù)體重增加了一個(gè) @RequestBody注解,要獲取POST過來的數(shù)據(jù),同時(shí)類型是 application/json,就可以用這個(gè)注解來獲取,我們把傳過來的字符串寫到msg里,很方便。

好了,基本的交互我們完成了,下一章會(huì)對(duì)post和get進(jìn)行一個(gè)詳細(xì)的講解。
本章代碼上傳至 sprintStart github springStart_basic_2,請(qǐng)自行下載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容