06-实现用户微服务
6-1 搭建微服务
引入依赖
<!-- 引入 Web 功能 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Eureka 客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- 引入 Feign, 可以以声明的方式调用微服务 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- 引入服务容错 Hystrix 的依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!-- Java Persistence API, ORM 规范 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL 驱动, 注意, 这个需要与 MySQL 版本对应 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.19</version> <scope>runtime</scope> </dependency> <!-- 通用模块 --> <dependency> <groupId>com.tuyrk</groupId> <artifactId>homepage-common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
启动类注解
@EnableJpaAuditing @EnableFeignClients @EnableCircuitBreaker @EnableEurekaClient @SpringBootApplication
项目配置
server: port: 7000 servlet: context-path: /homepage-user spring: application: name: eureka-client-homepage-user main: allow-bean-definition-overriding: true jpa: show-sql: true hibernate: ddl-auto: none properties: hibernate.format_sql: true open-in-view: false datasource: url: jdbc:mysql://127.0.0.1:3306/imooc_356?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver tomcat: max-active: 4 min-idle: 2 initial-size: 2 eureka: client: service-url: defaultZone: http://server1:8000/eureka/ feign: hystrix: enabled: true
6-2 数据表实体类及Dao接口的定义
用户信息表homepage_user映射实体表
@Data @NoArgsConstructor @AllArgsConstructor @Entity @EntityListeners(AuditingEntityListener.class) @Table(name = "homepage_user") public class HomepageUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; // 用户名 @Column(name = "username", nullable = false) private String username; // 用户邮箱 @Column(name = "email", nullable = false) private String email; // 创建时间 @Column(name = "create_time", nullable = false) @CreatedDate private Date createTime; // 更新时间 @Column(name = "update_time", nullable = false) @LastModifiedDate private Date updateTime; public HomepageUser(String username, String email) { this.username = username; this.email = email; } public static HomepageUser invalid() { HomepageUser homepageUser = new HomepageUser("", ""); homepageUser.setId(-1L); return homepageUser; } }
用户课程表homepage_user_course映射实体表
@Data @NoArgsConstructor @AllArgsConstructor @Entity @EntityListeners(AuditingEntityListener.class) @Table(name = "homepage_user_course") public class HomepageUserCourse { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id; // 用户id @Column(name = "user_id", nullable = false) private Long userId; // 课程id @Column(name = "course_id", nullable = false) private Long courseId; // 创建时间 @Column(name = "create_time", nullable = false) @CreatedDate private Date createTime; // 更新时间 @Column(name = "update_time", nullable = false) @LastModifiedDate private Date updateTime; }
HomepageUser数据表访问接口
public interface HomepageUserDao extends JpaRepository<HomepageUser, Long> { // 通过用户名寻找用户记录 HomepageUser findByUsername(String username); }
HomepageUserCourse数据表访问接口
public interface HomepageUserCourseDao extends JpaRepository<HomepageUserCourse, Long> { // 通过用户id寻找数据记录 List<HomepageUserCourse> findAllByUserId(Long userId); }
6-3 Feign 接口及值对象的定义
通过Feign访问课程微服务
@FeignClient(value = "eureka-client-homepage-course", fallback = CourseClientHystrix.class) public interface CourseClient { // 通过id获取课程信息 @GetMapping("/homepage-course/get/course") CourseInfo getCourseInfo(Long id); // 通过ids获取课程信息 @PostMapping("/homepage-course/get/courses") List<CourseInfo> getCourseInfos(CourseInfosRequest request); }
熔断降级策略
@Component public class CourseClientHystrix implements CourseClient { @Override public CourseInfo getCourseInfo(Long id) { return CourseInfo.invalid(); } @Override public List<CourseInfo> getCourseInfos(CourseInfosRequest request) { return Collections.emptyList(); } }
创建用户请求对象
@Data @NoArgsConstructor @AllArgsConstructor public class CreateUserRequest { private String username; private String email; // 请求有效性验证 public boolean validate() { return StringUtils.isNotBlank(username) && StringUtils.isNotBlank(email); } }
用户课程对象
@Data @NoArgsConstructor @AllArgsConstructor public class UserCourseInfo { private UserInfo userInfo; private List<CourseInfo> courseInfos; public static UserCourseInfo invalid() { return new UserCourseInfo(new UserInfo(), Collections.emptyList()); } }
6-4 微服务功能实现
用户相关服务接口
public interface IUserService { // 创建用户 UserInfo createUser(CreateUserRequest request); // 根据ID获取用户信息 UserInfo getUserInfo(Long id); // 获取用户和课程信息 UserCourseInfo getUserCourseInfo(Long id); }
用户相关实现
@Slf4j @Service public class UserServiceImpl implements IUserService { @Autowired private HomepageUserDao homepageUserDao; @Autowired private HomepageUserCourseDao homepageUserCourseDao; @Autowired private CourseClient courseClient; // 创建用户 @Override public UserInfo createUser(CreateUserRequest request) { if (!request.validate()) { return UserInfo.invalid(); } HomepageUser oldUser = homepageUserDao.findByUsername(request.getUsername()); if (!Objects.isNull(oldUser)) { return UserInfo.invalid(); } HomepageUser newUser = homepageUserDao.save(new HomepageUser(request.getUsername(), request.getEmail())); return new UserInfo(newUser.getId(), newUser.getUsername(), newUser.getEmail()); } // 根据ID获取用户信息 @Override public UserInfo getUserInfo(Long id) { Optional<HomepageUser> user = homepageUserDao.findById(id); HomepageUser curUser = user.orElse(HomepageUser.invalid()); return new UserInfo(curUser.getId(), curUser.getUsername(), curUser.getEmail()); } // 获取用户和课程信息 @Override public UserCourseInfo getUserCourseInfo(Long id) { Optional<HomepageUser> user = homepageUserDao.findById(id); HomepageUser curUser = user.orElse(null); if (Objects.isNull(curUser)) { return UserCourseInfo.invalid(); } UserInfo userInfo = new UserInfo(curUser.getId(), curUser.getUsername(), curUser.getEmail()); List<HomepageUserCourse> userCourses = homepageUserCourseDao.findAllByUserId(curUser.getId()); if (CollectionUtils.isEmpty(userCourses)) { return new UserCourseInfo(userInfo, Collections.emptyList()); } List<Long> courseIds = userCourses.stream().map(HomepageUserCourse::getCourseId).collect(Collectors.toList()); List<CourseInfo> courseInfos = courseClient.getCourseInfos(new CourseInfosRequest(courseIds)); return new UserCourseInfo(userInfo, courseInfos); } }
用户服务对外接口
@Slf4j @RestController public class HomepageUserController { @Autowired private IUserService userService; @PostMapping("/create/user") public UserInfo createUser(@RequestBody CreateUserRequest request) { log.info("<homepage-user>: create user -> {}", JSON.toJSONString(request)); return userService.createUser(request); } @GetMapping("/get/user") public UserInfo getUserInfo(Long id) { log.info("<homepage-user>: get user -> {}", id); return userService.getUserInfo(id); } @GetMapping("/get/user/course") public UserCourseInfo getUserCourseInfo(Long id) { log.info("<homepage-user>: get user course -> {}", id); return userService.getUserCourseInfo(id); } }
6-5 功能接口测试用例的实现
创建用户
@Test @Transactional void createUser() { CreateUserRequest request = new CreateUserRequest("tuyrk", "tuyrk@qq.com"); UserInfo user = userService.createUser(request); assertEquals("tuyrk", user.getUsername()); }
获取用户信息
@Test void getUserInfo() { UserInfo userInfo = userService.getUserInfo(1L); assertEquals("tuyrk", userInfo.getUsername()); }
创建用户课程对应关系
@Test @Transactional void findAllByUserId() { HomepageUserCourse userCourse1 = new HomepageUserCourse(); userCourse1.setUserId(1L); userCourse1.setCourseId(1L); HomepageUserCourse userCourse2 = new HomepageUserCourse(); userCourse2.setUserId(1L); userCourse2.setCourseId(2L); java.util.List<HomepageUserCourse> userCourses = homepageUserCourseDao.saveAll(List.of(userCourse1, userCourse2)); assertEquals(2, userCourses.size()); }
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 tuyrk@qq.com
文章标题:06-实现用户微服务
文章字数:1.4k
本文作者:神秘的小岛岛
发布时间:2020-04-27, 23:13:33
最后更新:2020-04-29, 00:07:38
原始链接:https://www.tuyrk.cn/imooc/356-springcloud/06-user-server/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。