先前的记录:
【尚筹网IDEA版】02-数据库创建、Mybatis逆向、Spring整合Mybatis
代码下载:
git clone https://github.com/YuanbaoQiang/atcrowdfunding.git
Spring-MVC下的ajax请求
基本流程
前端代码
$("#btn4").click(function () {
// 准备要发送的数据
var student = {
"stuId":10,
"stuName":"tom",
"address":{
"province":"湖南",
"city":"长沙",
"street":"岳麓"
},
"subjectList":[
{
"subjectName":"JavaSE",
"subjectScore":99
},
{
"subjectName":"SSM",
"subjectScore":98
}
],
"map":{
"key1":"v1",
"key2":"v2"
}
};
// 将jason对象转换为json字字符串
let 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);
}
});
});
Handler方法处理
@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;
}
控制台打印:
日志输出:
[15:17:49.147] [INFO ] [http-nio-8080-exec-6] [com.yuanbaoqiang.crowd.mvc.handler.TestHandler] [Student(stuId=10, stuName=tom, address=Address(province=湖南, city=长沙, street=岳麓), subjectList=[subject(subjectName=JavaSE, subjectScore=99), subject(subjectName=SSM, subjectScore=98)], map={key1=v1, key2=v2})]
注意:如果日志乱码,在encoder
标签中增加一行 <charset>UTF-8</charset>
即可。
异常映射
使用异常映射机制将整个项目的异常和错误提示进行统一管理。
基于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>
</props>
</property>
</bean>
注意:
1.exceptionMappings
是SimpleMappingExceptionResolver
的一个成员属性。
2.prop
中的system-error会经过视图解析器处理,所以如果发生java.lang.Exception异常就会跳转到system-error.jsp页面
补充:
对于简单的handler方法,完全可以用view-controller
替代,直接吧请求地址和视图名称关联起来,不必配置handler方法
@RequestMapping("/admin/to/login/page.html")
public String toLoginPage(){
return "admin-login";
}
等同于
<mvc:view-controller path="/admin/to/login/page.html" view-name="admin-login"/>
基于注解的异常处理
基于注解的方式主要涉及到两个注解:
@ControllerAdvice
:这个注解就是增强型控制器,作用是将对于控制器的全局配置放在同一个位置(类)。
@ExceptionHandler
:将一个具体的异常类型和一个方法关联起来
创建具体的类:CrowdExceptionResolver
,统一管理异常。
package com.yuanbaoqiang.crowd.mvc.config;
import com.google.gson.Gson;
import com.yuanbaoqiang.crrowd.constant.CrowdConstant;
import com.yuanbaoqiang.crrowd.util.CrowdUtil;
import com.yuanbaoqiang.crrowd.util.ResultEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @description:
* @author: YuanbaoQiang
* @time: 2020/11/4 19:13
*/
// @ControllerAdvice 表示当前类是一个基于注解的异常处理器类
@ControllerAdvice
public class CrowdExceptionResolver {
@ExceptionHandler(value = ArithmeticException.class)
public ModelAndView resolveMathException(ArithmeticException exception, HttpServletRequest request, HttpServletResponse response
) throws IOException {
String viewName = "system-error";
return commonResolve(viewName,exception,request,response);
}
// @ExceptionHandler将一个具体的异常类型和一个方法关联起来
@ExceptionHandler(value = NullPointerException.class)
public ModelAndView resolveNullPonintException(NullPointerException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
String viewName = "system-error";
return commonResolve(viewName,exception,request,response);
}
/*
* @description: 一个通用的异常处理方法
* @param viewName
* @param exception
* @param request
* @param response
* @return: org.springframework.web.servlet.ModelAndView
* @author: YuanbaoQiang
* @time: 2020/11/4 19:55
*/
private ModelAndView commonResolve(
String viewName, // 异常处理完成后跳转的页面
Exception exception, // 实际捕获到的异常类型
HttpServletRequest request, // 请求
HttpServletResponse response // 响应
) throws IOException {
// 1. 判断当前请求的类型
boolean judgrResult = CrowdUtil.judgeRequestType(request);
// 2. 如果时ajax请求
if(judgrResult){
// 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;
}
}
工具类的创建
CrowdConstant
:用于统一管理常量,防止再开发过程中因为书写错误而导致的报错!
package com.yuanbaoqiang.crrowd.constant;
/**
* @description: 统一管理常量
* @author: YuanbaoQiang
* @time: 2020/11/4 20:03
*/
public class CrowdConstant {
public static final String MESSAGE_LOGIN_FAILED = "抱歉!账号密码错误!请重新输入";
public static final String MESSAGE_LOGIN_ACCT_ALREADY_IN_USE = "抱歉!这个账号已经被使用了!";
public static final String MESSAGE_ACCESS_FORBIDEN = "请登录以后再访问!";
public static final String ATTR_NAME_EXCEPTION = "exception";
}
CrowdUtil
:判断当前的请求是否为Ajax请求(可以在浏览器的请求头查看是否有以下参数!)
package com.yuanbaoqiang.crrowd.util;
import javax.servlet.http.HttpServletRequest;
/**
* @description:
* @author: YuanbaoQiang
* @time: 2020/11/4 18:53
*/
public class CrowdUtil {
/*
* @description: 判断当前的请求是否为Ajax请求
* @param request
* @return: boolean
* @author: YuanbaoQiang
* @time: 2020/11/4 19:11
*/
public static boolean judgeRequestType(HttpServletRequest request){
// 1. 获取请求消息头
String acceptHeader = request.getHeader("Accept");
String xRequestHeader = request.getHeader("X-Requested-With");
// 2. 判断当前请求是否为ajax请求
return (acceptHeader != null && acceptHeader.contains("application/json"))||
(xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"));
}
}