众筹项目之环境配置(三)

本文详细介绍了在SpringMVC环境下如何处理Ajax请求,包括@RequestBody和@ResponseBody注解的使用,以及异常映射的配置,强调了在发送复杂对象时使用JSON请求体的重要性,并讲解了如何统一返回数据格式。
摘要由CSDN通过智能技术生成

11. SpringMVC 环境下的 Ajax 请求

在这里插入图片描述

11.1 建立意识

前端发送过来,后端要处理的请求有两种:
普通请求:后端处理完成后返回页面,浏览器使用使用页面替换整个窗口中的内容
Ajax 请求:后端处理完成后通常返回 JSON 数据,jQuery 代码使用 JSON 数据
对页面局部更新

11.2 常用注解

在这里插入图片描述
ResponseBody和@RequestBody要想正常工作必须有jackson的支持,请确认当前环境引入了如下依赖

11.2.2加入依赖

在这里插入图片描述

<!-- Spring进行JSON数据转换依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <!-- 引入 Servlet 容器中相关依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSP 页面使用的依赖 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1.3-b06</version>
            <scope>provided</scope>
        </dependency>

11.2.3 加入 jQuery

在这里插入图片描述
在这里插入图片描述

11.3 @RequestBody 注解

11.3.1 作用

让 handler 方法的返回值本身就是当前请求的响应数据。不再参考视图处理器
中配置的前后缀信息。

@Controller
public class TestHandler {
	@Autowired
    private AdminService adminService;
    private Logger logger = LoggerFactory.getLogger(TestHandler.class);
    
    @RequestMapping("/test/ssm.html")
    public String testSsm(ModelMap modelMap){

        List<Admin> adminList = adminService.getAll();
        modelMap.addAttribute("adminList", adminList);


        return "target";
    }
}

11.3.2 注意

开启 SpringMVC 的注解驱动
mvc:annotation-driven/
必须有 jackson 依赖
jackson-core
jackson-databind
扩展名需要和实际返回的数据格式一致
响应体返回 JSON
请求扩展名*.json
web.xml 中 DispatcherServlet 必须映射*.json 扩展名

11.4 @ResponseBody 注解

11.4.1 场景设定

jQuery 通过 Ajax 请求给服务器端发送一个数组:[5,8,12]

11.4.2 尝试方案一

前端发送数据

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

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

浏览器开发者工具看到的请求体
在这里插入图片描述

jQuery 私自在请求参数名字后面附加了“[]”
后端接收数据

@ResponseBody
    @RequestMapping("/send/array/one.html")
    public String testReceiveArrayOne(@RequestParam("array[]") List<Integer> array){
        for (Integer number : array){
            System.out.println("number=" + number);
        }
        return "success";
    }

这里一定要带上多出来的方括号!!!
结论:不建议采用这个方案!!!

11.4.3 尝试方案二

前端发送数据

$("#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) {    //服务器端成功处理请求后调用的回调函数,
                        alert(response);
                    },
                    "error": function (response) {     //服务器端处理请求失败后调用的回调函数,
                        alert(response);
                    }
                });
            });

浏览器开发者工具看到的请求体
在这里插入图片描述

后端接收数据

@ResponseBody
    @RequestMapping("/send/array/two.html")
    public String testReceiveArrayTwo(ParamData paramData){
        List<Integer> array = paramData.getArray();
        for (Integer number : array){
            System.out.println("number=" + number);
        }
        return "success";
    }

结论:这个方案不成立!

11.4.4 尝试方案三

前端发送数据

$("#btn3").click(function () {
                    //准备好要发送到服务器端的数组
                var array = [5, 8, 12];
                console.log(array.length);

                    //将JSON数组转换未JSON字符串
                var requestBody = JSON.stringify(array);
                //"['5', '8', '12']"
                console.log(requestBody.length);

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

浏览器开发者工具看到的请求体
在这里插入图片描述

后端接收数据

@ResponseBody
    @RequestMapping("send/array/three.html")
    public String testReceiveArrayThree(@RequestBody List<Integer> array){
        for (Integer number : array) {
            logger.info("number=" + number);
        }
        return "success";
    }

结论:建议使用的方案!!!

11.4.5 需要注意的点

前端
首先准备好要发送的 JSON 数据
JSON 对象
JSON 数组
将 JSON 对象或 JSON 数组转换为 JSON 字符串
var arrayStr = JSON.stringify(array);
将 JSON 字符串直接赋值给 data 属性
“data”:arrayStr
必须要设置 contentType
“contentType”:“application/json;charset=UTF-8”
后端
加入 jackson 依赖
开启注解驱动
使用注解
@RequestBody Integer[] empIdArray

11.4.6 发送复杂对象举例

前端发送数据

$("#btn4").click(function () {
                //准备要发送的数据
                var student = {
                    "stuId": 5,
                    "stuName": "tom",
                    "address": {
                        "province": "广东",
                        "city": "深圳",
                        "street": "后瑞"
                    },
                    "subjectsList": [
                        {
                            "subjectName": "JavaSE",
                            "subjectScore": 100
                        },{
                            "subjectName": "SSM",
                            "subjectScore": 99
                        }
                    ],
                    "map": {
                        "k1": "v1",
                        "k2": "v2"
                    }
                };

                //将JSON对象转换未JSON字符串
                var requestBody = JSON.stringify(student);

                //发送Ajax请求
                $.ajax({
                    "url": "/send/compose/object.json",
                    "type": "post",
                    "data": requestBody,
                    "contentType": "application/json;charset=UTF-8",
                    "dataType": "json",
                    "success": function (response) {
                        console.log(response);
                    },
                    "error": function (response) {
                        console.log(response);
                    }
                })
            });

浏览器开发者工具中看到的请求体
在这里插入图片描述

后端接收数据

@ResponseBody
    @RequestMapping("/send/compose/object.json")
    public ResultEntity<Student> testReceiveComposeObject(@RequestBody Student student, HttpServletRequest request){
        boolean judgeResult = CrowdUtil.judgeRequestType(request);

        logger.info("judgeResult=" + judgeResult);
        logger.info(student.toString());
        //将"查询"到的Student对象封装到ResultEntity中返回
        ResultEntity<Student> resultEntity = ResultEntity.successWithData(student);
        String a = null;
        System.out.println(a.length());
        return  resultEntity;
    }

11.4.7小结

@RequestBody 使用的场景:传统发送请求参数方式不方便发送的数据,使用
JSON 请求体的方式发送。特别是要发送复杂对象的时候。

11. 5对比

在这里插入图片描述
在这里插入图片描述

11.6 统一返回数据格式

/**
* 用于统一项目中所有 Ajax 请求的返回值类型
* @author Lenovo
*
* @param <T>
*/
public class ResultEntity<T> {
public static final String SUCCESS = "SUCCESS";
public static final String FAILED = "FAILED";
public static final String NO_MESSAGE = "NO_MESSAGE";
public static final String NO_DATA = "NO_DATA";
/**
* 返回操作结果为成功,不带数据
* @return
*/
public static <E> ResultEntity<E> successWithoutData() {
return new ResultEntity<E>(SUCCESS, NO_MESSAGE, null);
}
/**
* 返回操作结果为成功,携带数据
* @param data
* @return
*/
public static <E> ResultEntity<E> successWithData(E data) {
return new ResultEntity<E>(SUCCESS, NO_MESSAGE, data);
}
/**
* 返回操作结果为失败,不带数据
* @param message
* @return
*/
public static <E> ResultEntity<E> failed(String message) {
return new ResultEntity<E>(FAILED, message, null);
}
private String operationResult;
private String operationMessage;
private T queryData;
public ResultEntity() {
}
public ResultEntity(String operationResult, String operationMessage, T queryData) {
super();
this.operationResult = operationResult;
this.operationMessage = operationMessage;
this.queryData = queryData;
}
@Override
public String toString() {
return "AjaxResultEntity [operationResult=" + operationResult + ", operationMessage="
+ operationMessage
+ ", queryData=" + queryData + "]";
}
public String getOperationResult() {
return operationResult;
}
public void setOperationResult(String operationResult) {
this.operationResult = operationResult;
}
public String getOperationMessage() {
return operationMessage;
}
public void setOperationMessage(String operationMessage) {
this.operationMessage = operationMessage;
}
public T getQueryData() {
return queryData;
}
public void setQueryData(T queryData) {
this.queryData = queryData;
}
}

12. 前端页面

12.1 静态资源引入

12.1.1 来源

“前端页面”目录下
在这里插入图片描述

12.1.2 复制到工程中的位置

在这里插入图片描述

12.2 初步显示管理员登录页面

12.2.1 准备页面文件

在这里插入图片描述

12.2.2 调整admin-login.jsp页面文件

把页面文件的内容从原型文件中复制过来,再进行必要的调整

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="keys" content="">
    <meta name="author" content="">
    <base href="http://${pageContext.request.serverName }:${pageContext.request.serverPort }${pageContext.request.contextPath }/"/>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>

    <style>

    </style>
</head>

12.2.3 配置 view-controller

在这里插入图片描述

12.3layer 弹层组件

在这里插入图片描述

12.3.1 解压

12.3.2 加入 layer 环境

在这里插入图片描述

12.3.3 页面引入 layer

在这里插入图片描述

12.3.4 使用

在这里插入图片描述

13 异常映射

13.1 作用

统一管理项目中的异常
抛出异常
显示异常信息
普通请求:在页面上显示异常信息
Ajax 请求:返回 JSON 数据

13.2 异常映射的工作机制

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

13.3 判断请求类型的工具方法

13.3.1 判断依据

在这里插入图片描述

13.3.2 创建工具类

在这里插入图片描述

13.3.3 代码

/**
     * 判断当前请求是否为Ajax请求
     *
     *      true:当前请求是Ajax请求
     *      false:当前请求不是Ajax请求
     */
    public static boolean judgeRequestType(HttpServletRequest request){

        //1.获取请求消息头
        String acceptHeader = request.getHeader("Accept");
        String xRequestHeader = request.getHeader("X-Requested-With");

        //2.判断
        if ((acceptHeader != null && acceptHeader.contains("application/json"))
            ||
        (xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"))){
            return true;
        }
        return false;
    }

13.4 异常映射实现方式

13.4.1 基于 XML

spring-web-mvc.xml 文件中的配置

   <!--配置基于XML的异常映射-->
            <bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
                <!-- 配置异常类型和具体视图页面的对应关系-->
                <property name="exceptionMappings">
                    <props>
                        <!-- key属性指定异常全类名-->
                        <!-- 标签中写对应的视图(这个值要拼前后缀得到具体路径)-->
                        <prop key="java.lang.Exception">system-error</prop>
                        <prop key="com.atguigu.crowd.exception.AccessForbiddenException">admin-login</prop>
                    </props>
                </property>
            </bean>

新建 system-error.jsp 页面

13.4.2 基于注解

在这里插入图片描述

创建异常处理器类

在这里插入图片描述

 @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveMathException(
            ArithmeticException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response
            ) throws IOException {

        String viewName = "admin-login";

        return commonResolve(viewName, exception, request, response);
    }

    // @ExceptionHandler将一个具体的异常类型和一个方法关联起来
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(
            //实际捕获到的异常类型
            NullPointerException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

            String viewName = "system.error";

            return commonResolve(viewName, exception, request, response);

    }
    private ModelAndView commonResolve(

            //异常处理完成后要去的页面
            String viewName,
            //实际捕获到的异常类型
            Exception exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {
        //1.判断当前请求类型
        boolean judgeReqsult = CrowdUtil.judgeRequestType(request);

        //2.如果是Ajax请求
        if (judgeReqsult){

            //3.创建ResultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());

            //4.创建Gson对象
            Gson gson = new Gson();

            //5.将ResultEntity对象转换为JSON字符串
            String json = gson.toJson(resultEntity);

            //6.将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(json);

            //7.由于上面已经通过原生的 response对象返回了响应,所有不提供ModelAndView对象
            return null;
        }

        //8.如果不是Ajax请求则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();

        //9.将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);

        //10.设置对应的视图名称
        modelAndView.setViewName(viewName);

        //11.返回ModelAndView
        return modelAndView;

    }

14. 以常量管理属性名和异常消息

在这里插入图片描述

public static final String MESSAGE_LOGIN_FAILED = "抱歉! 账号密码错误!请重新输入!";
    public static final String ATTR_NAME_EXCEPTION = "exception";

好处:减少打字错误!!!

14.1 创建管理员登录页面

在这里插入图片描述

15. 创建后台管理员登录页面(后台首页)

15.1 创建admin-login.jsp

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

15.2 跳转到登录页面

15.2.1 配置 view-controller

在这里插入图片描述
在这里插入图片描述

16. 使用layer弹层组件

16.1 加入layer库文件和样式文件

在这里插入图片描述

16.2 在页面上引入layer环境

在这里插入图片描述

16.3 修饰system-error页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="keys" content="">
    <meta name="author" content="">
    <base href="http://${pageContext.request.serverName }:${pageContext.request.serverPort }${pageContext.request.contextPath }/"/>
    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/font-awesome.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>
    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
               //相当于浏览器的后退按钮
                window.history.back();
            });
        });
    </script>
    <style>

    </style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <div><a class="navbar-brand" href="index.html" style="font-size:32px;">尚筹网-创意产品众筹平台</a></div>
        </div>
    </div>
</nav>

<div class="container">


        <h2 class="form-signin-heading" style="text-align: center;">
            <i class="glyphicon glyphicon-log-in"></i> 尚筹网系统消息
        </h2>
            <%--
                requestScope对应的是存放request域数据的Map
                requestScope.exception相当于request.getAttribute("exception")
                requestScope.exception.message相当于exception.getMessage()
            --%>
        <h3 style="text-align: center;">${requestScope.exception.message}</h3>
        <button type="submit" style="width: 150px; margin: 50px auto 0px auto"  class="btn btn-lg btn-success btn-block">
            点我返回上一步</button>
</div>

</body>
</html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值