Spring 4 MVC Ajax Hello Worldの例

このチュートリアルでは、Spring MVC Webプロジェクトを作成し、Ajax経由でフォームを送信する方法を説明します。

使用される技術:

  1. Spring 4.2.2.RELEASE

  2. Jackson 2.6.3

  3. ログバック1.1.3

  4. jQuery 1.10.2

  5. Maven 3

  6. JDK 1.8

  7. Tomcat 8またはJetty 9

  8. Eclipse 4.5

  9. ブートストラップ3

__P.SプロジェクトクラスパスでJacksonライブラリが見つかった場合、Springはジャクソンを使ってjsonデータをオブジェクト変換と自動的に処理します。

1.クイックリファレンス

1.1 HTMLでは、jQuery `$ .ajax()`を使用してフォームリクエストを送信します。

    jQuery(document).ready(function($) {
        $("#search-form").submit(function(event) {

           //Prevent the form from submitting via the browser.
            event.preventDefault();
            searchViaAjax();

        });
    });

    function searchAjax() {
        var data = {}
        data["query"]= $("#query").val();

        $.ajax({
            type : "POST",
            contentType : "application/json",
            url : "${home}search/api/getSearchResult",
            data : JSON.stringify(data),
            dataType : 'json',
            timeout : 100000,
            success : function(data) {
                console.log("SUCCESS: ", data);
                display(data);
            },
            error : function(e) {
                console.log("ERROR: ", e);
                display(e);
            },
            done : function(e) {
                console.log("DONE");
            }
        });
    }

1.2 Ajaxリクエストを処理するSpringコントローラ。

@Controller
public class AjaxController {

    @ResponseBody
    @RequestMapping(value = "/search/api/getSearchResult")
    public AjaxResponseBody getSearchResultViaAjax(@RequestBody SearchCriteria search) {

        AjaxResponseBody result = new AjaxResponseBody();
       //logic
        return result;

    }

}

2.プロジェクトディレクトリ

標準のMavenプロジェクトディレクトリ構造であるプロジェクトディレクトリを確認します。

3.プロジェクトの依存関係

pom.xml

<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.mkyong</groupId>
    <artifactId>spring4-mvc-maven-ajax-example</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>spring4 mvc maven ajax example</name>

    <properties>
        <jdk.version>1.8</jdk.version>
        <spring.version>4.2.2.RELEASE</spring.version>
        <jackson.version>2.6.3</jackson.version>
        <logback.version>1.1.3</logback.version>
        <jcl.slf4j.version>1.7.12</jcl.slf4j.version>
        <jstl.version>1.2</jstl.version>
        <servletapi.version>3.1.0</servletapi.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Need this for json to/from object -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <!-- JSTL for views -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>

        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${jcl.slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <!-- compile only, runtime container will provide this -->
        <!-- Need this for config annotation -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servletapi.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.2.11.v20150529</version>
                <configuration>
                    <scanIntervalSeconds>10</scanIntervalSeconds>
                    <webApp>
                        <contextPath>/spring4ajax</contextPath>
                    </webApp>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.10</version>
                <configuration>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                    <wtpversion>2.0</wtpversion>
                    <wtpContextName>spring4ajax</wtpContextName>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>

            <!-- Deploy to WildFly -->
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-maven-plugin</artifactId>
                <version>1.1.0.Alpha5</version>
                <configuration>
                    <hostname>127.0.0.1</hostname>
                    <port>9990</port>
                    <username>admin</username>
                    <password>admin</password>
                    <name>spring4ajax.war</name>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4.スプリングコンポーネント

重要なクラスのみが表示されます。

4.1 `@ RestController`はAjaxリクエストを処理します。コメントを読み、自明です。

AjaxController.java

package com.mkyong.web.controller;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;
import com.mkyong.web.model.AjaxResponseBody;
import com.mkyong.web.model.SearchCriteria;
import com.mkyong.web.model.User;

@RestController
public class AjaxController {

    List<User> users;

   //@ResponseBody, not necessary, since class is annotated with @RestController
   //@RequestBody - Convert the json data into object (SearchCriteria) mapped by field name.
   //@JsonView(Views.Public.class) - Optional, filters json data to display.
    @JsonView(Views.Public.class)
    @RequestMapping(value = "/search/api/getSearchResult")
    public AjaxResponseBody getSearchResultViaAjax(@RequestBody SearchCriteria search) {

        AjaxResponseBody result = new AjaxResponseBody();

        if (isValidSearchCriteria(search)) {
            List<User> users = findByUserNameOrEmail(search.getUsername(), search.getEmail());

            if (users.size() > 0) {
                result.setCode("200");
                result.setMsg("");
                result.setResult(users);
            } else {
                result.setCode("204");
                result.setMsg("No user!");
            }

        } else {
            result.setCode("400");
            result.setMsg("Search criteria is empty!");
        }

       //AjaxResponseBody will be converted into json format and send back to the request.
        return result;

    }

    private boolean isValidSearchCriteria(SearchCriteria search) {

        boolean valid = true;

        if (search == null) {
            valid = false;
        }

        if ((StringUtils.isEmpty(search.getUsername())) && (StringUtils.isEmpty(search.getEmail()))) {
            valid = false;
        }

        return valid;
    }

   //Init some users for testing
    @PostConstruct
    private void iniDataForTesting() {
        users = new ArrayList<User>();

        User user1 = new User("mkyong", "pass123", "[email protected]", "012-1234567", "address 123");
        User user2 = new User("yflow", "pass456", "[email protected]", "016-7654321", "address 456");
        User user3 = new User("laplap", "pass789", "[email protected]", "012-111111", "address 789");
        users.add(user1);
        users.add(user2);
        users.add(user3);

    }

   //Simulate the search function
    private 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;

    }
}

4.2 "json data"は `@ RequestBody`を介してこのオブジェクトに変換されます。

SearchCriteria.java

package com.mkyong.web.model;

public class SearchCriteria {

    String username;
    String email;

   //getters and setters
}

4.2リクエストに返される内容を制御するために `@ JsonView`のダミークラスを作成します。

Views.java

package com.mkyong.web.jsonview;

public class Views {
    public static class Public {}
}

4.3検索機能のためのユーザーオブジェクト。 @JsonViewで注釈が付けられたフィールドが表示されます。

User.java

package com.mkyong.web.model;

import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;

public class User {

    @JsonView(Views.Public.class)
    String username;

    String password;

    @JsonView(Views.Public.class)
    String email;

    @JsonView(Views.Public.class)
    String phone;

    String address;

   //getters, setters and contructors
}

4.4このオブジェクトはjson形式に変換され、要求に戻ります。

AjaxResponseBody.java

package com.mkyong.web.model;

import java.util.List;
import com.fasterxml.jackson.annotation.JsonView;
import com.mkyong.web.jsonview.Views;

public class AjaxResponseBody {

    @JsonView(Views.Public.class)
    String msg;

    @JsonView(Views.Public.class)
    String code;

    @JsonView(Views.Public.class)
    List<User> result;

   //getters and setters
}
  • Note ** `@ JsonView`はSpringフレームワークではなくJacksonライブラリに属します。

5. jQuery Ajax

JSPでは、単純な検索フォームを作成し、フォームリクエストをjQuery `$ .ajax`で送信します。

welcome.jsp

<%@page session="false"%>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="en">
<head>
<c:url var="home" value="/" scope="request"/>

<spring:url value="/resources/core/css/hello.css" var="coreCss"/>
<spring:url value="/resources/core/css/bootstrap.min.css"
    var="bootstrapCss"/>
<link href="${bootstrapCss}" rel="stylesheet"/>
<link href="${coreCss}" rel="stylesheet"/>

<spring:url value="/resources/core/js/jquery.1.10.2.min.js"
    var="jqueryJs"/>
<script src="${jqueryJs}"></script>
</head>

<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">Spring 4 MVC Ajax Hello World</a>
        </div>
    </div>
</nav>

<div class="container" style="min-height: 500px">

    <div class="starter-template">
        <h1>Search Form</h1>
        <br>

        <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">Username</label>
                <div class="col-sm-10">
                    <input type=text class="form-control" id="username">
                </div>
            </div>
            <div class="form-group form-group-lg">
                <label class="col-sm-2 control-label">Email</label>
                <div class="col-sm-10">
                    <input type="text" class="form-control" id="email">
                </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">Search</button>
                </div>
            </div>
        </form>

    </div>

</div>

<div class="container">
    <footer>
        <p>
            © <a href="/">Mkyong.com</a> 2015
        </p>
    </footer>
</div>

<script>
    jQuery(document).ready(function($) {

        $("#search-form").submit(function(event) {

           //Disble the search button
            enableSearchButton(false);

           //Prevent the form from submitting via the browser.
            event.preventDefault();

            searchViaAjax();

        });

    });

    function searchViaAjax() {

        var search = {}
        search["username"]= $("#username").val();
        search["email"]= $("#email").val();

        $.ajax({
            type : "POST",
            contentType : "application/json",
            url : "${home}search/api/getSearchResult",
            data : JSON.stringify(search),
            dataType : 'json',
            timeout : 100000,
            success : function(data) {
                console.log("SUCCESS: ", data);
                display(data);
            },
            error : function(e) {
                console.log("ERROR: ", e);
                display(e);
            },
            done : function(e) {
                console.log("DONE");
                enableSearchButton(true);
            }
        });

    }

    function enableSearchButton(flag) {
        $("#btn-search").prop("disabled", flag);
    }

    function display(data) {
        var json = "<h4>Ajax Response</h4><pre>"
                + JSON.stringify(data, null, 4) + "</pre>";
        $('#feedback').html(json);
    }
</script>

</body>
</html>

6.デモ

リンク://wp-content/uploads/2015/10/spring-mvc-ajax-example-demo-1.png[ spring-mvc-ajax-example-demo-1 ]

6.2フィールドの検証が空です。

リンク://wp-content/uploads/2015/10/spring-mvc-ajax-example-demo-2.png[ spring-mvc-ajax-example-demo-2 ]

6.3ユーザ名による検索。

6.4。電子メールで検索してください。

リンク://wp-content/uploads/2015/10/spring-mvc-ajax-example-demo-4.png[ spring-mvc-ajax-example-demo-4 ]

{空} 5。 Chromeブラウザで、要素、ネットワークタグを調べます。

リンク://wp-content/uploads/2015/10/spring-mvc-ajax-example-demo-5.png[ spring-mvc-ajax-example-demo-5 ]

7.このプロジェクトをどのように実行するのですか?

7.1 Githubからソースコードをクローン

$ git clone https://github.com/mkyong/spring4-mvc-ajax-example

7.2組み込みJettyコンテナを実行します。

$ mvn jetty:run

7.3このURLにアクセスする - http://localhost:8080/spring4ajax/

前の投稿:Androidスピナー(ドロップダウンリスト)の例
次の投稿:ResourceBundleMessageSourceの例のSpringリソースバンドル