API模块

trip_modules-api父模块下创建子模块trip-users-api,pom文件内容如下:

pom.xml
<?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.swx</groupId>
<artifactId>trip-modules-api</artifactId>
<version>1.0.0</version>
</parent>

<artifactId>trip-users-api</artifactId>

<dependencies>
<dependency>
<groupId>com.swx</groupId>
<artifactId>trip-common-core</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<scope>provided</scope> <!-- 只在编译和测试生效,运行时不生效,阻止依赖的传递性 -->
</dependency>
<!-- Redis模块 -->
<dependency>
<groupId>com.swx</groupId>
<artifactId>trip-common-redis</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

创建数据库实体类:UserInfo,首先创建com.swx.user.domain包,在该包下创建实体类。

UserInfo
@Getter
@Setter
@TableName("userinfo")
public class UserInfo {
public static final int GENDER_SECRET = 0; // 保密
public static final int GENDER_MALE = 1; // 男
public static final int GENDER_FEMALE = 2; // 女
public static final int STATE_NORMAL = 0; // 正常
public static final int STATE_DISABLE = 1; // 冻结

@TableId(type = IdType.AUTO)
private Long id;

private String nickname; // 昵称
private String phone; // 手机
private String email; // 邮箱
private String password; // 密码
private Integer gender = GENDER_SECRET; // 性别
private Integer level = 0; // 用户级别
private String city; // 所在城市
private String headImgUrl; // 头像
private String info; // 个性签名
private Integer state = STATE_NORMAL; // 状态
}

微服务模块

API模块不需要启动类,在运行时不需要Mybatis Plus的依赖,但是开发时使用到了注解,所需使用scope限制只在编译和测试依赖,并且阻止依赖的传递性。而Server需要运行时依赖,所以不使用scope。

api和server都引入了依赖,但是使用scope限制api中依赖的传递。这样的好处是,当service不需要api中的依赖时,能避免因为引入依赖而没有配置导致项目启动失败。

trip_modules父模块下创建子模块trip-users-server,pom文件内容如下:

pom.xml
<?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.swx</groupId>
<artifactId>trip_modules</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>trip-users-server</artifactId>

<dependencies>
<dependency>
<groupId>com.swx</groupId>
<artifactId>trip-users-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Nacos注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
</project>

配置文件:bootstrap.yaml,内容如下:

spring:
application:
name: user-service
cloud:
nacos:
server-addr: xxx.xxx.xxx.xxx:8848
config:
file-extension: yaml
namespace: trip_cloud_dev
profiles:
active: dev

Nacos配置文件

  • ID:user-service-dev.yaml

  • Group:DEFAULT_GROUP

  • 描述:用户微服务配置

  • 配置内容:

    user-service-dev.yaml
    server:
    port: 8091
    spring:
    cloud:
    nacos:
    server-addr: xxx.xxx.xxx.xxx:8848
    discovery:
    namespace: ${spring.cloud.nacos.config.namespace}
    datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///trip-user?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
    username: root
    password: xxxxxx

配置网关路由

  • ID:trip-gateway-dev.yaml

  • Group:DEFAULT_GROUP

  • 描述:旅游项目网关配置

  • 配置内容:

    trip-gateway-dev.yaml
    - id: trip_user
    uri: lb://user-service
    predicates:
    # 路径匹配, 前缀匹配方式, 只要以 /product-serv/ 开头的请求, 都会被转发到 uri 上去
    - Path=/u/**
    # 过滤器, 执行真正的转发之前, 要执行哪些过滤器
    filters:
    # StripPrefix: 跳过前缀的过滤器, 此处配置为 1 则表示在转发请求前, 自动将第一个前缀删除
    # 例如: 请求地址为 /product-serv/products/1, 此时将前缀删除后, 会变成 /products/1
    - StripPrefix=1

创建启动类:TripUsersApplication,首先创建com.swx.user包,在该包下创建。

TripUsersApplication
@SpringBootApplication
@MapperScan("com.swx.user.mapper")
public class TripUsersApplication {
public static void main(String[] args) {
SpringApplication.run(TripUsersApplication.class, args);
}
}

创建 UserInfoMapper,首先创建com.swx.user.mapper包,在该包下创建。

继承Mybatis Plus的BaseMapper

UserInfoMapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}

创建 UserInfoService,首先创建com.swx.user.service包,在该包下创建。

继承Mybatis Plus的IService

UserInfoService
public interface UserInfoService extends IService<UserInfo> {
}

实现 UserInfoService,首先创建com.swx.user.service.impl包,在该包下创建。

继承Mybatis Plus的ServiceImpl,同时实现自己的UserInfoService

UserServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
}

创建 UserInfoController,,首先创建com.swx.user.controller包,在该包下创建。

注意:这里使用了构造器注入方式,因为对象是 final,可以有效避免下面这种情况

userInfoService = null;
UserInfoController
@RestController
@RequestMapping("/user")
public class UserInfoController {

private final UserInfoService userInfoService;

public UserInfoController(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}

@GetMapping("/test")
public List<UserInfo> test(){
return userInfoService.list();
}
}

Redis Key

用户模块下的Redis Key 应该遵循设计规范,因此创建类: UserRedisKeyPrefix,继承 BaseKeyPrefix

在模块trip-users-api中创建包:com.swx.user.redis.key,在该包下创建类:UserRedisKeyPrefix

UserRedisKeyPrefix
public class UserRedisKeyPrefix extends BaseKeyPrefix {

public static final UserRedisKeyPrefix USER_REGISTER_VERIFY_CODE_STRING =
new UserRedisKeyPrefix("USERS:REGISTER:VERIFY_CODE:", 10L, TimeUnit.MINUTES);

public UserRedisKeyPrefix(String prefix) {
super(prefix);
}

public UserRedisKeyPrefix(String prefix, Long timeout, TimeUnit unit) {
super(prefix, timeout, unit);
}
}