Spring Boot教學
Spring Boot是什麼?
Spring Boot簡介
Spring Boot主要目標
Spring Boot快速入門
新項目爲什麼需要Spring Boot?
Spring Boot引導過程
Spring Boot核心和限制
Spring Boot Tomcat部署
Spring Boot優點和缺點
Spring Boot構建系統
Spring Boot入門
Spring Boot代碼結構
Spring Boot安裝
Spring Boot Bean和依賴注入
Spring Boot應用程序開發入門
Spring Boot運行器(Runner)
Spring Boot JSP應用實例
Spring Boot應用程序屬性
Spring Boot將WAR文件部署到Tomcat
Spring Boot日誌
Spring Boot Hello World(Thymeleaf)示例
Spring Boot構建RESTful Web服務
Spring Boot非web應用程序實例
Spring Boot異常處理
Spring Boot @ConfigurationProperties實例
Spring Boot攔截器
Spring Boot SLF4J日誌實例
Spring Boot Servlet過濾器
Spring Boot Ajax實例
Spring Boot Tomcat端口號
Spring Boot文件上傳示例(Ajax和REST)
Spring Boot Rest模板
Spring Boot文件上傳示例
Spring Boot文件處理
Spring Boot服務組件
Spring Boot Thymeleaf示例
Spring Boot使用RESTful Web服務
Spring Boot CORS支持
Spring Boot國際化
Spring Boot調度
Spring Boot啓用HTTPS
Spring Boot Eureka服務器
Spring Boost Eureka服務註冊
Spring Boot Zuul代理服務器和路由
Spring Boot雲配置服務器
Spring Boot雲配置客戶端
Spring Boot Actuator
Spring Boot管理服務器
Spring Boot管理客戶端
Spring Boot啓用Swagger2
Spring Boot創建Docker鏡像
Spring Boot跟蹤微服務日誌
Spring Boot Flyway數據庫
Spring Boot發送電子郵件
Spring Boot Hystrix
Spring Boot Web Socket
Spring Boot批量服務
Spring Boot Apache Kafka
Spring Boot單元測試用例
Spring Boot Rest控制器單元測試
Spring Boot數據庫源(連接數據庫)
Spring Boot保護Web應用程序

Spring Boot Ajax實例

本文將展示如何使用jQuery.ajax將HTML表單請求發送到Spring REST API並返回JSON響應。

使用的工具 :

  1. Spring Boot 1.5.1.RELEASE
  2. Spring 4.3.6.RELEASE
  3. Maven 3
  4. jQuery
  5. Bootstrap 3

1. 項目結構

創建一個標準的Maven項目:ajax-example,用於演示在Spring Boot中使用Ajax技術,搜索用戶信息。其結構如下圖所示 -

2. 項目依賴

文件:pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.yiibai</groupId>
<artifactId>ajax-example</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.1.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>2.2.4</version>
    </dependency>

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>3.3.7</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <!-- Package as an executable jar/war -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
</project>

3. Spring REST API

REST控制器,接受一個SearchCriteria並返回一個ResponseEntity

一個正常的Spring Boot依賴和一些webjars資源。文件:SearchController.java 如下所示 -

package com.yiibai.controller;

import com.yiibai.model.AjaxResponseBody;
import com.yiibai.model.SearchCriteria;
import com.yiibai.model.User;
import com.yiibai.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class SearchController {

    UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @PostMapping("/api/search")
    public ResponseEntity<?> getSearchResultViaAjax(@Valid @RequestBody SearchCriteria search, Errors errors) {

        AjaxResponseBody result = new AjaxResponseBody();

        //If error, just return a 400 bad request, along with the error message
        if (errors.hasErrors()) {

            result.setMsg(errors.getAllErrors().stream().map(x -> x.getDefaultMessage()).collect(Collectors.joining(",")));
            return ResponseEntity.badRequest().body(result);

        }

        List<User> users = userService.findByUserNameOrEmail(search.getUsername());
        if (users.isEmpty()) {
            result.setMsg("no user found!");
        } else {
            result.setMsg("success");
        }
        result.setResult(users);

        return ResponseEntity.ok(result);
    }
}

一些其它的POJO類,它們分別如下所示 -
文件:AjaxResponseBody.java

package com.yiibai.model;

import java.util.List;

public class AjaxResponseBody {

    String msg;
    List<User> result;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public List<User> getResult() {
        return result;
    }

    public void setResult(List<User> result) {
        this.result = result;
    }
}

文件:User.java

package com.yiibai.model;

public class User {

    String username;
    String password;
    String email;

    public User(String username, String password, String email) {
        this.username = username;
        this.password = password;
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

驗證器類:SearchCriteria.java

package com.yiibai.model;

import org.hibernate.validator.constraints.NotBlank;

public class SearchCriteria {

    @NotBlank(message = "username can't empty!")
    String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

用於初始化一些用戶進行搜索的服務。文件:UserService.java 如下所示 -

package com.yiibai.services;

import com.yiibai.model.User;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserService {

    private List<User> users;

    // Love Java 8
    public List<User> findByUserNameOrEmail(String username) {

        List<User> result = users.stream().filter(x -> x.getUsername().equalsIgnoreCase(username)).collect(Collectors.toList());

        return result;

    }
    /*public List<User> findByUserNameOrEmail(String username, String email) {

        List<User> result = new ArrayList<User>();

        for (User user : users) {

            if ((!StringUtils.isEmpty(username)) && (!StringUtils.isEmpty(email))) {

                if (username.equals(user.getUsername()) && email.equals(user.getEmail())) {
                    result.add(user);
                    continue;
                } else {
                    continue;
                }

            }
            if (!StringUtils.isEmpty(username)) {
                if (username.equals(user.getUsername())) {
                    result.add(user);
                    continue;
                }
            }

            if (!StringUtils.isEmpty(email)) {
                if (email.equals(user.getEmail())) {
                    result.add(user);
                    continue;
                }
            }
        }
        return result;

    }*/

    // Init some users for testing
    @PostConstruct
    private void iniDataForTesting() {
        users = new ArrayList<User>();
        User user1 = new User("maxsu", "password111", "[email protected]");
        User user2 = new User("yiflow", "password222", "[email protected]");
        User user3 = new User("minaxu", "password333", "[email protected]");
        User user4 = new User("minalee", "password333", "[email protected]");
        User user5 = new User("yiiflow", "password333", "[email protected]");

        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);
    }
}

Spring Boot啓動器(程序入口),參考以下代碼實現。文件:SpringBootWebApplication.java 如下所示 -

package com.yiibai;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootWebApplication {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }
}

4. HTML表單+ jQuery Ajax

一個簡單的HTML表單,用 bootstrap 框架裝飾。
文件:ajax.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Spring Boot Ajax實例</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

    <link rel="stylesheet" type="text/css"
          href="webjars/bootstrap/3.3.7/css/bootstrap.min.css"/>
</head>
<body>

<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="http://www.yiibai.com">易百教程</a>
        </div>
    </div>
</nav>

<div class="container" style="min-height: 500px">
    <div class="starter-template">
        <h1>Spring Boot AJAX 示例</h1>
        <div id="feedback"></div>
        <form class="form-horizontal" id="search-form">
            <div class="form-group form-group-lg">
                <label class="col-sm-2 control-label">用戶名:</label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="username"/>
                </div>
            </div>

            <div class="form-group">
                <div class="col-sm-offset-2 col-sm-10">
                    <button type="submit" id="bth-search"
                            class="btn btn-primary btn-lg">搜索
                    </button>
                </div>
            </div>
        </form>
    </div>
</div>
<div class="container">
    <footer>
        <p>
            © <a href="http://www.yiibai.com">Yiibai.com</a> 2017
        </p>
    </footer>
</div>
<script type="text/javascript"
        src="webjars/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>

獲取HTML表單,並通過JSON.stringify將搜索條件轉換爲JSON格式,並通過jQuery.ajax發送POST請求。
文件:main.js 如下所示 -

$(document).ready(function () {
    $("#search-form").submit(function (event) {
        //stop submit the form, we will post it manually.
        event.preventDefault();
        fire_ajax_submit();
    });

});

function fire_ajax_submit() {
    var search = {}
    search["username"] = $("#username").val();
    //search["email"] = $("#email").val();
    $("#btn-search").prop("disabled", true);
    $.ajax({
        type: "POST",
        contentType: "application/json",
        url: "/api/search",
        data: JSON.stringify(search),
        dataType: 'json',
        cache: false,
        timeout: 600000,
        success: function (data) {
            var json = "<h4>Ajax Response</h4><pre>"
                + JSON.stringify(data, null, 4) + "</pre>";
            $('#feedback').html(json);
            console.log("SUCCESS : ", data);
            $("#btn-search").prop("disabled", false);
        },
        error: function (e) {
            var json = "<h4>Ajax Response</h4><pre>"
                + e.responseText + "</pre>";
            $('#feedback').html(json);
            console.log("ERROR : ", e);
            $("#btn-search").prop("disabled", false);
        }
    });
}

5. 運行示例

啓動 Spring Boot 運行項目並測試結果。打開終端,進入到項目目錄下(pom.xml文件所在目錄),執行以下命令 -

F:\worksp\springboot\ajax-example> mvn spring-boot:run
... ...
02:57:41,425 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
02:57:41,425 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
02:57:41,425 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@7cf10a6f - Registering current configuration as safe fallback point


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
::Spring Boot::       (v1.5.1.RELEASE)

2017-03-28 02:57:42 INFO  com.yiibai.SpringBootWebApplication - Starting SpringBootWebApplication on MY-PC with PID 7656 (F:\worksp\springboot\ajax-example\target\classes started by Administrator in F:\worksp\springboot\ajax-example)
2017-03-28 02:57:42 DEBUG com.yiibai.SpringBootWebApplication - Running with Spring Boot v1.5.1.RELEASE, Spring v4.3.6.RELEASE
2017-03-28 02:57:42 INFO  com.yiibai.SpringBootWebApplication - No active profile set, falling back to default profiles: default
2017-03-28 02:57:46 INFO  com.yiibai.SpringBootWebApplication - Started SpringBootWebApplication in 5.007 seconds (JVM running for 6.084)

打開瀏覽器,訪問以下地址:http://localhost:8080/ , 應該會看到如下頁面 -
Spring

如果沒有輸入用戶名,直接點擊「搜索」,那麼應該會看到以下結果 -
Spring

如果輸入一個存在的用戶名:maxsu,直接點擊「搜索」,那麼應該會看到以下結果 -
Spring

6. 下載示例代碼

要下載代碼,請參考下載頁面。