人之所以痛苦,那是因为你在成长。--------magic_guo
由于第一次实际搭建这些模块,深深体会到“小伙子,这里面水很深,你把握不住啊!”这句话的含义;其中出现了很多bug,但最后还是一一解决,文章后面会把遇到的问题都写是哪个,以供参考;
搭建shop-user模块:
基础模块搭建好以后,后面的模块搭建,千篇一律,模式一样,不同的是各个模块所需要的功能和依赖不同;
总结搭建思路:创建一个spring initializr模块,选择好Group和Artifact后,选择依赖;整理pom文件(选择父pom,清理不必要的依赖以及添加所需依赖),编写mapper、service、serviceImpl和controller层;编写yml文件(改名字为bootstrap.yml,在config配置一份,在yml直接拉取即可);启动类加注解,启动此模块并验证端口,访问接口是否正常;
shop-user模块搭建细节:
在微服务项目构建之处,就要将一些代码与模块,该抽离的抽离,该剥茧剥茧,这样有助于以后项目的维护,而且代码清晰易懂;
由于user模块是一个web模块,后面会有很多类似的业务模块,因此将所有的实体类抽离出来,放入一个maven工程中来管理;这样在启动或者将来部署的时候以jar包的形式引入即可;
构建shop-entity模块:
此模块是一个maven工程(不要建成spring工程),创建好以后整理pom文件:
所需依赖:mybatis-plus(实体类要使用mybatis-plus的注解)、lombok(实体类要使用lombok的注解)
此外要注意的是,只添加lombom依赖是不行的,lombok需要在idea安装插件才能使用;
shop-entitty的pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.guo</groupId>
<artifactId>shop-pom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.guo</groupId>
<artifactId>shop-entity</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
创建数据库,创建数据表:
编写实体类:
package com.guo.entity;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@TableName("t_user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private String username;
private String password;
private Integer age;
private Integer sex;
private String email;
private String phone;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
}
还有一个实体类,是ResultEntity类,前后端分离的项目中,后端只返回数据给前端,但是数据多而复杂,因此统一成功只返回一种响应信息对于前后端来说都是一个很好的选择;此类包括的内容:响应的状态,信息,以及返回的数据(返回的数据使用一个泛型来接受):
此类应该在编写shop-user的controller层时描述更合适,为了将此模块的东西讲完,所以就在这里记录下来了;
package com.guo.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author magic_guo
* @version 1.0
* @date 2021/7/18 14:00
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultEntity<T> {
private static final String SUCCESS = "success";
private static final String ERROR = "error";
// 返回消息
private String msg;
// 返回状态
private String status;
// 返回数据
private T data;
// 只返回成的状态
public static <T> ResultEntity<T> success() {
return new ResultEntity(SUCCESS, null,null);
}
public static <T> ResultEntity<T> success(T t) {
return new ResultEntity<>(SUCCESS, null, t);
}
public static <T> ResultEntity<T> error(String msg) {
return new ResultEntity(ERROR, msg, null);
}
public static ResultEntity responseClient(boolean flag) {
if (flag) {
return ResultEntity.success();
}else {
return ResultEntity.error("添加用户失败!");
}
}
}
user模块:
所需依赖:config的客户端、eureka的客户端、mybatis-plus、spring web、mysql的依赖、实体类模块
pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.guo</groupId>
<artifactId>shop-pom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.guo</groupId>
<artifactId>shop-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shop-user</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.guo</groupId>
<artifactId>shop-entity</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
mapper层接口:
继承mybatis-puls的BaseMapper接口,接收一个实体类User
package com.guo.mapper;
/**
* @author magic_guo
* @version 1.0
* @date 2021/7/18 13:48
*/
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.guo.entity.User;
import org.apache.ibatis.annotations.Mapper;
public interface UserMapper extends BaseMapper<User> {
}
service层接口:
继承mybatis的IService接口,接收一个User实体类
package com.guo.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.guo.entity.User;
import org.apache.ibatis.annotations.Mapper;
/**
* @author magic_guo
* @version 1.0
* @date 2021/7/18 13:48
*/
public interface UserMapper extends BaseMapper<User> {
}
serviceImpl实现类层:
先继承mybatis-plus的ServiceImpl接口(接收一个mapper和实体类User),实现service层接口,然后添加@Service注解
package com.guo.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.guo.entity.User;
import com.guo.mapper.UserMapper;
import com.guo.service.IUserService;
import org.springframework.stereotype.Service;
/**
* @author magic_guo
* @version 1.0
* @date 2021/7/18 13:52
*/
@Service
public class IUserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
controller层:
类上添加@RequestMapping注解、@RestController注解和@Slf4j注解
类内注入接口:@Autowired(注入的service接口层,具体调用时会去找此接口的实现类,如果是实现类不唯一,则会报错;可以将实现类调用排上先后顺序)
接口:添加@RequestMapping注解
注意:
1、@RestController是@Controller和@ResponseBody的结合体,两个标注合并起来的作用
2、如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是Return 里的内容
3、如果需要返回到指定页面,则需要用 @Controller配合视图解析器InternalResourceViewResolver才行
4、如果需要返回JSON,XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注解
package com.guo.controller;
import com.guo.entity.ResultEntity;
import com.guo.entity.User;
import com.guo.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author magic_guo
* @version 1.0
* @date 2021/7/18 13:46
*/
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
IUserService userService;
@RequestMapping("/addUser")
public ResultEntity addUser(User user) {
return ResultEntity.responseClient(userService.insert(user));
}
}
编写yml:
将yml配置一份在config模块中,启动时去shop-config中拉取:
application-shop-user.yml:
server:
port: 8001
spring:
application:
name: shop-user
此模块需要连接数据库,以后别的业务模块也需配置数据库,因此将数据源配置抽离出来:
datasources.yml:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/2008-shop-copy
driver-class-name: com.mysql.jdbc.Driver
本地的bootstrap.yml:
拉取shop-user的配置、数据源配置、eureka客户端配置
spring:
cloud:
config:
uri: http://localhost:9999
profile: shop-user, eureka-client, datasource
name: application
启动类:
开启spring的包扫描、开启mybatis的mapper扫描,添加eureka客户端注解
package com.guo.user;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication(scanBasePackages = "com.guo")
@MapperScan("com.guo.mapper")
@EnableEurekaClient
public class ShopUserApplication {
public static void main(String[] args) {
SpringApplication.run(ShopUserApplication.class, args);
}
}
启动shop-user启动类,查看端口是否是配置端口;如果修改了相关模块的内容,相关模块也要重新启动一下;
查看eureka注册中心是否注册了user模块:
访问接口:
查看数据库:
遇到的问题:
1、创建模块的时候,包结构没有定义好,以至于在启动类上添加包扫描和mapper扫描出现了:controller层注入的问题(spring容器将UserService和UserServiceImpl都当做Servcie注入类);
2、lombok插件未安装,一直导致lombok的注解不能使用;
本文章教学视频来自:https://www.bilibili.com/video/BV1tb4y1Q74E?p=3&t=125
静下心,慢慢来,会很快!