前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security技术栈开发企业级认证与授权(四)RESTful API服务异常处理

Spring Security技术栈开发企业级认证与授权(四)RESTful API服务异常处理

作者头像
itlemon
发布2020-04-03 14:39:22
7750
发布2020-04-03 14:39:22
举报
文章被收录于专栏:深入理解Java深入理解Java

当我们从浏览器访问不存在的Spring BootRESTful API的时候,往往会返回Spring Boot内置的404错误界面,但是作为前后端分离的应用,相同的API也许会在其他终端访问,比如手机APP等,那么也会是相同的处理方式吗?

一、Spring Boot的默认处理方式分析
  • 从浏览器端访问

启动Spring Boot项目,从浏览器访问一个不存在的API,如“/user/hello”,这时候返回来的是一个HTML页面,如下图所示:

Spring Boot默认的404界面
Spring Boot默认的404界面
  • APP端访问

APP端访问我们可以使用模拟RESTful API发送器来进行发送,我这里使用的Paw软件,你可以在你的谷歌浏览器上安装Postman来进行发送。访问“/user/hello”返回的结果如下如所示:

从客户端访问返回的结果
从客户端访问返回的结果

对比上面的两种访问方式,返回的错误类型是不一样的,浏览器访问返回的是一个HTML页面,而客户端访问返回的是一个JSON数据。那么问题来了,Spring Boot是如何确定当前请求来自浏览器还是客户端?我们可以从它的源代码中找到答案。 这段源代码来自于Spring Boot的一个包org.springframework.boot.autoconfigure.web中的BasicErrorController,从类名就可以知道它是一个Controller,且处理的路径就是“/error”。找到错误处理的两个方法,如下图所示:

这里写图片描述
这里写图片描述

第一个方法和第二个方法处理的都是同一个API,区别就在于第一个方法的@RequestMapping里面包含一个produces属性,它表示将生成什么类型的资源返回给前端,很明显,第一个方法要返回的是一个HTML页面,而第二个方法返回的是JSON数据。这就很明了了,当浏览器访问错误的API的时候,会自动进入第一个方法处理错误,从客户端访问的时候,就会进入第二个方法处理错误。当然,从浏览器发送的请求的时候,我们可以看见请求头中看到浏览器要求的返回数据类型就包含了text/html,如下图所示:

这里写图片描述
这里写图片描述

以上的例子都是访问资源不存在的案例,访问的处理逻辑并未进入对应的Controller就被Spring Boot打回去了,如果是服务代码抛出了异常,Spring Boot是如何处理的呢?在这里我再写一个Controller,手动抛出异常。代码如下:

代码语言:javascript
复制
@GetMapping("/user5")
@ResponseBody
public User user5() {
    throw new RuntimeException("User is not exist.");
}

从浏览器端访问http://localhost:8080/user5,返回的依然是HTML页面,如下所示:

这里写图片描述
这里写图片描述

而从客户端访问,返回的依然是JSON数据,如下图所示:

这里写图片描述
这里写图片描述
二、自定义服务异常处理

在实际的开发过程中,如果出现404或者500的错误的时候,返回给浏览器是Spring Boot默认的处理界面,这并不友好,我们可以实现自定义页面来给出更好的温馨提示。

  • 浏览器端自定义处理方式

这里仅仅介绍一种最简单的方式来处理异常,在resources文件夹下再建立一个resources文件夹,然后再在新建的resources文件夹下建立一个error,在error文件夹里面建立404.html500.html,在访问出现404错误的时候,就会跳转到我们自己定义的HTML中,而不是Spring Boot默认的界面。

  • 自定义服务异常处理类 在实际的开发中,我们完全可以自定义服务异常处理类,以满足实际的开发需求。这里写一个异常类,在业务逻辑处理中,可以根据需要手动抛出自己自定义的异常。比如:
代码语言:javascript
复制
package com.lemon.security.web.exception;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * @author lemon
 * @date 2018/4/1 下午2:08
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class UserNotExistException extends RuntimeException {

    private Integer id;

    public UserNotExistException(Integer id) {
        super("user not exist.");
        this.id = id;
    }
}

为了测试,在Controller添加一个方法,代码如下:

代码语言:javascript
复制
@GetMapping("/user6/{id:\\d+}")
@ResponseBody
public User user6(@PathVariable Integer id) {
    throw new UserNotExistException(id);
}

当访问这个API的时候,就会抛出我们自定义的异常,这时候,Spring Boot默认的处理方式返回的结果如下图:

这里写图片描述
这里写图片描述

有时候我们前端不需要这么多的信息,只需要部分信息,这个时候就需要自定义异常处理了,而不是采用Spring Boot的默认处理方式了,在这里,我们可以写一个异常处理类,专门用来处理自定义异常。

代码语言:javascript
复制
package com.lemon.security.web.exception.handler;

import com.lemon.security.web.exception.UserNotExistException;
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 java.util.HashMap;
import java.util.Map;

/**
 * 自定义错误处理逻辑
 *
 * @author lemon
 * @date 2018/4/1 下午2:48
 */
@ControllerAdvice
public class UserNotExistExceptionHandler {

    @ExceptionHandler(UserNotExistException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public Map<String, Object> handleUserNotExistException(UserNotExistException ex) {
        Map<String, Object> result = new HashMap<>();
        result.put("id", ex.getId());
        result.put("message", ex.getMessage());
        return result;
    }
}

当一个类加上了@ControllerAdvice注解,那么这个类就具备了处理其他Controller异常的能力,具体的处理方式还是通过方法来进行的。上面的方法就是专门来处理UserNotExistException这个异常的,@ExceptionHandler就是指定了需要被处理的异常,@ResponseStatus指定状态码,最后将处理后的数据返回。定义好这个类之后,当代码中抛出了UserNotExistException异常的时候,都会转到这个方法中进行处理。再次运行应用,访问http://localhost:8080/user6/1返回的数据如下如所示:

这里写图片描述
这里写图片描述

这就是我们自定义的异常处理后的数据了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Spring Boot的默认处理方式分析
  • 二、自定义服务异常处理
相关产品与服务
Serverless HTTP 服务
Serverless HTTP 服务基于腾讯云 API 网关 和 Web Cloud Function(以下简称“Web Function”)建站云函数(云函数的一种类型)的产品能力,可以支持各种类型的 HTTP 服务开发,实现了 Serverless 与 Web 服务最优雅的结合。用户可以快速构建 Web 原生框架,把本地的 Express、Koa、Nextjs、Nuxtjs 等框架项目快速迁移到云端,同时也支持 Wordpress、Discuz Q 等现有应用模版一键快速创建。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档