上期我们完成了Spring boot 项目的搭建,本期我们实现一个简单的接口服务。
一 、创建接口服务
无论是Spring MVC还是Restful风格的接口服务,
spring-boot-starter-web中都包含其注解@RestController或@Controller
注意:由于
spring-boot-starter-web默认替我们引入了核心启动器spring-boot-starter,因此,当 Spring Boot 项目中的pom.xml引入了spring-boot-starter-web的依赖后,就无须在引入spring-boot-starter核心启动器的依赖了
- 首先,在
pom.xml文件中引入spring-boot-starter-web:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.6</version>
<scope>compile</scope>
</dependency>
- 创建DTO对象
创建接口传输对象UserDto,代码如下:
package com.holmium.springboot.app.dto;
/**
* @author holmium
* @description: 用户对象
* @date 2023年04月15日
*/
public class UserDto {
/**
* 用户ID
*/
String userId;
/**
* 用户名
*/
String userName;
/**
* 性别
*/
String sex;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
- 创建接口类
UserApi
UserApi对外提供Restful风格的接口服务
package com.holmium.springboot.app.api;
import com.holmium.springboot.app.dto.UserDto;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author holmium
* @description:
* @date 2023年04月14日11:50
*/
@RestController
public class UserApi {
@GetMapping(value = "/userinfo")
public UserDto gerUserInfo() {
UserDto user = new UserDto();
user.setUserId("888888");
user.setUserName("holmium");
user.setSex("1");
return user;
}
}
- 测试接口
启动接口服务,通过接口测试工具对接口进行访问,结果如下:
二、返回统一格式结果优化
从上述接口返回结果可以看到,接口返回的数据使我们自己定义的对象,所以每个接口返回的结果格式都不尽相同,这样给接口使用者带来一定困扰,我们可不可以对定义一个统一格式的返回结果?答案是肯定。
- 首先,我们创建统一返回结果对象Result类
package com.holmium.springboot.common.resp;
/**
* @author holmium
* @description 统一的返回结果
* @date 2023年04月15日15:11
*/
public class Result<T>{
/**
* 请求响应代码,如:001-成功,000-失败
*/
private String code;
/**
* 请求返回信息描述或异常信息
*/
private String message;
/**
*接口请求返回业务对象数据
*/
private T data;
public Result() {
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
- 第二步,我们对UserApi返回结果进行改造
package com.holmium.springboot.app.api;
import com.holmium.springboot.app.dto.UserDto;
import com.holmium.springboot.app.resp.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author holmium
* @description:
* @date 2023年04月15日23:50
*/
@RestController
public class UserApi {
@GetMapping(value = "/userinfo")
public Result<UserDto> gerUserInfo() {
//接口返回数据对象
UserDto user = new UserDto();
user.setUserId("888888");
user.setUserName("holmium");
user.setSex("1");
//接口统一返回结果
Result<UserDto> result = new Result<>();
result.setData(user);
result.setCode("001");
result.setMessage("接口调用成功");
return result;
}
}
- 调整后返回结果如下:
三、接口异常异常统一封装
实际业务开发中,在系统运行中常常会抛出各种异常,这些异常,如果不对异常进行封装的话, 异常将会注解抛给接口调用方,程序显得极不友好,并且对于有些我们没有预料到的异常,就会直接抛给用户。
-
举例:未做任何处理的异常
- 进行异常模拟改造
增加User处理的类,在类中增加方法getUser(),直接抛出异常:
package com.holmium.springboot.domain.user.impl;
import com.holmium.springboot.common.dto.UserDto;
import com.holmium.springboot.domain.user.User;
import org.springframework.stereotype.Service;
/**
* @author holmium
* @date 2023年04月16日 0:14
*/
@Service
public class UserImpl implements User {
@Override
public UserDto getUser() throws Exception {
throw new Exception("接口调用异常");
}
}
- 在接口类中调用上述方法
package com.holmium.springboot.app.api;
import com.holmium.springboot.app.vo.UserVo;
import com.holmium.springboot.common.enums.CodeEnum;
import com.holmium.springboot.common.resp.Result;
import com.holmium.springboot.domain.user.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author holmium
* @description:
* @date 2023年04月15日23:50
*/
@RestController
public class UserApi {
@Resource
User user;
@GetMapping(value = "/userinfo")
public Result<UserVo> gerUserInfo(@RequestParam("id") Long id) {
//接口统一返回结果
Result<UserVo> result = new Result<>();
if(id==1) {
//TODO:
}else{
try {
user.getUser();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return result;
}
}
- 测试服务
从返回结果和后台服务日志来看测试结果
图 测试结果 图后台日志
从测试结果发现,接口返回信息不准确,也极不友好,跟正常返回格式不同,对于接口调用方来说,增加了处理难度。
- 对异常进行统一封装处理
对异常进行捕捉,增加统一返回结果封装。
package com.holmium.springboot.app.api;
import com.holmium.springboot.app.vo.UserVo;
import com.holmium.springboot.common.enums.CodeEnum;
import com.holmium.springboot.common.resp.Result;
import com.holmium.springboot.domain.user.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author holmium
* @description:
* @date 2023年04月15日23:50
*/
@RestController
public class UserApi {
@Resource
User user;
@GetMapping(value = "/userinfo")
public Result<UserVo> gerUserInfo(@RequestParam("id") Long id) {
//接口统一返回结果
Result<UserVo> result = new Result<>();
if(id==1) {
//TODO:
}else{
try {
user.getUser();
} catch (Exception e) {
result.setCode(CodeEnum.FAIL.getCode());
result.setMessage(e.getMessage());
}
}
return result;
}
}
- 改造后测试
经过统一封装后,返回结果同正常请求结果返回格式相同,调用方调用接口更加友好更加友好
四、引入lombok,简化对象写法
在实际工作中,我们要写大量的各种对象,这些对象属性都有
get和set方法,手写起来非常麻烦,是否有什么方法可以简化对象的编写,不用写get和set方法?引入lombok插件,即可解决这个问题
在pom文件中引入Lombok的jar包
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
在对象类中添加@Data注解
在类上添加
@Data注解后,不用在编写get和set方法,在引用这个类对象的时候,可以直接调用get和set方法,和之前一模一样,这大大简化的对象属性编写,尤其当对象属性比较多的时候,这种编写更加明显
@Data //增加@Data注解,简化get和set方法
public class UserVo {
/**
* 用户ID
*/
String userId;
/**
* 用户名
*/
String userName;
/**
* 性别:1-男 0-女
*/
String sex;
}
五、写在最后
上述接口虽然进行统一结果返回封装,但是我们发现接口层添加了大量的代码,且每一个接口都有大量的冗余代码,能否对接口层进行进一步简化,对公共部门进行统一处理呢? 下期我们将对接口统一返回和异常统一返回进行封装。