Springboot 实现api接口(一)

Springboot 实现api接口(一)

1、序言

网络程序正朝着移动设备的方向发展,前后端分离、APP,最好的交互交互方式莫过于通过API接口实现。

本项目加密方式采用参数排序+key验签方式,后期可按需求更换

本次我们先了解一下Spring对API接口开发的支持,然后我们采用Spring Boot搭建项目,本项目暂未使用权限管理系统,后期主键完善,可按需求对key进行配置或者使用安全框架进行管理。借用Swagger列出API接口,便于查阅。

2、返回格式

根据当前趋势,API接口要求返回的格式一般为 application/json,有特殊行业如银行等返回格式为xml报文,本次统一使用json。Spring Boot返回json,提供了两种实现方式:类注解方法注解

类注解 @RestController

@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/saveUser")
    public Object saveUser(@Validated User user){
        return user;
    }
}

方法注解 @ResponseBody

@Controller
@RequestMapping("/demo")
public class Demo {
    @RequestMapping
    @ResponseBody
    public String getCapitalize(String args){
        return args.toUpperCase();
    }
}

值得提醒的是,虽然都是都可以,但我更推荐使用类注解,项目的主要目的是提供和统一api接口,会显得我们的编码风格十分统一,代码更加紧凑,不至于看起来零散。

注:Mapping根据业务自行选择,推荐@GetMapping、@PostMapping格式。

3、接收参数/参数验证

  • 举例说明
@GetMapping("/saveUser")
public Object saveUser(@Validated User user){
    return user;
}
  • 可以使用validation进行参数验证
    maven导包
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-validationartifactId>
dependency>

在实体参数上添加注解来达到验证参数的效果,然后在方法参数前添加@Validated开启验证。如果参数错误会抛出BindException异常,后期统一异常处理响应。

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)//解决参数为null不返回前端
public class User implements Serializable {
    private Long Id;
    @NotNull(message = "用户名不能为空")
    private String username;
    @NotNull(message = "年龄不能为空")
    private Integer age;
    private String email;
}

4、异常统一处理

每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。 为了将所有类型的异常处理从各处理过程解耦出来,保证相关处理过程的功能较单一,实现异常信息的统一处理和维护。

Spring MVC处理异常有3种方式:

  • 使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;

  • 实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;

  • 使用@ExceptionHandler注解实现异常处理;

今天主要说springboot基于@ExceptionHandler注解实现异常处理

@ExceptionHandler注解:定义控制器发生异常后的操作,可以拦截所有控制器发生的异常。统一异常处理 ,通过@ExceptionHandler(value = Exception.class) 来指定捕获的异常。“@ControllerAdvice + @ExceptionHandle" 可以处理除“404”以外的运行异常。

  1. 创建BaseBusinessException类(自定义业务异常),继承RuntimeException类。
package com.cch.error;

import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Auther: cch
 * @Date: 2020/9/21 16:03
 * @Description: 自定义异常返回结果实体类
 */
@Data
@NoArgsConstructor
public class BaseBusinessException extends RuntimeException{

    private BaseError error = DefaultError.SYSTEM_INTERNAL_ERROR;
    private String extMessage = null;

    public BaseBusinessException(String message) {
        super(message);
        this.extMessage = message;
    }
    public BaseBusinessException(String message, Throwable cause) {
        super(message, cause);
        this.extMessage = message;
    }
    public BaseBusinessException(Throwable cause) {
        super(cause);
    }
    public BaseBusinessException(BaseError error) {
        this.error = error;
    }
    public BaseBusinessException(String message, BaseError error) {
        super(message);
        this.extMessage = message;
        this.error = error;
    }
    public BaseBusinessException(String message, Throwable cause, BaseError error) {
        super(message, cause);
        this.extMessage = message;
        this.error = error;
    }
    public BaseBusinessException(Throwable cause, BaseError error) {
        super(cause);
        this.error = error;
    }
}

  1. 创建统一响应类
package com.cch.error;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

/**
 * @Auther: cch
 * @Date: 2020/9/21 16:12
 * @Description: 相应结果实体类
 */
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response {

    private String code;
    private Object data;
    private String message;

}

  1. 创建ExceptionControllerAdvice类(全局异常处理器),使用ResponseEntity返回自定义响应码 – 508。
package com.cch.exception;

import com.cch.error.BaseBusinessException;
import com.cch.error.DefaultError;
import com.cch.error.Response;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * @Auther: cch
 * @Date: 2020/9/21 14:07
 * @Description: 全局处理异常
 */
@RestControllerAdvice
public class ExceptionControllerAdvice {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Response> APIExceptionHandler(Exception exception) {

        Response response = new Response();

        if (exception instanceof BaseBusinessException) {
            BaseBusinessException bbe = (BaseBusinessException)exception;
            response.setCode(bbe.getError().getErrorCode());
            response.setData(bbe.getError().getErrorMessage());
            if (exception.getMessage() != null) {
                response.setData(exception.getMessage());
            }
        } else if (exception instanceof BindException) {
            BindException bindException = (BindException)exception;
            response.setCode(DefaultError.PARAMETER_ERROR.getErrorCode());
            response.setData(DefaultError.PARAMETER_ERROR.getErrorMessage());
            FieldError fieldError = bindException.getBindingResult().getFieldError();
            response.setMessage(fieldError.getDefaultMessage());
        }else{
            exception.printStackTrace();
            response.setCode(DefaultError.SYSTEM_INTERNAL_ERROR.getErrorCode());
            response.setData(DefaultError.SYSTEM_INTERNAL_ERROR.getErrorMessage());
        }
        return new ResponseEntity (response, HttpStatus.LOOP_DETECTED);
    }

}

当项目中又异常可直接抛出,示例:

    @GetMapping("/saveUser")
    public Object saveUser(@Validated User user){
        if(user == null){
            throw new BaseBusinessException("用户不能为空");
        }
        return user;
    }

附:异常使用枚举,可根据个人需求灵活使用,这是我个人使用习惯。
BaseError接口

package com.cch.error;

/**
 * @Auther: cch
 * @Date: 2020/9/21 16:06
 * @Description: 异常枚举父接口
 */
public interface BaseError {
    String getErrorCode();
    String getErrorMessage();

}

可根据异常类型定义多个枚举,然后实现BaseError,示例通用异常:

package com.cch.error;

/**
 * @Auther: cch
 * @Date: 2020/9/21 16:07
 * @Description: 默认异常
 */
public enum DefaultError implements BaseError {

    SYSTEM_INTERNAL_ERROR("0000", "系统内部错误"),
    PARAMETER_ERROR("0001","参数错误");

    String errorCode;
    String errorMessage;
    private static final String ns = "DFT";

    DefaultError(String errorCode, String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    @Override
    public String getErrorCode() {
        return ns + "." + errorCode;
    }

    @Override
    public String getErrorMessage() {
        return errorMessage;
    }
}

注:下一篇link请求加密验签。

你可能感兴趣的:(java,后端)