Springboot 实现api接口(一)

Springboot 实现api接口(一)

一、序言

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

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

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

二、返回格式

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

类注解 @RestControllerjson

@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接口,会显得咱们的编码风格十分统一,代码更加紧凑,不至于看起来零散。api

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

三、接收参数/参数验证

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

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

@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;
}

四、异常统一处理

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

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;
    }
}

注:下一篇请求加密验签和接口文档使用。

相关文章
相关标签/搜索