前言:在SpringCloud微服务项目中,我们经常需要跨模块调用接口方法来实现相应的业务逻辑,所以会经常有一些公共重复性的代码,比如接受其他模块接口返回的对象类、接口返回格式封装类、一些工具类以及一些调用第三方接口的实现类等等。
当项目下的子模块越来越多,代码重复的次数也会越来越多,如果每次新增一个子模块又要进行重复代码编写的话,会使得项目越来越冗余,这是我们最不想看到的。为了使这些代码更好的进行管理和复用,我们可以单独构建一个子模块,用来存放这些公共代码。当某个模块需要调用时,只需要用maven工具将该公共模块进行打包,然后在需要调用模块的pom.xml文件中引入该公共模块的依赖即可。
一。示例项目说明:
1.初始项目结构
- springcloud_demo:项目名称
- eureka-server:服务注册与发现子模块
- provider:服务提供子模块
- consumer:服务消费子模块
2.项目场景
consumer服务消费子模块业务逻辑中需要获取所有用户的信息,但是用户接口模块是provider服务提供子模块来进行操作的,所以consumer需要调用provider的接口方法,来拿到所有用户的信息。
二。项目实现
1.provider服务提供端
Controller层
/**
* @Description:服务端控制器
* @Author :zks
* @Date :16:07 2020/8/27
*/
@RequestMapping("provider")
@RestController
public class ProviderController {
@Autowired
private IUserService userService;
/**
* 得到全部用户信息
* @return
*/
@GetMapping("getUserList")
public Result getUser(){
List<User> users=userService.getUserList();
return Result.success(users);
}
}
Service层
/**
* @Description:用户Service
* @Author :zks
* @Date :14:24 2020/9/10
*/
public interface IUserService {
/**
* 得到所有用户信息
* @return
*/
List<User> getUserList();
}
/**
* @Description:用户Service实现
* @Author :zks
* @Date :14:26 2020/9/10
*/
@Service
public class IUserServiceImpl implements IUserService {
@Override
public List<User> getUserList() {
List<User> users=new ArrayList<>();
//这里模拟从数据库获取数据
User userOne=new User();
userOne.setId(1);
userOne.setUserName("张三");
userOne.setPassword("123456");
User userTwo=new User();
userTwo.setId(2);
userTwo.setUserName("李四");
userTwo.setPassword("654321");
users.add(userOne);
users.add(userTwo);
return users;
}
}
Domain层
/**
* @Description:用户实体类
* @Author :zks
* @Date :13:43 2020/9/10
*/
public class User {
private int id;
private String userName;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}
}
util接口返回封装工具类
/**
* @Description:后台接口返回json格式封装类
* @Author :zks
* @Date :11:58 2020/9/8
*/
public class Result<T> implements Serializable {
//状态码
private Integer status;
//状态
private String message;
//返回封装数据
private T data;
public Result() {
}
public Result(Integer status) {
this.status = status;
}
public Result(Integer status, String message) {
this.status = status;
this.message = message;
}
public Result(Integer status, String message, T data) {
this.status = status;
this.message = message;
this.data = data;
}
//不返回数据构造方法
public Result(CodeEnum codeEnum) {
this.status = codeEnum.getCode();
this.message = codeEnum.getMessage();
}
//返回数据构造方法
public Result(CodeEnum codeEnum, T data) {
this(codeEnum);
this.data = data;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
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;
}
//请求成功(不返回数据)
public static <T> Result <T> success(){
return new Result <T>(CodeEnum.SUCCESS);
}
//请求成功(返回数据)
public static <T> Result <T> success(T data){
return new Result <T>(CodeEnum.SUCCESS,data);
}
//参数格式不正确
public static <T> Result <T> badRequest(){
return new Result <T>(CodeEnum.BAD_REQUEST);
}
// .......可根据自己的需要往下延伸
@Override
public String toString() {
return "Result{" +
"status=" + status +
", message='" + message + '\'' +
", data=" + data +
'}';
}
}
/**
* @Description:状态码枚举类
* @Author :zks
* @Date :14:00 2020/9/8
*/
public enum CodeEnum {
/**
* 成功
*/
SUCCESS(200, "ok"),
/**
* 参数不齐全或参数错误
*/
BAD_REQUEST(400,"参数不正确");
private Integer code;
private String message;
CodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
构建完成项目结构图如下:
2.consumer服务消费端
Controller层
/**
* @Description:消费端控制器
* @Author :zks
* @Date :16:18 2020/8/27
*/
@RequestMapping("consumer")
@RestController
public class ConsumerController {
@Autowired
private ConsumerService consumerService;
@RequestMapping("getUserList")
public Result getUserList(){
return consumerService.getUserList();
}
}
Service层
/**
* @Description:使用@FeignClient注解调用注册子模块接口方法
* @Author :zks
* @Date :16:31 2020/8/27
*/
//注册子模块名称
@FeignClient(value = "service-provider")
public interface ConsumerService {
/**
* 跨模块调用得到用户信息列表
* @return
*/
@GetMapping("provider/getUserList")
public Result getUserList();
}
Domain层
、util接口返回封装工具类
与provider消费端一致。
构建完成项目结构图如下:
项目总结构图如下:
因为侧重点不同,这里没有详细写到项目创建过程,如果对该项目创建有疑惑,可以去看我的另外一篇博文:使用Idea构建SpringCloud项目(图文详解+简单易懂)里面有详细的步骤。
3.项目运行
依次启动eureka-server、provider和consumer:
用postman测试成功:
4.总结
由上述实现代码我们可以发现,Domain层
和util接口返回封装工具类
其实都是两个模块所共用,且代码一致,那我们为何不把它拿出来防在一个公共模块来进行调用呢?
三。模块重构
1.新建一个子模块common-api
重构后项目结构如下:
2.放入公共代码
3.用maven工具打包发布
先clean再install:
打包完成:
4.引入该公共模块依赖
删除consumer
和provider
中的公共代码:
打开common-api
的pom.xml文件,找到打包依赖:
分别复制到consumer
和provider
的pom.xml文件中:
导入公共模块中的类:
5.项目运行
运行项目使用postman进行测试,成功拿到接口数据:
该Springcloud微服务中多模块重复代码重构成公共模块demo已上传,有需要的小伙伴可以自行下载:springcloud_demo