处理时间(Date
)类型
Spring Boot
进行参数绑定使用的是 SpringMvc
,涉及 Date
类型的参数绑定的时候,默认是时间格式是 yyyy/MM/dd
,我们可以自定义格式,只需要配置文件里面配置下:
# 日期格式
spring.mvc.date-format=yyyy.MM.dd
thymeleaf 页面拼接字符串
表达式之间直接使用 +
拼接,比如 :@{/emp/} + ${emp.id}
;
映射路径占位符
在映射路径中可以使用占位符的 @GetMapping(/emp/{id})
;这样参数传入 id
就会被放到
使用 put、delete 方法
表单 仅支持两种方法提交,POST ,GET
;
如果想要使用其他方法,则需要进行一番操作;
-
SpringMvc
配置HiddenHttpMethodFilter
(Spring Boot
已经自动配置好了,美滋滋); -
页面创建一个表单
-
创建一个
input
项,type
为hidden
,·name
属性值必须为_method
,然后value
属性的值,就写我们想要使用的方法:<input type="hidden" name="_method" value="put">
错误处理机制
-
Spring Boot
默认返回一个白板页面; -
自定义错误响应
-
定制错误的页面
-
有模板引擎
将错误页面放在 类路径 的
templates/error
文件夹下面,命名为 状态码.html ,这样发生错误的时候,就会去寻找状态码对应的页面;当然这样很傻,那么多状态码,需要写很多页面,因此,还可以直接创建
4xx.html
、5xx.html
,这样发生404,402,403
这些4xx
的错误的时候,由于没有对应的页面,就会退而其次,匹配4xx.html
页面,5xx
也是同样的道理 ;如果
4xx.html
、404.html
同时存在,这时候发生404
错误,会匹配上404.html
,精确优先 ;在页面中还可以获取一些信息:
timestamp
(时间戳)、status
(状态码)、error
(错误提示)、exception
(异常对象),message
(异常消息),errors
(JSR303
数据校验的错误信息) -
没有模板引擎
没有模板引擎,就去静态资源文件夹下面,寻找对应的
4xx.html ,5xx.html
; -
以上两种情况都没有
那就莫得选择了,只能使用
Spring Boot
的默认错误提示页面 ;
-
-
定制错误
JSON
自定义异常处理器,使用
@ControllerAdvice
标注类,然后在方法上,使用@ExceptionHandler
标注要处理什么异常,然后只要发生了对应的异常,该方法就会得到调用,方法参数可以写一些我们自己想要获得的对象;@ControllerAdvice public class MyExceptionController { @ResponseBody @ExceptionHandler({UserNotExistException.class}) public Map<String,Object> handlerUserNotExist(Exception e){ Map<String,Object> map = new HashMap<>(); map.put("code","Test Exception"); map.put("message",e.getMessage()); return map ; } }
方法的返回值,就会被送到页面,但是这样有个缺点,丢失自适应效果(本来浏览器和终端方法,
Spring Boot
会显示不同的效果的,浏览器显示 白板错误页面,终端显示JSON
串 ),无论是浏览器还是终端,都显示JSON
串;进行改动下,转发到
/error
炸,就可以自适应了:@ExceptionHandler({UserNotExistException.class}) public String handlerUserNotExistAdaptive(Exception e){ Map<String,Object> map = new HashMap<>(); map.put("code","Test Exception"); map.put("message",e.getMessage()); // 转发到 /error return "forward:/error" ; }
但是 又有新问题了:发生异常以后,状态码,就会变成
4xx ,5xx
,然后被我上面的方法捕捉到以后,来了一个转发,异常被吞咽了,异常链断掉了,状态码已经变了,变为正常的200
,因为转发又没发生异常;虽然转发到
/error
,但是状态码已经变了,此时去/error
下面,没有对应的页面了,就只能找默认的页面了;因此,我们在转发之前,设置下状态码:
request.setAttribute("javax.servlet.error.status_code",400);
,键不是瞎写的,是必须是这个:@ExceptionHandler({UserNotExistException.class}) public String handlerUserNotExistAdaptive(Exception e, HttpServletRequest request){ request.setAttribute("javax.servlet.error.status_code",400); Map<String,Object> map = new HashMap<>(); map.put("code","Test Exception"); map.put("message",e.getMessage()); // 转发到 /error return "forward:/error" ; }
现在还有最后一个问题,我们在转发的时候,带过去的数据,页面其实拿不到的,现在要解决这个问题:
页面上能用的数据,或者
JSON
返回能用的数据,其实都是在ErrorAttributes.class
类里面的,通过getErrorAttibutes
获取的,因此,我们只需要获取到getErrorAttibutes
方法的返回值,然后再返回值里面添加上我们自己的数据即可 ;@Component public class MyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) { Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace); errorAttributes.put("message","Test"); return errorAttributes; } }
-
如果我们在别的地方也有数据想要带到页面,需要向下面这样做:
-
首先在转发之前,将我们的数据放到域里面;
@ExceptionHandler({UserNotExistException.class}) public String handlerUserNotExistAdaptive(Exception e, HttpServletRequest request){ request.setAttribute("javax.servlet.error.status_code",400); Map<String, Object> myErrorAttributesMap = new HashMap<>(); myErrorAttributesMap.put("message","sasasa"); myErrorAttributesMap.put("code","Test Exception"); request.setAttribute("errorAttributesMap",myErrorAttributesMap); // 转发到 /error return "forward:/error" ; }
-
然后在
getErrorAttibutes
方法,从域里面取出来,然后添加到getErrorAttibutes
方法的返回值中;
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
// 数字代表域,0 是 request , 1 是 session ,
Map<String, Object> errorAttributesMap = (Map<String, Object>) webRequest.getAttribute("errorAttributesMap", 0);
Map<String, Object> errorAttributes = super.getErrorAttributes(webRequest, includeStackTrace);
errorAttributes.put("message","Test");
errorAttributes.put("error",errorAttributesMap);
return errorAttributes;
}