三 后台环境搭建 - 9. 表述层配置

9. 表述层配置

分支: git checkout -b 3.9.0_web

9.1 目标

  • handler 中装配 Service

  • 页面能够访问到 handler

  • 页面 -> hander (@RequestMapping) -> Service -> Mapper -> 数据库

9.2 思路 web.xml 和 Spring 配置文件关系

  • 图 9-1 各个配置文件的关系

IOC: ApplicationContext

img

9.3 web.xml 配置

  • Ctrl + Shift + Alt + S 打开项目配置

img

  • Apply

img

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- needed for ContextLoaderListener -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>

    <!-- Bootstraps the root web application context before servlet initialization -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 强制请求设置字符集 -->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!-- 强制响应设置字符集 -->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <!-- 这个 Filter 执行的顺序要在所有其他 filter 前面 -->
    <!-- 原因如下: -->
    <!-- request.setCharacterEncoding(encoding); 必须在 request.getParameter() 前面 -->
    <!-- response.setCharacterEncoding(encoding); 必须在 response.getWriter() 前面 -->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-web-mvc.xml</param-value>
        </init-param>
        <!-- Servlet 默认生命周期中, 创建对象是在第一次接收到请求时 -->
        <!-- 而 DispatcherServlet 创建对象后有大量的 "框架初始化" 工作, 不适合在第一次请求时来做 -->
        <!-- 设置 load-on-startup 就是为了 DispatcherServlet 在 Web 应用启动时创建对象初始化 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!-- url-pattern 配置方式一: / 表示拦截所有请求 -->
        <!-- <url-pattern>/</url-pattern> -->

        <!-- url-pattern 配置方式二: 配置请求扩展名-->
        <!-- 优点1: 静态资源完全不需要经过 SpringMVC, 不需要拦截 -->
        <!-- 优点2: 可以实现伪静态效果。表面上看起来是访问一个 HTML 文件这样的静态资源, 但是实际上是经过 Java 代码运算的结果 -->
        <!--    伪静态作用1: 给黑客入侵增加难度 -->
        <!--    伪静态作用2: 有利于 SEO 优化 (让百度、谷歌这样的搜索引擎更容易找到我们项目) -->
        <!-- 缺点: 不符合 RESTFul 风格 -->
        <url-pattern>*.html</url-pattern>

        <!-- 为什么要另外再配置 json 扩展名呢? -->
        <!-- 如果一个 Ajax 请求扩展名是 HTML, 但是实际服务器给浏览器返回的是 JSON 数据, 二者就不匹配了, 会出现406错误 -->
        <!-- 为了让 Ajax 请求能够顺利拿到 JSON 格式数据, 我们另外配置 JSON 扩展名 -->
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>
</web-app>
9.3.1 配置 ContextLoaderListener
    <!-- needed for ContextLoaderListener -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>

    <!-- Bootstraps the root web application context before servlet initialization -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
9.3.2 配置 CharacterEncodingFilter
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!-- 指定字符集 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!-- 强制请求设置字符集 -->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!-- 强制响应设置字符集 -->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <!-- 这个 Filter 执行的顺序要在所有其他 filter 前面 -->
    <!-- 原因如下: -->
    <!-- request.setCharacterEncoding(encoding); 必须在 request.setParameter() 前面 -->
    <!-- response.setCharacterEncoding(encoding); 必须在 response.getWriter() 前面 -->
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
9.3.3 配置 DispatcherServlet
    <servlet>
        <servlet-name>springDispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-web-mvc.xml</param-value>
        </init-param>
        <!-- Servlet 默认生命周期中, 创建对象是在第一次接收到请求时 -->
        <!-- 而 DispatcherServlet 创建对象后有大量的 "框架初始化" 工作, 不适合在第一次请求时来做 -->
        <!-- 设置 load-on-startup 就是为了 DispatcherServlet 在 Web 应用启动时创建对象初始化 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>springDispatcherServlet</servlet-name>
        <!-- url-pattern 配置方式一: / 表示拦截所有请求 -->
        <!-- <url-pattern>/</url-pattern> -->

        <!-- url-pattern 配置方式二: 配置请求扩展名-->
        <!-- 优点1: 静态资源完全不需要经过 SpringMVC, 不需要拦截 -->
        <!-- 优点2: 可以实现伪静态效果。表面上看起来是访问一个 HTML 文件这样的静态资源, 但是实际上是经过 Java 代码运算的结果 -->
        <!--    伪静态作用1: 给黑客入侵增加难度 -->
        <!--    伪静态作用2: 有利于 SEO 优化 (让百度、谷歌这样的搜索引擎更容易找到我们项目) -->
        <!-- 缺点: 不符合 RESTFul 风格 -->
        <url-pattern>*.html</url-pattern>

        <!-- 为什么要另外再配置 json 扩展名呢? -->
        <!-- 如果一个 Ajax 请求扩展名是 HTML, 但是实际服务器给浏览器返回的是 JSON 数据, 二者就不匹配了, 会出现406错误 -->
        <!-- 为了让 Ajax 请求能够顺利拿到 JSON 格式数据, 我们另外配置 JSON 扩展名 -->
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>
9.3.4 创建 spring-web-mvc.xml
  • atcrowdfunding02-admin-webui > resources

9.4 配置 spring-web-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
">
    <!-- 配置自动扫描的包: 扫描 handler -->
    <context:component-scan base-package="com.atguigu.crowd.mvc"/>

    <!-- 配置 SpringMVC 的注解驱动 -->
    <mvc:annotation-driven/>

    <!-- 配置视图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

</beans>
9.4.1 创建包
  • config

  • handler

  • interceptor

img

9.5 测试 SSM 整合环境

9.5.1 创建 index.jsp

img

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>

</body>
</html>
9.5.2 导入依赖

img

        <!-- 引入 Servlet 容器中相关依赖 -->
        <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- JSP 页面使用的依赖 -->
        <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <scope>provided</scope>
        </dependency>

img

        <!-- 引入 Servlet 容器中相关依赖 -->
        <!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
9.5.3 创建 TestHandler
package com.atguigu.crowd.mvc.handler;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.service.api.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class TestHandler {

    @Autowired
    private AdminService adminService;

    @RequestMapping("/test/ssm.html")
    public String testSsm(ModelMap modelMap) {
        List<Admin> adminList = adminService.getAll();
        modelMap.addAttribute("adminList", adminList);
        return "target";
    }

}
  • getAll - AdminService
package com.atguigu.crowd.service.api;

import com.atguigu.crowd.entity.Admin;

import java.util.List;

public interface AdminService {

    void saveAdmin(Admin admin);

    List<Admin> getAll();
}
  • getAll - AdminServiceImpl
package com.atguigu.crowd.service.impl;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.AdminExample;
import com.atguigu.crowd.mapper.AdminMapper;
import com.atguigu.crowd.service.api.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Override
    public void saveAdmin(Admin admin) {
        adminMapper.insert(admin);

        throw new RuntimeException();
    }

    @Override
    public List<Admin> getAll() {
        return adminMapper.selectByExample(new AdminExample());
    }
}
9.5.4 创建 target.jsp

img

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<h1>Success</h1>

${requestScope.adminList}

</body>
</html>
9.5.5 创建 tomcat 并运行
  1. 打开项目设置 Ctrl + Shilf + Alt + S

    1. 点击 Create Artifact

img

  1. 选中所有右键 put into Output Root

img

  1. Apply

  2. Ctrl + Shelf + A

    1. 搜索 Edit Con

img

img

  1. 创建 Tomcat Service

img

  1. 选择 Tomcat

📎apache-tomcat-9.0.14.zip

img

  • 设置 VM: -Dfile.encoding=utf-8

img

  1. 添加项目

img

img

  1. Apply
  2. Alt + 8打开 Services
  3. 启动项目

img

  • 启动报错, 权限问题 error=13, Permission denied
进入到tomcat的bin目录下,执行命令

chmod a+x catalina.sh
  • 编码问题

img

img

  • VM 设置后重启生效

img

9.6 base 标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
  </head>
  <body>
    
  <%--<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>--%>
  <a href="test/ssm.html">测试 SMM 配置环境</a>
  
  </body>
</html>
9.6.1 注意的点
  • 端口号前面的冒号不能省略
  • contextPath 前面不能写 /
  • contextPath 后面必须写 /
  • 页面上所有参照 base 标签对的标签都必须放在 base 标签后面
  • 页面上所有参照 base 标签的标签的路径都不能以 / 开头

9.7 AJAX

9.7.1 建立意识

img

9.7.2 常用注解

img

  • @ResponseBody 和 @RequestBody 想要正常工作必须有 Jackson 的支持, 请确认当前环境引入了如下依赖 ( 已引入 )
        <!-- Spring 进行 JSON 数据转换依赖 -->
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
  • 同时必须配置了 mvc:annotation-driven
9.7.3 @RequestBody 注解的使用

img

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
</head>
<body>

<%--<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>--%>
<a href="test/ssm.html">测试 SMM 配置环境</a>

</body>
</html>
9.7.4 Ajax 发送数组 - 方案一

img

  • index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
                $.ajax({
                    url: "send/array",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: {
                        array: [5, 8, 12]
                    },       // 要发送的请求参数
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });
        })
    </script>
</head>
<body>

<%--<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>--%>
<a href="test/ssm.html">测试 SMM 配置环境</a>

<br/>


<button id="btn1">Send [5, 8, 12] One</button>

</body>
</html>
  • TestHandler.java
    @ResponseBody
    @RequestMapping("/send/array.html")
    public String testReceiveArrayOne(@RequestParam("array[]") List<Integer> list) {

        list.forEach(System.out::println);

        return "success";
    }
  • 缺陷: handler 方法中接收数据时需要在请求参数名字后面多谢一组 []
9.7.4 Ajax 发送数组 - 方案二

img

  • index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
                $.ajax({
                    url: "send/array.html",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: {
                        array: [5, 8, 12]
                    },       // 要发送的请求参数
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });

            $("#btn2").click(function () {
                $.ajax({
                    url: "send/array/two.html",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: {
                        "array[0]": 5,
                        "array[1]": 8,
                        "array[2]": 12,
                    },       // 要发送的请求参数
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });
        })
    </script>
</head>
<body>

<%--<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>--%>
<a href="test/ssm.html">测试 SMM 配置环境</a>

<br/>
<br/>

<button id="btn1">Send [5, 8, 12] One</button>

<br/>
<br/>

<button id="btn2">Send [5, 8, 12] One</button>

</body>
</html>
  • TestHandler.java
package com.atguigu.crowd.mvc.handler;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.ParamData;
import com.atguigu.crowd.service.api.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class TestHandler {

    @Autowired
    private AdminService adminService;
    
    @ResponseBody
    @RequestMapping("/send/array/two.html")
    public String testReceiveArrayTwo(ParamData paramData) {
        List<Integer> list = paramData.getArray();

        list.forEach(System.out::println);

        return "success";
    }

    @ResponseBody
    @RequestMapping("/send/array.html")
    public String testReceiveArrayOne(@RequestParam("array[]") List<Integer> list) {

        list.forEach(System.out::println);

        return "success";
    }

    @RequestMapping("/test/ssm.html")
    public String testSsm(ModelMap modelMap) {
        List<Admin> adminList = adminService.getAll();
        System.out.println(adminList);
        modelMap.addAttribute("adminList", adminList);
        modelMap.addAttribute("adminList2", adminList);
        modelMap.addAttribute("adminList4", adminList);

        return "/target";
    }

}
  • ParamData

img

package com.atguigu.crowd.entity;

import java.util.List;

public class ParamData {

    private List<Integer> array;

    public ParamData() {
    }

    public ParamData(List<Integer> array) {
        this.array = array;
    }

    public List<Integer> getArray() {
        return array;
    }

    public void setArray(List<Integer> array) {
        this.array = array;
    }

    @Override
    public String toString() {
        return "ParamData{" +
                "array=" + array +
                '}';
    }
}
9.7.5 Ajax 发送数组 - 方案三

img

  • index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#btn1").click(function () {
                $.ajax({
                    url: "send/array.html",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: {
                        array: [5, 8, 12]
                    },       // 要发送的请求参数
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });

            $("#btn2").click(function () {
                $.ajax({
                    url: "send/array/two.html",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: {
                        "array[0]": 5,
                        "array[1]": 8,
                        "array[2]": 12,
                    },       // 要发送的请求参数
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });

            $("#btn3").click(function () {

                // 准备好要发送到服务器端的数组
                var array = [5, 8, 12];

                // 将 JSON 数组转换为 JSON 字符串
                var requestBody = JSON.stringify(array);

                $.ajax({
                    url: "send/array/three.html",      // 请求目标资源的地址
                    type: "post",           // 请求方式
                    data: requestBody,       // 请求体
                    contentType: "application/json;charset=UTF-8",       // 请求体的内容类型, 告诉服务器本次请求的请求体是 JSON 数据
                    dataType: "text",       // 如何对待服务器返回的数据
                    success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
                        alert(response);
                    },
                    error: function () {    // 服务器端处理请求失败后调用的回调函数

                    }
                })
            });
        })
    </script>
</head>
<body>

<%--<a href="${pageContext.request.contextPath}/test/ssm.html">测试 SMM 配置环境</a>--%>
<a href="test/ssm.html">测试 SMM 配置环境</a>

<br/>
<br/>

<button id="btn1">Send [5, 8, 12] One</button>

<br/>
<br/>

<button id="btn2">Send [5, 8, 12] One</button>

<br/>
<br/>

<button id="btn3">Send [5, 8, 12] One</button>

</body>
</html>
  • TestHandler.java
package com.atguigu.crowd.mvc.handler;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.ParamData;
import com.atguigu.crowd.service.api.AdminService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class TestHandler {

    @Autowired
    private AdminService adminService;

    @ResponseBody
    @RequestMapping("/send/array/three.html")
    public String testReceiveArrayThree(@RequestBody List<String> list) {
        Logger logger = LoggerFactory.getLogger(TestHandler.class);
        list.forEach(logger::info);
        return "success";
    }

    @ResponseBody
    @RequestMapping("/send/array/two.html")
    public String testReceiveArrayTwo(ParamData paramData) {
        List<Integer> list = paramData.getArray();

        list.forEach(System.out::println);

        return "success";
    }

    @ResponseBody
    @RequestMapping("/send/array.html")
    public String testReceiveArrayOne(@RequestParam("array[]") List<Integer> list) {
        list.forEach(System.out::println);

        return "success";
    }

    @RequestMapping("/test/ssm.html")
    public String testSsm(ModelMap modelMap) {
        List<Admin> adminList = adminService.getAll();
        System.out.println(adminList);
        modelMap.addAttribute("adminList", adminList);
        modelMap.addAttribute("adminList2", adminList);
        modelMap.addAttribute("adminList4", adminList);

        return "/target";
    }

}
9.7.6 Ajax 发送复杂对象
  • Student 类
package com.atguigu.crowd.entity;

import java.util.List;
import java.util.Map;

public class Student {

    private Integer stuId;
    private String stuName;
    private Address address;
    private List<Subject> subjectList;
    private Map<String, String> map;

    public Student() {
    }

    public Student(Integer stuId, String stuName, Address address, List<Subject> subjectList, Map<String, String> map) {
        this.stuId = stuId;
        this.stuName = stuName;
        this.address = address;
        this.subjectList = subjectList;
        this.map = map;
    }

    public Integer getStuId() {
        return stuId;
    }

    public void setStuId(Integer stuId) {
        this.stuId = stuId;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Subject> getSubjectList() {
        return subjectList;
    }

    public void setSubjectList(List<Subject> subjectList) {
        this.subjectList = subjectList;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "Student{" +
                "stuId=" + stuId +
                ", stuName='" + stuName + '\'' +
                ", address=" + address +
                ", subjectList=" + subjectList +
                ", map=" + map +
                '}';
    }
}
  • Address 类
package com.atguigu.crowd.entity;

public class Address {

    private String province;
    private String city;
    private String street;

    public Address() {
    }

    public Address(String province, String city, String street) {
        this.province = province;
        this.city = city;
        this.street = street;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", street='" + street + '\'' +
                '}';
    }
}
  • Subject 类
package com.atguigu.crowd.entity;

public class Subject {

    private String subjectName;
    private Integer subjectScore;

    public Subject() {
    }

    public Subject(String subjectName, Integer subjectScore) {
        this.subjectName = subjectName;
        this.subjectScore = subjectScore;
    }

    public String getSubjectName() {
        return subjectName;
    }

    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }

    public Integer getSubjectScore() {
        return subjectScore;
    }

    public void setSubjectScore(Integer subjectScore) {
        this.subjectScore = subjectScore;
    }

    @Override
    public String toString() {
        return "Subject{" +
                "subjectName='" + subjectName + '\'' +
                ", subjectScore=" + subjectScore +
                '}';
    }
}
  • TestHandler - testReceiveComposeObject
    @ResponseBody
    @RequestMapping("/send/compose/object.html")
    public String testReceiveComposeObject(@RequestBody Student student) {
        Logger logger = LoggerFactory.getLogger(TestHandler.class);
        logger.info(student.toString());
        return "success";
    }
  • index - btn4
$("#btn4").click(function () {
    // 准备好要发送到服务器端的数组
    var student = {
        stuId: 5,
        stuName: "tom",
        address: {
            province: "广东",
            city: "深圳",
            street: "后端"
        },
        subjectList: [
            {
                subjectName: "javaSE",
                subjectScore: 100
            },
            {
                subjectName: "SSM",
                subjectScore: 99
            }
        ],
        map: {
            k1: "v1",
            k2: "v2"
        }
    }

    // 将 JSON 数组转换为 JSON 字符串
    var requestBody = JSON.stringify(student);

    $.ajax({
        url: "send/compose/object.html",      // 请求目标资源的地址
        type: "post",           // 请求方式
        data: requestBody,       // 请求体
        contentType: "application/json;charset=UTF-8",       // 请求体的内容类型, 告诉服务器本次请求的请求体是 JSON 数据
        dataType: "text",       // 如何对待服务器返回的数据
        success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
            alert(response);
        },
        error: function () {    // 服务器端处理请求失败后调用的回调函数

        }
    })
});
9.7.7 对 Ajax 请求返回的结果进行规范

img

package com.atguigu.crowd.util;

/**
 * 统一整个项目中 Ajax 请求返回的结果 (未来也可以用于分布式架构各个模块间调用时返回统一类型)
 *
 * @param <T>
 */
public class ResultEntity<T> {
    public static final String SUCCESS = "SUCCESS";
    public static final String FAILED = "FAILED";

    // 用来封装当前请求处理的结果是成功还是失败
    private String result;

    // 请求处理失败时返回的错误消息
    private String message;

    // 要返回的数据
    private T data;

    /**
     * 请求处理成功且不需要返回数据时使用的工具方法
     *
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithoutData() {
        return new ResultEntity<Type>(SUCCESS, null, null);
    }

    /**
     * 请求处理成功且需要返回数据时使用的工具
     *
     * @param data 要返回的数据
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithData(Type data) {
        return new ResultEntity<Type>(SUCCESS, null, data);
    }

    /**
     * 请求处理失败后使用的工具方法
     *
     * @param message 失败的错误消息
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> failed(String message) {
        return new ResultEntity<Type>(FAILED, message, null);
    }

    public ResultEntity() {
    }

    public ResultEntity(String result, String message, T data) {
        this.result = result;
        this.message = message;
        this.data = data;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResultEntity{" +
                "result='" + result + '\'' +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }
}
  • 测试 TestHandler -
    @ResponseBody
    @RequestMapping("/send/compose/object2.json")
    public ResultEntity<Student> testReceiveComposeObject2(@RequestBody Student student) {
        Logger logger = LoggerFactory.getLogger(TestHandler.class);
        logger.info(student.toString());

        // 将"查询"到的 Student 对象封装到 ResultEntity 中返回
        return ResultEntity.successWithData(student);
    }
  • 测试 index - btn5
	$("#btn5").click(function () {
      // 准备好要发送到服务器端的数组
      var student = {
          stuId: 5,
          stuName: "tom",
          address: {
              province: "广东",
              city: "深圳",
              street: "后端"
          },
          subjectList: [
              {
                  subjectName: "javaSE",
                  subjectScore: 100
              },
              {
                  subjectName: "SSM",
                  subjectScore: 99
              }
          ],
          map: {
              k1: "v1",
              k2: "v2"
          }
      }

      // 将 JSON 数组转换为 JSON 字符串
      var requestBody = JSON.stringify(student);

      $.ajax({
          url: "send/compose/object2.json",      // 请求目标资源的地址
          type: "post",           // 请求方式
          data: requestBody,       // 请求体
          contentType: "application/json;charset=UTF-8",       // 请求体的内容类型, 告诉服务器本次请求的请求体是 JSON 数据
          dataType: "JSON",       // 如何对待服务器返回的数据
          success: function (response) {  // 服务器端成功处理请求后调用的回调函数, response 是响应体数据
              alert(response);
          },
          error: function () {    // 服务器端处理请求失败后调用的回调函数

          }
      })
  });

9.8 Push

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值