SpringBoot默认的错误处理机制:

一、测试需要的部分代码

(完整代码放在了github https://github.com/lhy1234/spring-security):

UserController:只对新增用户做测试,省略其他代码

@RestController
@RequestMapping("/user")
public class UserController { /**
* 创建
* @Description:
* //@RequestBody:json映射到java
* @Valid 和User类上的@NotBlank注解一起做校验
* BindingResult存储的是校验错误信息
* @param @param user
* @param @return
* @return User
* @throws
* @author lihaoyang
* @date 2018年2月24日
*/
@PostMapping
public User create(@Valid @RequestBody User user){ //,BindingResult errors 先屏蔽BindingResult让springboot做错误处理,不屏蔽就能正常响应200了 // if(errors.hasErrors()){
// errors.getAllErrors().stream()
// .forEach(error -> System.err.println(error.getDefaultMessage()));
// } user.setId("1");
System.err.println(user);
return user;
} //省略其他代码。。。 }

User类:使用valid注解校验

public class User {

    public interface UserSimpleView {};
public interface UserDetailView extends UserSimpleView{}; //继承 private String id; @NotBlank(message="用户名不能为空")
private String username; @NotBlank(message="密码不能为空")
private String password;
@Past(message="生日只能是过去的日期")
private Date birthday; //省略get set }

一、对于进入controller之前就被打回的错误处理

 1、对于url不存在的400错误处理

springboot对浏览器和app的请求,处理是不一样的:

  1.1,使用浏览器,响应式的body一段html:

  使用Springboot,启动服务,使用浏览器访问一个不存在的url后,出现html空白页:

  

  浏览器发出的请求:请求头Content-Type:text/html;

  

  1.2,使用chrome插件restlet client(https://restlet.com/modules/client/)模拟app访问:

  

  使用restlet client模拟app访问不存在的url,响应体body是一个json:

  

                      图一           

从上图可以看出,使用app发出的请求请求头是contentType是json类型

springboot错误处理类控制器 BasicErrorController代码片段:

这个控制器处理的url是 /error ,但是会根据请求头里类型的不同,做不同的处理,浏览器发的请求走上边的,返回时html;app发的请求,走下边的方法,返回是一个json。

这里提供了一种机制:同一个url,不同的情况做不同的处理。

上边是对url不存在的400错误的处理,从图一可以看出,springboot的响应信息很简单:

错误码 400,加上响应体body:

{
"timestamp": 1519608427470,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/xxx"
}

2,对于不符合校验规则的错误处理

  User类的username和password是不能为空的,使用restlet client发出post请求,请求体为{},空的json,这样就不符合校验规则了(host是变量127.0.0.1):

  

响应头:

响应体:

会吧错误信息返回。

上边这两种情况,都是在进入controller之前就被spring打回的,一般我们需要在进入controller方法后,调用service过程中有异常来进行处理,下边模拟这种情况:

二、进入controller方法后发生了异常

在getInfo里直接抛出运行时异常模拟调用service发生错误:

/**
* 详情
* @Description: TODO
* @param @param id
* @param @return
* @return User
* @throws
* @author lihaoyang
* @date 2018年2月24日
*/
@GetMapping("{id:\\d+}") //{}里可以是正则,匹配数字
// @GetMapping("detail/{id}")
@JsonView(User.UserDetailView.class)
public User getInfo(@PathVariable(value="id",required=true) String id){ throw new RuntimeException("query deltail interface has error!"); // System.err.println(id);
// User user = new User();
// user.setUsername("tom");
// user.setPassword("123456");
// user.setId("1");
// return user;
}

使用浏览器访问:

对于浏览器也可以自定义错误页面,在src/main/resources下新建resources/error目录,可以自定义错误页面,这个对于app访问是无效的,app还是返回json

模拟app访问:错误中只包含抛出的异常信息

大部分情况,这种springboot对rest服务做的错误处理已经够用了。

如果还不够用也可以自己定义错误处理机制:

三、自定义异常

自定义异常:

package com.imooc.exception;

/**
* 用户不存在异常
* ClassName: UserNotExistException
* @Description: TODO
* @author lihaoyang
* @date 2018年2月26日
*/
public class UserNotExistException extends RuntimeException{
/**
* @Fields serialVersionUID : TODO
*/
private static final long serialVersionUID = 1L; private String id; public UserNotExistException(String id){
super("user not exist!");
this.id = id;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} }

controller方法:

    @GetMapping("{id:\\d+}") //{}里可以是正则,匹配数字
// @GetMapping("detail/{id}")
@JsonView(User.UserDetailView.class)
public User getInfo(@PathVariable(value="id",required=true) String id){ // throw new RuntimeException("query deltail interface has error!");
throw new UserNotExistException(id); // System.err.println(id);
// User user = new User();
// user.setUsername("tom");
// user.setPassword("123456");
// user.setId("1");
// return user;
}

此时浏览器访问,返回自定义的错误页

区别就在于app访问,exception类已经是自定义的了,但是异常信息message还不够详细,下面介绍怎么处理

统一异常处理类:

package com.imooc.web.controller;

import java.util.HashMap;
import java.util.Map; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import com.imooc.exception.UserNotExistException; /**
* @ControllerAdvice:处理其他controller抛出的异常,都会到这里处理
*/
@ControllerAdvice
public class ControllerExceptionHandler { @ExceptionHandler(UserNotExistException.class)//处理哪个异常类
@ResponseBody //返回json
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码 500
public Map<String,Object> handlerUserNotExistException(UserNotExistException ex){
Map<String,Object> result = new HashMap<>();
//通过ex对象拿到异常信息
result.put("id", ex.getId());
result.put("message", ex.getMessage());
return result;
}
}

app访问,可以打印自己想要的异常信息。

Spring Security构建Rest服务-0300-Restful API异常处理的更多相关文章

  1. Spring Security构建Rest服务-1001-spring social开发第三方登录之spring social基本原理

    OAuth协议是一个授权协议,目的是让用户在不将服务提供商的用户名密码交给第三方应用的条件下,让第三方应用可以有权限访问用户存在服务提供商上的资源. 接着上一篇说的,在第三方应用获取到用户资源后,如果 ...

  2. Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录

    基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...

  3. Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式

    SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...

  4. Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商

    实现服务提供商,就是要实现认证服务器.资源服务器. 现在做的都是app的东西,所以在app项目写代码  认证服务器: 新建 ImoocAuthenticationServerConfig 类,@Ena ...

  5. Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架

    基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...

  6. Spring Security构建Rest服务-0900-rememberMe记住我

    Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...

  7. Spring Security构建Rest服务-0400-使用切片拦截rest服务

    Restful API的拦截: 1,过滤器(Filter) 2,拦截器(Interceptor) 3,切片(Aspect) 1,过滤器 和传统javaweb一鸟样,例,记录controller执行时间 ...

  8. Spring Security构建Rest服务-1401-权限表达式

    Spring Security 的权限表达式 用法,在自定义的BrowserSecurityConfig extends WebSecurityConfigurerAdapter 配置文件里,每一个a ...

  9. Spring Security构建Rest服务-1205-Spring Security OAuth开发APP认证框架之Token处理

    token处理之二使用JWT替换默认的token JWT(Json Web Token) 特点: 1,自包含:jwt token包含有意义的信息 spring security oauth默认生成的t ...

  10. Spring Security构建Rest服务-1204-Spring Security OAuth开发APP认证框架之Token处理

    token处理之一基本参数配置 处理token时间.存储策略,客户端配置等 以前的都是spring security oauth默认的token生成策略,token默认在org.springframe ...

随机推荐

  1. python小练习--函数调用函数,让对象具有能动性

    class Box:#定义一个类名为Box,类名后不必有括号,类包含类属性和类方法,这个类没有定义类属性 '''这是一个计算体积的类'''#这是这个类的__doc__属性,执行类后就可以在交互界面输入 ...

  2. UVaLive 4452 The Ministers' Major Mess (TwoSat)

    题意:有 m 个人对 n 个方案投票,每个人最多只能对其中的4个方案投票(其他的相当于弃权),每一票要么支持要么反对.问是否存在一个最终决定,使得每个投票人都有超过一半的建议被采纳,在所有可能的最终决 ...

  3. html5获取经纬度

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. strcpy,strlen, strcat, strcmp函数,strlen函数和sizeof的区别

    //计算字符串实际长度        //strlen()函数:当遇到'\0'时,计算结束,'\0'不计入长度之内,如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下去,直到遇到'\0 ...

  5. RabbitMQ 初探

    有哪些优点 可靠性:RabbitMQ 提供了多种技术可以让你在性能和可靠性之间进行权衡.这些技术包括持久性.投递确认.发布者证实和高可用性. 灵活的路由:提供了多种内置交换机类型.如果你有更复杂的路由 ...

  6. 用idea简单创建web项目——两种方式

    最近同学让我教她们用idea创建web项目,于是我用两种方式创建web项目,并整理截图给她们看,一种是用maven创建,一种是不用maven创建,适合菜鸟哈哈~ 方法一:不用maven 1.解压tom ...

  7. WebAPI Token 验证

    WebAPI Token 验证 登录端 //HttpContext.Current.Session.Timeout = 10; ////生成Ticket //FormsAuthenticationTi ...

  8. Python 爬虫实战—盘搜搜

    近期公司给了个任务:根据关键搜索百度网盘共享文件并下载. 琢磨了几天写下了一段简单的demo代码,后期优化没有处理. 主要的思路:(1)根据关键字爬取盘搜搜的相关信息 (2)解析并获取盘搜搜跳转到百度 ...

  9. json--pyton中obj与json的互转,js中obj与json的互转

    json 解释:json是一种跨平台的通用的数据格式 python中对象(obj)与json之间的相互转换 1.对象(obj)转json格式的字符串 json.dumps(res) res = () ...

  10. WPF 的Listbox 滚动处理

    操作需求场景:Listbox 高150  item 高150 listbox有几十个item ,希望鼠标滚轮滚动一次listbox 能滚动到下一个item, 代码实现: <Grid x:Name ...