├── .gitignore
├── .idea
├── .gitignore
├── compiler.xml
├── encodings.xml
├── jarRepositories.xml
├── libraries
│ └── mybatis_generator_for_imooc_1_0_SNAPSHOT.xml
├── misc.xml
└── uiDesigner.xml
├── README.md
├── book-api
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── imooc
│ │ ├── Application.java
│ │ ├── config
│ │ ├── InterceptorConfig.java
│ │ ├── MinIOConfig.java
│ │ └── knife4jConfig.java
│ │ ├── controller
│ │ ├── BaseController.java
│ │ ├── BaseInfoProperties.java
│ │ ├── CommentController.java
│ │ ├── FansController.java
│ │ ├── FileController.java
│ │ ├── MsgController.java
│ │ ├── PassportController.java
│ │ ├── RabbitMQConsumer.java
│ │ ├── UserInfoController.java
│ │ └── VlogController.java
│ │ └── intercepter
│ │ ├── PassportInterceptor.java
│ │ └── UserTokenInterceptor.java
│ └── resources
│ ├── application-dev.yml
│ ├── application-prod.yml
│ ├── application.yml
│ ├── banner
│ ├── banner.txt
│ ├── cat.png
│ └── qiaoba.txt
│ └── bootstrap.yml
├── book-common
├── pom.xml
└── src
│ └── main
│ ├── java
│ ├── com
│ │ └── imooc
│ │ │ ├── enums
│ │ │ ├── FileTypeEnum.java
│ │ │ ├── MessageEnum.java
│ │ │ ├── Sex.java
│ │ │ ├── UserInfoModifyType.java
│ │ │ └── YesOrNo.java
│ │ │ ├── exceptions
│ │ │ ├── GraceException.java
│ │ │ ├── GraceExceptionHandler.java
│ │ │ └── MyCustomException.java
│ │ │ ├── grace
│ │ │ └── result
│ │ │ │ ├── GraceJSONResult.java
│ │ │ │ ├── IMOOCJSONResult.java
│ │ │ │ └── ResponseStatusEnum.java
│ │ │ └── utils
│ │ │ ├── DateUtil.java
│ │ │ ├── DesensitizationUtil.java
│ │ │ ├── IPUtil.java
│ │ │ ├── JsonUtils.java
│ │ │ ├── MinIOUtils.java
│ │ │ ├── MyInfo.java
│ │ │ ├── PagedGridResult.java
│ │ │ ├── RedisOperator.java
│ │ │ ├── SMSUtils.java
│ │ │ └── TencentCloudProperties.java
│ └── org
│ │ └── n3r
│ │ └── idworker
│ │ ├── Code.java
│ │ ├── DayCode.java
│ │ ├── Id.java
│ │ ├── IdWorker.java
│ │ ├── InvalidSystemClock.java
│ │ ├── RandomCodeStrategy.java
│ │ ├── Sid.java
│ │ ├── Test.java
│ │ ├── WorkerIdStrategy.java
│ │ ├── strategy
│ │ ├── DayPrefixRandomCodeStrategy.java
│ │ ├── DefaultRandomCodeStrategy.java
│ │ ├── DefaultWorkerIdStrategy.java
│ │ └── FileLock.java
│ │ └── utils
│ │ ├── HttpReq.java
│ │ ├── IPv4Utils.java
│ │ ├── Ip.java
│ │ ├── Props.java
│ │ ├── Serializes.java
│ │ └── Utils.java
│ └── resources
│ └── tencentcloud.properties
├── book-mapper
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── imooc
│ │ ├── mapper
│ │ ├── CommentMapper.java
│ │ ├── CommentMapperCustom.java
│ │ ├── FansMapper.java
│ │ ├── FansMapperCustom.java
│ │ ├── MyLikedVlogMapper.java
│ │ ├── UsersMapper.java
│ │ ├── VlogMapper.java
│ │ └── VlogMapperCustom.java
│ │ ├── my
│ │ └── mapper
│ │ │ └── MyMapper.java
│ │ └── repository
│ │ └── MessageRepository.java
│ └── resources
│ └── mapper
│ ├── CommentMapper.xml
│ ├── CommentMapperCustom.xml
│ ├── FansMapper.xml
│ ├── FansMapperCustom.xml
│ ├── MyLikedVlogMapper.xml
│ ├── UsersMapper.xml
│ ├── VlogMapper.xml
│ └── VlogMapperCustom.xml
├── book-model
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── imooc
│ ├── bo
│ ├── CommentBO.java
│ ├── RegistLoginBO.java
│ ├── UpdatedUserBO.java
│ └── VlogBO.java
│ ├── mo
│ └── MessageMO.java
│ ├── pojo
│ ├── Comment.java
│ ├── Fans.java
│ ├── MyLikedVlog.java
│ ├── Users.java
│ └── Vlog.java
│ └── vo
│ ├── CommentVO.java
│ ├── FansVO.java
│ ├── IndexVlogVO.java
│ ├── UsersVO.java
│ └── VlogerVO.java
├── book-service
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── imooc
│ ├── base
│ ├── BaseInfoProperties.java
│ └── RabbitMQConfig.java
│ └── service
│ ├── CommentService.java
│ ├── FansService.java
│ ├── MsgService.java
│ ├── UserService.java
│ ├── VlogService.java
│ └── impl
│ ├── CommentServiceImpl.java
│ ├── FansServiceImpl.java
│ ├── MsgServiceImpl.java
│ ├── UserServiceImpl.java
│ └── VlogServiceImpl.java
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # 项目排除路径
2 | /book-api/target/
3 | /book-common/target/
4 | /book-mapper/target/
5 | /book-model/target/
6 | /book-service/target/
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # 默认忽略的文件
2 | /shelf/
3 | /workspace.xml
4 | # 基于编辑器的 HTTP 客户端请求
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
31 |
32 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/libraries/mybatis_generator_for_imooc_1_0_SNAPSHOT.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Haut短视频
2 | ## Haut短视频是一个短视频类的App,拥有用户业务模块,短视频模块,粉丝业务模块,评论业务模块,消息业务模块,并且完整上线运行
3 | SpringBoot+Uniapp仿抖音短视频App
4 | 需要前端uinapp可以私信
5 |
6 | 只用修改api模块下面的配置即可运行
7 |
8 | Knife4j 接口文档通过访问 http://ip+prot/doc.html#/home 查看api
9 | # 架构
10 | 
11 | 
12 |
13 | # 效果
14 |
15 | 
16 | 
17 | 
18 | 
19 |
--------------------------------------------------------------------------------
/book-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.imooc
8 | imooc-red-book-dev
9 | 1.0-SNAPSHOT
10 |
11 |
12 | jar
13 |
14 |
15 | book-api
16 |
17 |
18 | 8
19 | 8
20 | UTF-8
21 |
22 |
23 |
24 |
25 |
26 |
27 | com.alibaba.cloud
28 | spring-cloud-starter-alibaba-nacos-discovery
29 |
30 |
31 |
32 |
33 | com.alibaba.cloud
34 | spring-cloud-starter-alibaba-nacos-config
35 |
36 |
37 |
38 |
39 | org.springframework.cloud
40 | spring-cloud-starter-bootstrap
41 |
42 |
43 |
44 |
45 | com.imooc
46 | book-service
47 | 1.0-SNAPSHOT
48 |
49 |
50 | com.github.xiaoymin
51 | knife4j-spring-boot-starter
52 |
53 |
54 | com.github.xiaoymin
55 | knife4j-springdoc-ui
56 |
57 |
58 |
59 |
60 | ${project.artifactId}
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-maven-plugin
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/Application.java:
--------------------------------------------------------------------------------
1 | package com.imooc;
2 |
3 |
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.context.annotation.ComponentScan;
7 | import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
8 | import tk.mybatis.spring.annotation.MapperScan;
9 |
10 | /**
11 | * @author vercen
12 | * @version 1.0
13 | * @date 2023/5/20 14:25
14 | */
15 | @SpringBootApplication
16 | @MapperScan(basePackages = {"com.imooc.mapper"})
17 | @ComponentScan(basePackages = {"com.imooc","org.n3r.idworker"})
18 | @EnableMongoRepositories
19 | public class Application {
20 | public static void main(String[] args) {
21 | SpringApplication.run(Application.class, args);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/config/InterceptorConfig.java:
--------------------------------------------------------------------------------
1 | package com.imooc.config;
2 |
3 | import com.imooc.intercepter.PassportInterceptor;
4 | import com.imooc.intercepter.UserTokenInterceptor;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
9 |
10 | @Configuration
11 | public class InterceptorConfig implements WebMvcConfigurer {
12 |
13 | @Bean
14 | public PassportInterceptor passportInterceptor() {
15 | return new PassportInterceptor();
16 | }
17 |
18 | @Bean
19 | public UserTokenInterceptor userTokenInterceptor() {
20 | return new UserTokenInterceptor();
21 | }
22 |
23 | @Override
24 | public void addInterceptors(InterceptorRegistry registry) {
25 | registry.addInterceptor(passportInterceptor())
26 | .addPathPatterns("/passport/getSMSCode");
27 |
28 | registry.addInterceptor(userTokenInterceptor())
29 | .addPathPatterns("/userInfo/modifyUserInfo")
30 | .addPathPatterns("/userInfo/modifyImage");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/config/MinIOConfig.java:
--------------------------------------------------------------------------------
1 | package com.imooc.config;
2 |
3 | import com.imooc.utils.MinIOUtils;
4 | import lombok.Data;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | @Configuration
10 | @Data
11 | public class MinIOConfig {
12 |
13 | @Value("${minio.endpoint}")
14 | private String endpoint;
15 | @Value("${minio.fileHost}")
16 | private String fileHost;
17 | @Value("${minio.bucketName}")
18 | private String bucketName;
19 | @Value("${minio.accessKey}")
20 | private String accessKey;
21 | @Value("${minio.secretKey}")
22 | private String secretKey;
23 |
24 | @Value("${minio.imgSize}")
25 | private Integer imgSize;
26 | @Value("${minio.fileSize}")
27 | private Integer fileSize;
28 |
29 | @Bean
30 | public MinIOUtils creatMinioClient() {
31 | return new MinIOUtils(endpoint, bucketName, accessKey, secretKey, imgSize, fileSize);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/config/knife4jConfig.java:
--------------------------------------------------------------------------------
1 | package com.imooc.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import springfox.documentation.builders.ApiInfoBuilder;
6 | import springfox.documentation.builders.PathSelectors;
7 | import springfox.documentation.builders.RequestHandlerSelectors;
8 | import springfox.documentation.service.Contact;
9 | import springfox.documentation.spi.DocumentationType;
10 | import springfox.documentation.spring.web.plugins.Docket;
11 | import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
12 |
13 | /**
14 | * @author vercen
15 | * @version 1.0
16 | * @date 2023/5/20 19:55
17 | */
18 | @Configuration
19 | @EnableSwagger2WebMvc
20 | public class knife4jConfig {
21 | @Bean
22 | public Docket defaultApi2() {
23 | Docket docket=new Docket(DocumentationType.SWAGGER_2)
24 | .apiInfo(new ApiInfoBuilder()
25 | //.title("swagger-bootstrap-ui-demo RESTful APIs")
26 | .description("短视频实战接口文档")
27 | .termsOfServiceUrl("http://www.xx.com/")
28 | .contact(new Contact("lee", "http://www.imooc.com/", "abc@imooc.com"))
29 | .version("1.0")
30 | .build())
31 | //分组名称
32 | .groupName("2.X版本")
33 | .select()
34 | //这里指定Controller扫描包路径
35 | .apis(RequestHandlerSelectors.basePackage("com.imooc.controller"))
36 | .paths(PathSelectors.any())
37 | .build();
38 | return docket;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/BaseController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.utils.RedisOperator;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 |
6 | //public class BaseController {
7 | //
8 | // @Autowired
9 | // public RedisOperator redis;
10 | //
11 | // public static final String MOBILE_SMSCODE = "mobile:smscode";
12 | // public static final String REDIS_USER_TOKEN = "redis_user_token";
13 | // public static final String REDIS_USER_INFO = "redis_user_info";
14 | //
15 | //}
16 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/BaseInfoProperties.java:
--------------------------------------------------------------------------------
1 | //package com.imooc.controller;
2 | //
3 | //import com.github.pagehelper.PageInfo;
4 | //import com.imooc.utils.RedisOperator;
5 | //import org.springframework.beans.factory.annotation.Autowired;
6 | //import org.springframework.validation.BindingResult;
7 | //import org.springframework.validation.FieldError;
8 | //
9 | //import java.util.HashMap;
10 | //import java.util.List;
11 | //import java.util.Map;
12 | //
13 | //public class BaseInfoProperties {
14 | //
15 | // @Autowired
16 | // public RedisOperator redis;
17 | //
18 | // public static final Integer COMMON_START_PAGE = 1;
19 | // public static final Integer COMMON_PAGE_SIZE = 10;
20 | //
21 | // public static final String MOBILE_SMSCODE = "mobile:smscode";
22 | // public static final String REDIS_USER_TOKEN = "redis_user_token";
23 | // public static final String REDIS_USER_INFO = "redis_user_info";
24 | //
25 | //
26 | // //我的关注总数
27 | // public static final String REDIS_MY_FOLLOWS_COUNTS = "redis_my_follows_counts";
28 | // // 我的粉丝总数
29 | // public static final String REDIS_MY_FANS_COUNTS = "redis_my_fans_counts";
30 | //
31 | // // 视频和发布者获赞数
32 | // public static final String REDIS_VLOG_BE_LIKED_COUNTS = "redis_vlog_be_liked_counts";
33 | // public static final String REDIS_VLOGER_BE_LIKED_COUNTS = "redis_vloger_be_liked_counts";
34 | //
35 | // public PagedGridResult setterPagedGrid(List> list,
36 | // Integer page) {
37 | // PageInfo> pageList = new PageInfo<>(list);
38 | // PagedGridResult gridResult = new PagedGridResult();
39 | // gridResult.setRows(list);
40 | // gridResult.setPage(page);
41 | // gridResult.setRecords(pageList.getTotal());
42 | // gridResult.setTotal(pageList.getPages());
43 | // return gridResult;
44 | // }
45 | //
46 | //}
47 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/CommentController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.bo.CommentBO;
5 | import com.imooc.enums.MessageEnum;
6 | import com.imooc.grace.result.GraceJSONResult;
7 | import com.imooc.pojo.Comment;
8 | import com.imooc.pojo.Vlog;
9 | import com.imooc.service.CommentService;
10 | import com.imooc.service.MsgService;
11 | import com.imooc.service.VlogService;
12 | import com.imooc.vo.CommentVO;
13 | import io.swagger.annotations.Api;
14 | import lombok.extern.slf4j.Slf4j;
15 | import org.apache.commons.lang3.StringUtils;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.web.bind.annotation.*;
18 |
19 | import javax.validation.Valid;
20 | import java.util.HashMap;
21 | import java.util.Map;
22 |
23 | @Slf4j
24 | @Api(tags = "CommentController 评论模块的接口")
25 | @RequestMapping("comment")
26 | @RestController
27 | public class CommentController extends BaseInfoProperties {
28 |
29 | @Autowired
30 | private CommentService commentService;
31 | @Autowired
32 | private MsgService msgService;
33 | @Autowired
34 | private VlogService vlogService;
35 | //
36 | @PostMapping("create")
37 | public GraceJSONResult create(@RequestBody @Valid CommentBO commentBO)
38 | throws Exception {
39 |
40 | CommentVO commentVO = commentService.createComment(commentBO);
41 | return GraceJSONResult.ok(commentVO);
42 | }
43 | //
44 | @GetMapping("counts")
45 | public GraceJSONResult counts(@RequestParam String vlogId) {
46 |
47 | String countsStr = redis.get(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId);
48 | if (StringUtils.isBlank(countsStr)) {
49 | countsStr = "0";
50 | }
51 |
52 | return GraceJSONResult.ok(Integer.valueOf(countsStr));
53 | }
54 |
55 | @GetMapping("list")
56 | public GraceJSONResult list(@RequestParam String vlogId,
57 | @RequestParam(defaultValue = "") String userId,
58 | @RequestParam Integer page,
59 | @RequestParam Integer pageSize) {
60 |
61 | return GraceJSONResult.ok(
62 | commentService.queryVlogComments(
63 | vlogId,
64 | userId,
65 | page,
66 | pageSize));
67 | }
68 |
69 | @DeleteMapping("delete")
70 | public GraceJSONResult delete(@RequestParam String commentUserId,
71 | @RequestParam String commentId,
72 | @RequestParam String vlogId) {
73 | commentService.deleteComment(commentUserId,
74 | commentId,
75 | vlogId);
76 | return GraceJSONResult.ok();
77 | }
78 |
79 | @PostMapping("like")
80 | public GraceJSONResult like(@RequestParam String commentId,
81 | @RequestParam String userId) {
82 |
83 | // 故意犯错,bigkey
84 | redis.incrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
85 | redis.setHashValue(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId, "1");
86 | // redis.hset(REDIS_USER_LIKE_COMMENT, userId, "1");
87 |
88 |
89 | // 系统消息:点赞评论
90 | Comment comment = commentService.getComment(commentId);
91 | Vlog vlog = vlogService.getVlog(comment.getVlogId());
92 | Map msgContent = new HashMap();
93 | msgContent.put("vlogId", vlog.getId());
94 | msgContent.put("vlogCover", vlog.getCover());
95 | msgContent.put("commentId", commentId);
96 | msgService.createMsg(userId,
97 | comment.getCommentUserId(),
98 | MessageEnum.LIKE_COMMENT.type,
99 | msgContent);
100 |
101 |
102 | return GraceJSONResult.ok();
103 | }
104 |
105 | @PostMapping("unlike")
106 | public GraceJSONResult unlike(@RequestParam String commentId,
107 | @RequestParam String userId) {
108 |
109 | redis.decrementHash(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId, 1);
110 | redis.hdel(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
111 |
112 | return GraceJSONResult.ok();
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/FansController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.grace.result.GraceJSONResult;
5 | import com.imooc.grace.result.ResponseStatusEnum;
6 | import com.imooc.pojo.Users;
7 | import com.imooc.service.FansService;
8 | import com.imooc.service.UserService;
9 | import io.swagger.annotations.Api;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.apache.commons.lang3.StringUtils;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.web.bind.annotation.*;
14 |
15 | @Slf4j
16 | @Api(tags = "FansController 粉丝相关业务功能的接口")
17 | @RequestMapping("fans")
18 | @RestController
19 | public class FansController extends BaseInfoProperties {
20 |
21 | @Autowired
22 | private UserService userService;
23 | @Autowired
24 | private FansService fansService;
25 |
26 | @PostMapping("follow")
27 | public GraceJSONResult follow(@RequestParam String myId,
28 | @RequestParam String vlogerId) {
29 |
30 | // 判断两个id不能为空
31 | if (StringUtils.isBlank(myId) || StringUtils.isBlank(vlogerId)) {
32 | return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_ERROR);
33 | }
34 |
35 | // 判断当前用户,自己不能关注自己
36 | if (myId.equalsIgnoreCase(vlogerId)) {
37 | return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_RESPONSE_NO_INFO);
38 | }
39 |
40 | // 判断两个id对应的用户是否存在
41 | Users vloger = userService.getUser(vlogerId);
42 | Users myInfo = userService.getUser(myId);
43 |
44 | // fixme: 两个用户id的数据库查询后的判断,是分开好?还是合并判断好?
45 | if (myInfo == null || vloger == null) {
46 | return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_RESPONSE_NO_INFO);
47 | }
48 | //
49 | // 保存粉丝关系到数据库
50 | fansService.doFollow(myId, vlogerId);
51 |
52 | // 博主的粉丝+1,我的关注+1
53 | redis.increment(REDIS_MY_FOLLOWS_COUNTS + ":" + myId, 1);
54 | redis.increment(REDIS_MY_FANS_COUNTS + ":" + vlogerId, 1);
55 |
56 | // 我和博主的关联关系,依赖redis,不要存储数据库,避免db的性能瓶颈
57 | redis.set(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + myId + ":" + vlogerId, "1");
58 | //
59 | return GraceJSONResult.ok();
60 | }
61 |
62 | @PostMapping("cancel")
63 | public GraceJSONResult cancel(@RequestParam String myId,
64 | @RequestParam String vlogerId) {
65 |
66 | // 删除业务的执行
67 | fansService.doCancel(myId, vlogerId);
68 |
69 | // 博主的粉丝-1,我的关注-1
70 | redis.decrement(REDIS_MY_FOLLOWS_COUNTS + ":" + myId, 1);
71 | redis.decrement(REDIS_MY_FANS_COUNTS + ":" + vlogerId, 1);
72 |
73 | // 我和博主的关联关系,依赖redis,不要存储数据库,避免db的性能瓶颈
74 | redis.del(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + myId + ":" + vlogerId);
75 |
76 | return GraceJSONResult.ok();
77 | }
78 |
79 | @GetMapping("queryDoIFollowVloger")
80 | public GraceJSONResult queryDoIFollowVloger(@RequestParam String myId,
81 | @RequestParam String vlogerId) {
82 | return GraceJSONResult.ok(fansService.queryDoIFollowVloger(myId, vlogerId));
83 | }
84 |
85 | @GetMapping("queryMyFollows")
86 | public GraceJSONResult queryMyFollows(@RequestParam String myId,
87 | @RequestParam Integer page,
88 | @RequestParam Integer pageSize) {
89 | return GraceJSONResult.ok(
90 | fansService.queryMyFollows(
91 | myId,
92 | page,
93 | pageSize));
94 | }
95 |
96 | @GetMapping("queryMyFans")
97 | public GraceJSONResult queryMyFans(@RequestParam String myId,
98 | @RequestParam Integer page,
99 | @RequestParam Integer pageSize) {
100 | return GraceJSONResult.ok(
101 | fansService.queryMyFans(
102 | myId,
103 | page,
104 | pageSize));
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/FileController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 |
4 | import com.imooc.config.MinIOConfig;
5 | import com.imooc.grace.result.GraceJSONResult;
6 | import com.imooc.utils.MinIOUtils;
7 | import com.imooc.utils.SMSUtils;
8 | import io.swagger.annotations.Api;
9 | import io.swagger.annotations.ApiOperation;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.web.bind.annotation.GetMapping;
13 | import org.springframework.web.bind.annotation.PostMapping;
14 | import org.springframework.web.bind.annotation.RestController;
15 | import org.springframework.web.multipart.MultipartFile;
16 |
17 | @Slf4j
18 | @Api(tags = "FileController 文件上传测试的接口")
19 | @RestController
20 | public class FileController {
21 |
22 | @Autowired
23 | private MinIOConfig minIOConfig;
24 |
25 | @PostMapping("upload")
26 | public GraceJSONResult upload(MultipartFile file) throws Exception {
27 |
28 | String fileName = file.getOriginalFilename();
29 |
30 | MinIOUtils.uploadFile(minIOConfig.getBucketName(),
31 | fileName,
32 | file.getInputStream());
33 |
34 | String imgUrl = minIOConfig.getFileHost()
35 | + "/"
36 | + minIOConfig.getBucketName()
37 | + "/"
38 | + fileName;
39 |
40 | return GraceJSONResult.ok(imgUrl);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/MsgController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.grace.result.GraceJSONResult;
5 | import com.imooc.mo.MessageMO;
6 | import com.imooc.service.MsgService;
7 | import io.swagger.annotations.Api;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RequestParam;
13 | import org.springframework.web.bind.annotation.RestController;
14 |
15 | import java.util.List;
16 |
17 | @Slf4j
18 | @Api(tags = "MsgController 消息功能模块的接口")
19 | @RequestMapping("msg")
20 | @RestController
21 | public class MsgController extends BaseInfoProperties {
22 |
23 | @Autowired
24 | private MsgService msgService;
25 |
26 | @GetMapping("list")
27 | public GraceJSONResult list(@RequestParam String userId,
28 | @RequestParam Integer page,
29 | @RequestParam Integer pageSize) {
30 |
31 | // mongodb 从0分页,区别于数据库
32 | if (page == null) {
33 | page = COMMON_START_PAGE_ZERO;
34 | }
35 | if (pageSize == null) {
36 | pageSize = COMMON_PAGE_SIZE;
37 | }
38 |
39 | List list = msgService.queryList(userId, page, pageSize);
40 |
41 | return GraceJSONResult.ok(list);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/PassportController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.bo.RegistLoginBO;
5 | import com.imooc.grace.result.GraceJSONResult;
6 | import com.imooc.grace.result.ResponseStatusEnum;
7 | import com.imooc.pojo.Users;
8 | import com.imooc.service.UserService;
9 | import com.imooc.utils.IPUtil;
10 | import com.imooc.utils.SMSUtils;
11 | import com.imooc.vo.UsersVO;
12 | import io.swagger.annotations.Api;
13 | import lombok.extern.slf4j.Slf4j;
14 | import org.apache.commons.lang3.StringUtils;
15 | import org.springframework.beans.BeanUtils;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.web.bind.annotation.*;
18 |
19 | import javax.servlet.http.HttpServletRequest;
20 | import javax.validation.Valid;
21 | import java.util.UUID;
22 |
23 | /**
24 | * @author vercen
25 | * @version 1.0
26 | * @date 2023/5/25 10:47
27 | */
28 | @Slf4j
29 | @RestController
30 | @RequestMapping("passport")
31 | @Api(tags = "通行证,验证码登录注册")
32 | public class PassportController extends BaseInfoProperties {
33 | @Autowired
34 | SMSUtils smsUtils;
35 | @Autowired
36 | UserService userService;
37 | @PostMapping("getSMSCode")
38 | public Object getSMSCode(@RequestParam String mobile, HttpServletRequest request) throws Exception {
39 | if (StringUtils.isBlank(mobile)){
40 | return GraceJSONResult.ok();
41 | }
42 |
43 | //TODO 获得用户ip 限制时间60s只能1次
44 | String userIp=IPUtil.getRequestIp(request);
45 |
46 | redis.setnx60s(MOBILE_SMSCODE+":"+userIp, userIp);
47 | String code=(int)((Math.random()*9+1)*100000)+"";
48 |
49 | smsUtils.sendSMS(mobile,code);
50 |
51 | log.info(code);
52 | redis.set(MOBILE_SMSCODE+":"+mobile, code,30*60);
53 | //TODO 验证码放入redis
54 | return GraceJSONResult.ok();
55 | }
56 |
57 | @PostMapping("login")
58 | public Object login(@Valid @RequestBody RegistLoginBO registLoginBO){
59 |
60 | String rediscode = redis.get(MOBILE_SMSCODE + ":" + registLoginBO.getMobile());
61 |
62 | if (StringUtils.isBlank(rediscode)|| !rediscode.equalsIgnoreCase(registLoginBO.getSmsCode())){
63 | System.out.println("rediscode"+rediscode);
64 | System.out.println("registLoginBO.getMobile()"+registLoginBO.getSmsCode());
65 | return GraceJSONResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
66 | }
67 |
68 | Users user = userService.queryMobileIsExist(registLoginBO.getMobile());
69 | if (user==null){
70 | user = userService.createUser(registLoginBO.getMobile());
71 | }
72 | String uToken = UUID.randomUUID().toString();
73 | redis.set(REDIS_USER_TOKEN+":"+user.getId(),uToken);
74 |
75 | //清除验证码
76 | redis.del(MOBILE_SMSCODE+":"+user.getMobile());
77 |
78 | //返回给前端
79 | UsersVO usersVO = new UsersVO();
80 | BeanUtils.copyProperties(user, usersVO);
81 | usersVO.setUserToken(uToken);
82 |
83 | return GraceJSONResult.ok(usersVO);
84 |
85 | }
86 |
87 | @PostMapping("logout")
88 | public Object logout(@RequestParam String userId){
89 |
90 | redis.del(REDIS_USER_TOKEN+":"+userId);
91 |
92 | return GraceJSONResult.ok();
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/RabbitMQConsumer.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.RabbitMQConfig;
4 | import com.imooc.enums.MessageEnum;
5 | import com.imooc.exceptions.GraceException;
6 | import com.imooc.grace.result.ResponseStatusEnum;
7 | import com.imooc.mo.MessageMO;
8 | import com.imooc.service.MsgService;
9 | import com.imooc.utils.JsonUtils;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.springframework.amqp.core.Message;
12 | import org.springframework.amqp.rabbit.annotation.RabbitListener;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Slf4j
17 | @Component
18 | public class RabbitMQConsumer {
19 |
20 | @Autowired
21 | private MsgService msgService;
22 |
23 | @RabbitListener(queues = {RabbitMQConfig.QUEUE_SYS_MSG})
24 | public void watchQueue(String payload, Message message) {
25 | log.info(payload);
26 |
27 | MessageMO messageMO = JsonUtils.jsonToPojo(payload, MessageMO.class);
28 |
29 | String routingKey = message.getMessageProperties().getReceivedRoutingKey();
30 | log.info(routingKey);
31 |
32 | // TODO: 下面这段代码可以优化,一个地方是参数优化,另外是枚举的判断优化
33 |
34 | if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.FOLLOW_YOU.enValue)) {
35 | msgService.createMsg(messageMO.getFromUserId(),
36 | messageMO.getToUserId(),
37 | MessageEnum.FOLLOW_YOU.type,
38 | null);
39 | } else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.LIKE_VLOG.enValue)) {
40 | msgService.createMsg(messageMO.getFromUserId(),
41 | messageMO.getToUserId(),
42 | MessageEnum.FOLLOW_YOU.type,
43 | messageMO.getMsgContent());
44 | } else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.COMMENT_VLOG.enValue)) {
45 | msgService.createMsg(messageMO.getFromUserId(),
46 | messageMO.getToUserId(),
47 | MessageEnum.COMMENT_VLOG.type,
48 | messageMO.getMsgContent());
49 | } else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.REPLY_YOU.enValue)) {
50 | msgService.createMsg(messageMO.getFromUserId(),
51 | messageMO.getToUserId(),
52 | MessageEnum.REPLY_YOU.type,
53 | messageMO.getMsgContent());
54 | } else if (routingKey.equalsIgnoreCase("sys.msg." + MessageEnum.LIKE_COMMENT.enValue)) {
55 | msgService.createMsg(messageMO.getFromUserId(),
56 | messageMO.getToUserId(),
57 | MessageEnum.LIKE_COMMENT.type,
58 | messageMO.getMsgContent());
59 | } else {
60 | GraceException.display(ResponseStatusEnum.SYSTEM_OPERATION_ERROR);
61 | }
62 |
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/controller/UserInfoController.java:
--------------------------------------------------------------------------------
1 | package com.imooc.controller;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.bo.UpdatedUserBO;
5 | import com.imooc.config.MinIOConfig;
6 | import com.imooc.enums.FileTypeEnum;
7 | import com.imooc.enums.UserInfoModifyType;
8 | import com.imooc.grace.result.GraceJSONResult;
9 | import com.imooc.grace.result.ResponseStatusEnum;
10 | import com.imooc.pojo.Users;
11 | import com.imooc.service.UserService;
12 | import com.imooc.utils.MinIOUtils;
13 | import com.imooc.utils.SMSUtils;
14 | import com.imooc.vo.UsersVO;
15 | import io.swagger.annotations.Api;
16 | import io.swagger.annotations.ApiOperation;
17 | import lombok.extern.slf4j.Slf4j;
18 | import org.apache.commons.lang3.StringUtils;
19 | import org.springframework.beans.BeanUtils;
20 | import org.springframework.beans.factory.annotation.Autowired;
21 | import org.springframework.stereotype.Controller;
22 | import org.springframework.web.bind.annotation.*;
23 | import org.springframework.web.multipart.MultipartFile;
24 |
25 | /**
26 | * @author vercen
27 | * @version 1.0
28 | * @date 2023/5/20 14:32
29 | */
30 | @RestController
31 | @Slf4j
32 | @Api(tags = "UserInfoController用户信息接口模块")
33 | @RequestMapping("userInfo")
34 | public class UserInfoController extends BaseInfoProperties {
35 |
36 | @Autowired
37 | UserService userService;
38 |
39 | // @ResponseBody
40 | @ApiOperation(value = "根据userId返回个人信息")
41 | @GetMapping("query")
42 | public Object query(@RequestParam String userId){
43 | Users user = userService.getUser(userId);
44 |
45 | UsersVO usersVO = new UsersVO();
46 | BeanUtils.copyProperties(user, usersVO);
47 |
48 |
49 | // 我的关注博主总数量
50 | String myFollowsCountsStr = redis.get(REDIS_MY_FOLLOWS_COUNTS + ":" + userId);
51 | // 我的粉丝总数
52 | String myFansCountsStr = redis.get(REDIS_MY_FANS_COUNTS + ":" + userId);
53 | // 用户获赞总数,视频博主(点赞/喜欢)总和
54 | // String likedVlogCountsStr = redis.get(REDIS_VLOG_BE_LIKED_COUNTS + ":" + userId);
55 | String likedVlogerCountsStr = redis.get(REDIS_VLOGER_BE_LIKED_COUNTS + ":" + userId);
56 |
57 | Integer myFollowsCounts = 0;
58 | Integer myFansCounts = 0;
59 | Integer likedVlogCounts = 0;
60 | Integer likedVlogerCounts = 0;
61 | Integer totalLikeMeCounts = 0;
62 |
63 |
64 | if (StringUtils.isNotBlank(myFollowsCountsStr)) {
65 | myFollowsCounts = Integer.valueOf(myFollowsCountsStr);
66 | }
67 | if (StringUtils.isNotBlank(myFansCountsStr)) {
68 | myFansCounts = Integer.valueOf(myFansCountsStr);
69 | }
70 | // if (StringUtils.isNotBlank(likedVlogCountsStr)) {
71 | // likedVlogCounts = Integer.valueOf(likedVlogCountsStr);
72 | // }
73 | if (StringUtils.isNotBlank(likedVlogerCountsStr)) {
74 | likedVlogerCounts = Integer.valueOf(likedVlogerCountsStr);
75 | }
76 | totalLikeMeCounts = likedVlogCounts + likedVlogerCounts;
77 |
78 | usersVO.setMyFollowsCounts(myFollowsCounts);
79 | usersVO.setMyFansCounts(myFansCounts);
80 | usersVO.setTotalLikeMeCounts(totalLikeMeCounts);
81 |
82 | //usersVO.setMyFansCounts((Integer) myFansCounts);
83 |
84 | return GraceJSONResult.ok(usersVO);
85 | }
86 |
87 | @PostMapping("modifyUserInfo")
88 | public GraceJSONResult modifyUserInfo(@RequestBody UpdatedUserBO updatedUserBO, @RequestParam Integer type) throws Exception {
89 |
90 | UserInfoModifyType.checkUserInfoTypeIsRight(type);
91 | Users newUserInfo = userService.updateUserInfo(updatedUserBO, type);
92 | return GraceJSONResult.ok(newUserInfo);
93 | }
94 |
95 | @Autowired
96 | private MinIOConfig minIOConfig;
97 |
98 | @PostMapping("modifyImage")
99 | public GraceJSONResult modifyImage(@RequestParam String userId,
100 | @RequestParam Integer type,
101 | MultipartFile file) throws Exception {
102 |
103 | if (type != FileTypeEnum.BGIMG.type && type != FileTypeEnum.FACE.type) {
104 | return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_UPLOAD_FAILD);
105 | }
106 |
107 | String fileName = file.getOriginalFilename();
108 |
109 | MinIOUtils.uploadFile(minIOConfig.getBucketName(),
110 | fileName,
111 | file.getInputStream());
112 |
113 | String imgUrl = minIOConfig.getFileHost()
114 | + "/"
115 | + minIOConfig.getBucketName()
116 | + "/"
117 | + fileName;
118 |
119 |
120 | // 修改图片地址到数据库
121 | UpdatedUserBO updatedUserBO = new UpdatedUserBO();
122 | updatedUserBO.setId(userId);
123 |
124 | if (type == FileTypeEnum.BGIMG.type) {
125 | updatedUserBO.setBgImg(imgUrl);
126 | } else {
127 | updatedUserBO.setFace(imgUrl);
128 | }
129 | Users users = userService.updateUserInfo(updatedUserBO);
130 |
131 | return GraceJSONResult.ok(users);
132 | }
133 |
134 |
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/intercepter/PassportInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.imooc.intercepter;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.exceptions.GraceException;
5 | import com.imooc.grace.result.ResponseStatusEnum;
6 | import com.imooc.utils.IPUtil;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.web.servlet.HandlerInterceptor;
9 | import org.springframework.web.servlet.ModelAndView;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 | @Slf4j
15 | public class PassportInterceptor extends BaseInfoProperties implements HandlerInterceptor {
16 |
17 | @Override
18 | public boolean preHandle(HttpServletRequest request,
19 | HttpServletResponse response, Object handler) throws Exception {
20 |
21 | // 获得用户的ip
22 | String userIp = IPUtil.getRequestIp(request);
23 |
24 | // 得到是否存在的判断
25 | boolean keyIsExist = redis.keyIsExist(MOBILE_SMSCODE + ":" + userIp);
26 |
27 | if (keyIsExist) {
28 | GraceException.display(ResponseStatusEnum.SMS_NEED_WAIT_ERROR);
29 | log.info("短信发送频率太大!");
30 | return false;
31 | }
32 |
33 | /**
34 | * true: 请求放行
35 | * false: 请求拦截
36 | */
37 | return true;
38 | }
39 |
40 | @Override
41 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
42 | }
43 |
44 | @Override
45 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/book-api/src/main/java/com/imooc/intercepter/UserTokenInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.imooc.intercepter;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.exceptions.GraceException;
5 | import com.imooc.grace.result.ResponseStatusEnum;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.springframework.web.servlet.HandlerInterceptor;
9 | import org.springframework.web.servlet.ModelAndView;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 | @Slf4j
15 | public class UserTokenInterceptor extends BaseInfoProperties implements HandlerInterceptor {
16 |
17 | @Override
18 | public boolean preHandle(HttpServletRequest request,
19 | HttpServletResponse response, Object handler) throws Exception {
20 |
21 |
22 | // 从header中获得用户id和token
23 | String userId = request.getHeader("headerUserId");
24 | String userToken = request.getHeader("headerUserToken");
25 |
26 | // 判断header中用户id和token不能为空
27 | if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(userToken)) {
28 | String redisToken = redis.get(REDIS_USER_TOKEN + ":" + userId);
29 | if (StringUtils.isBlank(redisToken)) {
30 | GraceException.display(ResponseStatusEnum.UN_LOGIN);
31 | return false;
32 | } else {
33 | // 比较token是否一致,如果不一致,表示用户在别的手机端登录
34 | if (!redisToken.equalsIgnoreCase(userToken)) {
35 | GraceException.display(ResponseStatusEnum.TICKET_INVALID);
36 | return false;
37 | }
38 | }
39 | } else {
40 | GraceException.display(ResponseStatusEnum.UN_LOGIN);
41 | return false;
42 | }
43 |
44 | /**
45 | * true: 请求放行
46 | * false: 请求拦截
47 | */
48 | return true;
49 | }
50 |
51 | @Override
52 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
53 | }
54 |
55 | @Override
56 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/book-api/src/main/resources/application-dev.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: ${port:8099}
3 |
4 | spring:
5 | datasource: # 数据源的相关配置
6 | type: com.zaxxer.hikari.HikariDataSource # 数据源的类型,可以更改为其他的数据源配置,比如druid
7 | driver-class-name: com.mysql.jdbc.Driver # mysql/MariaDB 的数据库驱动类名称
8 | url: jdbc:mysql://192.168.1.7:3306/imooc-red-book-dev?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
9 | username: root
10 | password: root
11 | hikari:
12 | connection-timeout: 30000 # 等待连接池分配连接的最大时间(毫秒),超过这个时长还没有可用的连接,则会抛出SQLException
13 | minimum-idle: 5 # 最小连接数
14 | maximum-pool-size: 20 # 最大连接数
15 | auto-commit: true # 自动提交
16 | idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则会被释放(retired)
17 | pool-name: DataSourceHikariCP # 连接池的名字
18 | max-lifetime: 18000000 # 连接池的最大生命时长(毫秒),超时则会被释放(retired)
19 | connection-test-query: SELECT 1
20 | redis:
21 | host: 192.168.1.61
22 | port: 6379
23 | database: 0
24 | password: itzixi
25 | data:
26 | mongodb:
27 | uri: mongodb://root:root@192.168.1.202:27017
28 | database: imooc-red-book
29 | rabbitmq:
30 | host: 192.168.1.204
31 | port: 5672
32 | username: admin
33 | password: admin
34 | virtual-host: imooc-red-book
35 | # application:
36 | # name: imooc-red-book-nacos
37 | cloud:
38 | nacos:
39 | discovery:
40 | server-addr: 192.168.1.159:8848 # nacos 所在的地址
41 |
42 | #counts: 100
43 |
44 | # 打开监控
45 | management:
46 | endpoint:
47 | web:
48 | exposure:
49 | include: '*'
50 |
51 | # MinIO 配置
52 | minio:
53 | endpoint: http://192.168.1.61:9000 # MinIO服务地址
54 | fileHost: http://192.168.1.61:9000 # 文件地址host
55 | bucketName: imooc # 存储桶bucket名称
56 | accessKey: imooc # 用户名
57 | secretKey: imooc123456 # 密码
58 | imgSize: 1024 # 图片大小限制,单位:m
59 | fileSize: 1024 # 文件大小限制,单位:m
60 |
--------------------------------------------------------------------------------
/book-api/src/main/resources/application-prod.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | datasource: # 数据源的相关配置
6 | type: com.zaxxer.hikari.HikariDataSource # 数据源的类型,可以更改为其他的数据源配置,比如druid
7 | driver-class-name: com.mysql.jdbc.Driver # mysql/MariaDB 的数据库驱动类名称
8 | url: jdbc:mysql://10.206.0.11:3306/imooc-red-book?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
9 | username: root
10 | password: imooc
11 | hikari:
12 | connection-timeout: 30000 # 等待连接池分配连接的最大时间(毫秒),超过这个时长还没有可用的连接,则会抛出SQLException
13 | minimum-idle: 5 # 最小连接数
14 | maximum-pool-size: 20 # 最大连接数
15 | auto-commit: true # 自动提交
16 | idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则会被释放(retired)
17 | pool-name: DataSourceHikariCP # 连接池的名字
18 | max-lifetime: 18000000 # 连接池的最大生命时长(毫秒),超时则会被释放(retired)
19 | connection-test-query: SELECT 1
20 | redis:
21 | host: 10.206.0.11
22 | port: 6379
23 | database: 0
24 | password: imooc
25 | data:
26 | mongodb:
27 | uri: mongodb://root:root@10.206.0.11:27017
28 | database: imooc
29 | rabbitmq:
30 | host: 10.206.0.11
31 | port: 5672
32 | username: imooc
33 | password: imooc
34 | virtual-host: imooc
35 | # application:
36 | # name: imooc-red-book-nacos
37 | cloud:
38 | nacos:
39 | discovery:
40 | server-addr: 10.206.0.11:8848 # nacos 所在的地址
41 |
42 | # 打开监控
43 | management:
44 | endpoint:
45 | web:
46 | exposure:
47 | include: '*'
48 |
49 | # MinIO 配置
50 | minio:
51 | endpoint: http://175.27.252.166:9000 # MinIO服务地址
52 | fileHost: http://175.27.252.166:9000 # 文件地址host
53 | bucketName: imooc # 存储桶bucket名称
54 | accessKey: root # 用户名
55 | secretKey: 12345678 # 密码
56 | imgSize: 1024 # 图片大小限制,单位:m
57 | fileSize: 1024 # 文件大小限制,单位:m
--------------------------------------------------------------------------------
/book-api/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | # port: 8099
3 | tomcat:
4 | uri-encoding: UTF-8
5 | max-swallow-size: -1 # tomcat默认大小2M,超过2M的文件不会被捕获,需要调整此处大小为100MB或者-1即可
6 |
7 | spring:
8 | application:
9 | name: imooc-red-book-nacos
10 | profiles:
11 | active: prod
12 | banner:
13 | location: classpath:banner/banner.txt
14 | servlet:
15 | multipart:
16 | max-file-size: 2MB # 文件上传大小限制,设置最大值,不能超过该值,否则报错
17 | # max-file-size: 500KB # 文件上传大小限制,设置最大值,不能超过该值,否则报错
18 | max-request-size: 2MB # 文件最大请求限制,用于批量上传
19 | # max-request-size: 500KB
20 |
21 | # 整合mybatis
22 | mybatis:
23 | type-aliases-package: com.imooc.pojo # 所有pojo类所在的包路径
24 | mapper-locations: classpath:mapper/*.xml # mapper映射文件
25 |
26 | # 通用mapper工具的配置
27 | mapper:
28 | mappers: com.imooc.my.mapper.MyMapper # 配置MyMapper,包含了一些封装好的CRUD方法
29 | not-empty: false # 在进行数据库操作的时候,username != null 是否会追加 username != ''
30 | identity: MYSQL
31 |
32 | # 分页插件助手的配置
33 | pagehelper:
34 | helper-dialect: MYSQL
35 | support-methods-arguments: true
36 |
37 | # 日志级别
38 | logging:
39 | level:
40 | root: info
41 |
--------------------------------------------------------------------------------
/book-api/src/main/resources/banner/banner.txt:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////
2 | // _ooOoo_ //
3 | // o8888888o //
4 | // 88" . "88 //
5 | // (| ^_^ |) //
6 | // O\ = /O //
7 | // ____/`---'\____ //
8 | // .' \\| |// `. //
9 | // / \\||| : |||// \ //
10 | // / _||||| -:- |||||- \ //
11 | // | | \\\ - /// | | //
12 | // | \_| ''\---/'' | | //
13 | // \ .-\__ `-` ___/-. / //
14 | // ___`. .' /--.--\ `. . ___ //
15 | // ."" '< `.___\_<|>_/___.' >'"". //
16 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | //
17 | // \ \ `-. \_ __\ /__ _/ .-` / / //
18 | // ========`-.____`-.___\_____/___.-`____.-'======== //
19 | // `=---=' //
20 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
21 | // 佛祖保佑 永无BUG 永不修改 //
22 | ////////////////////////////////////////////////////////////////////
--------------------------------------------------------------------------------
/book-api/src/main/resources/banner/cat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercen/vlog/403328c43b2f00cbe65b152671015aeb51c4ac7f/book-api/src/main/resources/banner/cat.png
--------------------------------------------------------------------------------
/book-api/src/main/resources/banner/qiaoba.txt:
--------------------------------------------------------------------------------
1 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
2 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
3 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
4 | ttttttttttttttttttttttttttttttttjtttjttjjtjW#Li;;ijE#Ettttjttjjjtttttttttttttttttttttttttttttttttttt
5 | ttttttttttttttttttttttttttttjtttLGtWtttt#i;itttttttjti;tWtttjWtDEjtttttttttttttttttttttttttttttttttt
6 | tttttttttttttttttttttttttttjjjttfjLjWtEjjtjtjttttttjjtjttLWt;jEjjttttttttttttttttttttttttttttttttttt
7 | ttttttttttttttttttttttttttDf;tjt;jWjjfLtttttttttttttttttttLDjjjjEtjj#ELttttttttttttttttttttttttttttt
8 | tttttttttttttttttttttttt#DjGjfjtjjtjjfLttttttttttttttttttjL#jjjjtttjtfLGfjtttttttttttttttttttttttttt
9 | tttttttttttttttttttttttttjfLjGttWjjjjLLtttttttttttttttttttLEjjjjjtttjjjjDjtttttttttttttttttttttttttt
10 | tttttttttttttttttttttttttjjjjDttLjjjjLLttttttttttttttttttjLLjLjjjttijjjjLjtttttttttttttttttttttttttt
11 | tttttttttttttttttttttttttjjjjjtttjjjfLLtttttttWEttf jtttttLDjLjjjjttEjfjLttttttttttttttttttttttttttt
12 | ttttttttttttttttttttttttijjjjjtjDjjjjLLjttttjG GL :jttttLWjjjjttKjWjKjKttttttttttttttttttttttttttt
13 | ttttttttttttttttttttttttijjjWjGjfjLjjLLjttttt,. ftttjLGjjtttj;jjj#jKjtttttttttttttttttttttttttt
14 | ttttttttttttttttttttttttEj#ffjjjfjjjWfLfjtttttf KtttttfLL;jjffjjLjjjjjttttttttttttttttttttttttttt
15 | tttttttttttttttttttttttttjjtjjjjjfLj#fLftttttjf tttttLLL#fjfjjjfjKjfttjttttttttttttttttttttttttt
16 | tttttttttttttttttttttttttDjjjjjjLjGj#LLLttttjD . . .jtttLLLWGGffjjjGjtjtttttttttttttttttttttttttttt
17 | tttttttttttttttttttttttttj;jjjjGLLDt#LLLtjjtjK Ej jtttLLLWjKLLLjjjjWttttttttttttttttttttttttttttt
18 | tttttttttttttttttttttttttttjGLLLLLLWKGLLttjtEWL;;;fKKjtttfWEWDLfLLLGWttttttttttttttttttttttttttttttt
19 | ttttttttttttttttttttttttttttttttfLLLfLGLD,,;ttjtttttti;;#LGLLLL#jttttttttttttttttttttttttttttttttttt
20 | tttttttttttttttttttttttttttttttttD::.#G;;jtjjjtttttjjtjtti;W:,:Wtttttttttttttttttttttttttttttttttttt
21 | ttttttttttttttttttttttttttttttttt;EjW,jtjjjjttjjttjtjtjjjjtj,Lj;jttttttttttttttttttttttttttttttttttt
22 | tttttttttttttttttttttttttttttttttE;;tjjtjjjKLLLLLLLLLGKjtjtjLLiWjttttttttttttttttttttttttttttttttttt
23 | tttttttttttttttttttttttttttttttttf,tjjttWLLLfLLLLLLLLfLfLKjtLLLfjttttttttttttttttttttttttttttttttttt
24 | ttttttttttttttttttttttttttttttttj,jjttEfLLLLLLLLLLLLLLLLLLLELLLLLttttttttttttttttttttttttttttttttttt
25 | tttttttttttttttttttttttttttttttjittjtfLLLLLLLLfDEKDLfLfLfLfLLfLLLWtttttttttttttttttttttttttttttttttt
26 | tttttttttttttttttttttttttttttttttjjffLLLLEGfjjjfjjjjjjGjKLLLfLfLLftjtttttttttttttttttttttttttttttttt
27 | ttttttttttttttttttttttttttttttttjjjLLLLKfjj;j;;;;;;;;,;jfjWLLLfLfLtttttttttttttttttttttttttttttttttt
28 | ttttttttttttttttttttttttttttttttttKLLLKf;ifj;i;;;;;;;j.E;;fLLLLGLLtttttttttttttttttttttttttttttttttt
29 | tttttttttttttttttttttttttttttttjtjLLLEG,;DWKWi;;;;;;;WWKE;;LfLLLLGtttttttttttttttttttttttttttttttttt
30 | ttttttttttttttttttttttttttttttttWELLLLL;; WKKD;;;;;;jKKK.;;LLLLLWftttttttttttttttttttttttttttttttttt
31 | tttttttttttttttttttttttttttttttttffLLLL:;EWKW,,;Di,;;KWKf;;fLLLLLjtttttttttttttttttttttttttttttttttt
32 | tttttttttttttttttttttttttttttttttWLLLLLE;,E.;;;;;,;;;;tDi;#LLLLfDttttttttttttttttttttttttttttttttttt
33 | ttttttttttttttttttttttttttttttttttKLLLLL;;;;;;;;tK,L;;;;;;LLLLfLtttttttttttttttttttttttttttttttttttt
34 | tttttttttttttttttttttttttttttttttttjLLLLW,;;;;;EEED;;;;;;WLLLDtttttttttttttttttttttttttttttttttttttt
35 | ttttttttttttttttttttttttttttttttttttjtKEL,;;;;;EjjW;;;;;KtEGjjjttttttttttttttttttttttttttttttttttttt
36 | ttttttttttttttttttttttttttttttttttttjtttttW,,;;jttj,i;tWKffKfjtttttttttttttttttttttttttttttttttttttt
37 | tttttttttttttttttttttttttttttttttttttttttttttDLjttfGWtjti,;Kjttttttttttttttttttttttttttttttttttttttt
38 | tttttttttttttttttttttttttttttttttttttttttttttDjittfj;,;;D;;;;ttttttttttttttttttttttttttttttttttttttt
39 | ttttttttttttttttttttttttttttttttttttttttttttE;;EEjWi;DGKj,iEjtjttttttttttttttttttttttttttttttttttttt
40 | tttttttttttttttttttttttttttttttttttttttttttt;,;;WWt;;;Dtttfttttttttttttttttttttttttttttttttttttttttt
41 | ttttttttttttttttttttttttttttttttttttttttttt;t;;;;;;;;;;Gtttttttttttttttttttttttttttttttttttttttttttt
42 | ttttttttttttttttttttttttttttttttttttttttjj,K;;;;;;;;;;;;jttttttttttttttttttttttttttttttttttttttttttt
43 | tttttttttttttttttttttttttttttttttttttttjf;;j;;;;;;;;;;;;tttttttttttttttttttttttttttttttttttttttttttt
44 | tttttttttttttttttttttttttttttttttttttttftGKE;;,;,,;;;;;ijttttttttttttttttttttttttttttttttttttttttttt
45 | tttttttttttttttttttttttttttttttttttttttEfijDGGGGGGGGGGGKjttttttttttttttttttttttttttttttttttttttttttt
46 | ttttttttttttttttttttttttttttttttttttttttfjtGGGGGGGGGGEDWtttttttttttttttttttttttttttttttttttttttttttt
47 | tttttttttttttttttttttttttttttttttttttttttttfEEDEEEEEEEKttttttttttttttttttttttttttttttttttttttttttttt
48 | tttttttttttttttttttttttttttttttttttttttttttttLDEWWEEEttttttttttttttttttttttttttttttttttttttttttttttt
49 | ttttttttttttttttttttttttttttttttttttttttttjtttKWjtKWjttttttttttttttttttttttttttttttttttttttttttttttt
50 | tttttttttttttttttttttttttttttttttttttttttttttttEjtjjijtttttttttttttttttttttttttttttttttttttttttttttt
51 | tttttttttttttttttttttttttttttttttttttttttttttK,Gttf,fDtttttttttttttttttttttttttttttttttttttttttttttt
52 | ttttttttttttttttttttttttttttttttttttttttttttWjD;tt;,fWtttttttttttttttttttttttttttttttttttttttttttttt
53 | ttttttttttttttttttttttttttttttttttttttttttttttjttttttttttttttttttttttttttttttttttttttttttttttttttttt
54 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
55 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
56 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
57 | tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
--------------------------------------------------------------------------------
/book-api/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | application:
3 | name: imooc-red-book-nacos
4 | cloud:
5 | nacos:
6 | config:
7 | server-addr: 10.206.0.11:8848 # nacos 所在的地址
8 | file-extension: yaml
--------------------------------------------------------------------------------
/book-common/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.imooc
8 | imooc-red-book-dev
9 | 1.0-SNAPSHOT
10 |
11 |
12 | book-common
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-web
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-configuration-processor
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-aop
37 |
38 |
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-data-redis
43 |
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-amqp
49 |
50 |
51 |
52 |
53 | org.projectlombok
54 | lombok
55 |
56 |
57 |
58 |
59 | com.fasterxml.jackson.core
60 | jackson-core
61 |
62 |
63 | com.fasterxml.jackson.core
64 | jackson-annotations
65 |
66 |
67 | com.fasterxml.jackson.core
68 | jackson-databind
69 |
70 |
71 |
72 | commons-codec
73 | commons-codec
74 |
75 |
76 | org.apache.commons
77 | commons-lang3
78 |
79 |
80 | commons-fileupload
81 | commons-fileupload
82 |
83 |
84 |
85 | com.google.guava
86 | guava
87 |
88 |
89 |
90 | joda-time
91 | joda-time
92 |
93 |
94 |
95 |
96 | com.tencentcloudapi
97 | tencentcloud-sdk-java
98 | 3.1.270
99 |
100 |
101 |
102 | io.minio
103 | minio
104 | 8.2.1
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/enums/FileTypeEnum.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | /**
4 | * @Desc: 文件类型 枚举
5 | */
6 | public enum FileTypeEnum {
7 | BGIMG(1, "用户背景图"),
8 | FACE(2, "用户头像");
9 |
10 | public final Integer type;
11 | public final String value;
12 |
13 | FileTypeEnum(Integer type, String value) {
14 | this.type = type;
15 | this.value = value;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/enums/MessageEnum.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | /**
4 | * @Desc: 消息类型
5 | */
6 | public enum MessageEnum {
7 | FOLLOW_YOU(1, "关注", "follow"),
8 | LIKE_VLOG(2, "点赞视频", "likeVideo"),
9 | COMMENT_VLOG(3, "评论视频", "comment"),
10 | REPLY_YOU(4, "回复评论", "replay"),
11 | LIKE_COMMENT(5, "点赞评论", "likeComment");
12 |
13 | public final Integer type;
14 | public final String value;
15 | public final String enValue;
16 |
17 | MessageEnum(Integer type, String value, String enValue) {
18 | this.type = type;
19 | this.value = value;
20 | this.enValue = enValue;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/enums/Sex.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | /**
4 | * @Desc: 性别 枚举
5 | */
6 | public enum Sex {
7 | woman(0, "女"),
8 | man(1, "男"),
9 | secret(2, "保密");
10 |
11 | public final Integer type;
12 | public final String value;
13 |
14 | Sex(Integer type, String value) {
15 | this.type = type;
16 | this.value = value;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/enums/UserInfoModifyType.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | import com.imooc.exceptions.GraceException;
4 | import com.imooc.grace.result.ResponseStatusEnum;
5 |
6 | /**
7 | * @Desc: 修改用户信息类型 枚举
8 | */
9 | public enum UserInfoModifyType {
10 | NICKNAME(1, "昵称"),
11 | IMOOCNUM(2, "慕课号"),
12 | SEX(3, "性别"),
13 | BIRTHDAY(4, "生日"),
14 | LOCATION(5, "所在地"),
15 | DESC(6, "简介");
16 |
17 | public final Integer type;
18 | public final String value;
19 |
20 | UserInfoModifyType(Integer type, String value) {
21 | this.type = type;
22 | this.value = value;
23 | }
24 |
25 | public static void checkUserInfoTypeIsRight(Integer type) {
26 | if (type != UserInfoModifyType.NICKNAME.type &&
27 | type != UserInfoModifyType.IMOOCNUM.type &&
28 | type != UserInfoModifyType.SEX.type &&
29 | type != UserInfoModifyType.BIRTHDAY.type &&
30 | type != UserInfoModifyType.LOCATION.type &&
31 | type != UserInfoModifyType.DESC.type) {
32 | GraceException.display(ResponseStatusEnum.USER_INFO_UPDATED_ERROR);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/enums/YesOrNo.java:
--------------------------------------------------------------------------------
1 | package com.imooc.enums;
2 |
3 | /**
4 | * @Desc: 是否 枚举
5 | */
6 | public enum YesOrNo {
7 | NO(0, "否"),
8 | YES(1, "是");
9 |
10 | public final Integer type;
11 | public final String value;
12 |
13 | YesOrNo(Integer type, String value) {
14 | this.type = type;
15 | this.value = value;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/exceptions/GraceException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exceptions;
2 |
3 | import com.imooc.grace.result.ResponseStatusEnum;
4 |
5 | /**
6 | * 优雅的处理异常,统一封装
7 | */
8 | public class GraceException {
9 |
10 | public static void display(ResponseStatusEnum responseStatusEnum) {
11 | throw new MyCustomException(responseStatusEnum);
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/exceptions/GraceExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exceptions;
2 |
3 | import com.imooc.grace.result.GraceJSONResult;
4 | import com.imooc.grace.result.ResponseStatusEnum;
5 | import org.springframework.validation.BindingResult;
6 | import org.springframework.validation.FieldError;
7 | import org.springframework.web.bind.MethodArgumentNotValidException;
8 | import org.springframework.web.bind.annotation.ControllerAdvice;
9 | import org.springframework.web.bind.annotation.ExceptionHandler;
10 | import org.springframework.web.bind.annotation.ResponseBody;
11 | import org.springframework.web.multipart.MaxUploadSizeExceededException;
12 |
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | /**
18 | * 统一异常拦截处理
19 | * 可以针对异常的类型进行捕获,然后返回json信息到前端
20 | */
21 | @ControllerAdvice
22 | public class GraceExceptionHandler {
23 |
24 | @ExceptionHandler(MyCustomException.class)
25 | @ResponseBody
26 | public GraceJSONResult returnMyException(MyCustomException e) {
27 | //e.printStackTrace();
28 | return GraceJSONResult.exception(e.getResponseStatusEnum());
29 | }
30 |
31 | @ExceptionHandler(MethodArgumentNotValidException.class)
32 | @ResponseBody
33 | public GraceJSONResult returnMethodArgumentNotValid(MethodArgumentNotValidException e) {
34 | BindingResult result = e.getBindingResult();
35 | Map map = getErrors(result);
36 | return GraceJSONResult.errorMap(map);
37 | }
38 |
39 | @ExceptionHandler(MaxUploadSizeExceededException.class)
40 | @ResponseBody
41 | public GraceJSONResult returnMaxUploadSize(MaxUploadSizeExceededException e) {
42 | // e.printStackTrace();
43 | return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_MAX_SIZE_2MB_ERROR);
44 | }
45 |
46 | public Map getErrors(BindingResult result) {
47 | Map map = new HashMap<>();
48 | List errorList = result.getFieldErrors();
49 | for (FieldError ff : errorList) {
50 | // 错误所对应的属性字段名
51 | String field = ff.getField();
52 | // 错误的信息
53 | String msg = ff.getDefaultMessage();
54 | map.put(field, msg);
55 | }
56 | return map;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/exceptions/MyCustomException.java:
--------------------------------------------------------------------------------
1 | package com.imooc.exceptions;
2 |
3 | import com.imooc.grace.result.ResponseStatusEnum;
4 |
5 | /**
6 | * 自定义异常
7 | * 目的:统一处理异常信息
8 | * 便于解耦,拦截器、service与controller 异常错误的解耦,
9 | * 不会被service返回的类型而限制
10 | */
11 | public class MyCustomException extends RuntimeException {
12 |
13 | private ResponseStatusEnum responseStatusEnum;
14 |
15 | public MyCustomException(ResponseStatusEnum responseStatusEnum) {
16 | super("异常状态码为:" + responseStatusEnum.status()
17 | + ";具体异常信息为:" + responseStatusEnum.msg());
18 | this.responseStatusEnum = responseStatusEnum;
19 | }
20 |
21 | public ResponseStatusEnum getResponseStatusEnum() {
22 | return responseStatusEnum;
23 | }
24 |
25 | public void setResponseStatusEnum(ResponseStatusEnum responseStatusEnum) {
26 | this.responseStatusEnum = responseStatusEnum;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/grace/result/GraceJSONResult.java:
--------------------------------------------------------------------------------
1 | package com.imooc.grace.result;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * 自定义响应数据类型枚举升级版本
7 | *
8 | * @Title: IMOOCJSONResult.java
9 | * @Package com.imooc.utils
10 | * @Description: 自定义响应数据结构
11 | * 本类可提供给 H5/ios/安卓/公众号/小程序 使用
12 | * 前端接受此类数据(json object)后,可自行根据业务去实现相关功能
13 | *
14 | * @Copyright: Copyright (c) 2020
15 | * @Company: www.imooc.com
16 | * @author 慕课网 - 风间影月
17 | * @version V2.0
18 | */
19 | public class GraceJSONResult {
20 |
21 | // 响应业务状态码
22 | private Integer status;
23 |
24 | // 响应消息
25 | private String msg;
26 |
27 | // 是否成功
28 | private Boolean success;
29 |
30 | // 响应数据,可以是Object,也可以是List或Map等
31 | private Object data;
32 |
33 | /**
34 | * 成功返回,带有数据的,直接往OK方法丢data数据即可
35 | * @param data
36 | * @return
37 | */
38 | public static GraceJSONResult ok(Object data) {
39 | return new GraceJSONResult(data);
40 | }
41 | /**
42 | * 成功返回,不带有数据的,直接调用ok方法,data无须传入(其实就是null)
43 | * @return
44 | */
45 | public static GraceJSONResult ok() {
46 | return new GraceJSONResult(ResponseStatusEnum.SUCCESS);
47 | }
48 | public GraceJSONResult(Object data) {
49 | this.status = ResponseStatusEnum.SUCCESS.status();
50 | this.msg = ResponseStatusEnum.SUCCESS.msg();
51 | this.success = ResponseStatusEnum.SUCCESS.success();
52 | this.data = data;
53 | }
54 |
55 |
56 | /**
57 | * 错误返回,直接调用error方法即可,当然也可以在ResponseStatusEnum中自定义错误后再返回也都可以
58 | * @return
59 | */
60 | public static GraceJSONResult error() {
61 | return new GraceJSONResult(ResponseStatusEnum.FAILED);
62 | }
63 |
64 | /**
65 | * 错误返回,map中包含了多条错误信息,可以用于表单验证,把错误统一的全部返回出去
66 | * @param map
67 | * @return
68 | */
69 | public static GraceJSONResult errorMap(Map map) {
70 | return new GraceJSONResult(ResponseStatusEnum.FAILED, map);
71 | }
72 |
73 | /**
74 | * 错误返回,直接返回错误的消息
75 | * @param msg
76 | * @return
77 | */
78 | public static GraceJSONResult errorMsg(String msg) {
79 | return new GraceJSONResult(ResponseStatusEnum.FAILED, msg);
80 | }
81 |
82 | /**
83 | * 错误返回,token异常,一些通用的可以在这里统一定义
84 | * @return
85 | */
86 | public static GraceJSONResult errorTicket() {
87 | return new GraceJSONResult(ResponseStatusEnum.TICKET_INVALID);
88 | }
89 |
90 | /**
91 | * 自定义错误范围,需要传入一个自定义的枚举,可以到[ResponseStatusEnum.java[中自定义后再传入
92 | * @param responseStatus
93 | * @return
94 | */
95 | public static GraceJSONResult errorCustom(ResponseStatusEnum responseStatus) {
96 | return new GraceJSONResult(responseStatus);
97 | }
98 | public static GraceJSONResult exception(ResponseStatusEnum responseStatus) {
99 | return new GraceJSONResult(responseStatus);
100 | }
101 |
102 | public GraceJSONResult(ResponseStatusEnum responseStatus) {
103 | this.status = responseStatus.status();
104 | this.msg = responseStatus.msg();
105 | this.success = responseStatus.success();
106 | }
107 | public GraceJSONResult(ResponseStatusEnum responseStatus, Object data) {
108 | this.status = responseStatus.status();
109 | this.msg = responseStatus.msg();
110 | this.success = responseStatus.success();
111 | this.data = data;
112 | }
113 | public GraceJSONResult(ResponseStatusEnum responseStatus, String msg) {
114 | this.status = responseStatus.status();
115 | this.msg = msg;
116 | this.success = responseStatus.success();
117 | }
118 |
119 | public GraceJSONResult() {
120 | }
121 |
122 | public Integer getStatus() {
123 | return status;
124 | }
125 |
126 | public void setStatus(Integer status) {
127 | this.status = status;
128 | }
129 |
130 | public String getMsg() {
131 | return msg;
132 | }
133 |
134 | public void setMsg(String msg) {
135 | this.msg = msg;
136 | }
137 |
138 | public Object getData() {
139 | return data;
140 | }
141 |
142 | public void setData(Object data) {
143 | this.data = data;
144 | }
145 |
146 | public Boolean getSuccess() {
147 | return success;
148 | }
149 |
150 | public void setSuccess(Boolean success) {
151 | this.success = success;
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/grace/result/IMOOCJSONResult.java:
--------------------------------------------------------------------------------
1 | package com.imooc.grace.result;
2 |
3 | /**
4 | *
5 | * @Title: IMOOCJSONResult.java
6 | * @Package com.imooc.utils
7 | * @Description: 自定义响应数据结构
8 | * 本类可提供给 H5/ios/安卓/公众号/小程序 使用
9 | * 前端接受此类数据(json object)后,可自行根据业务去实现相关功能
10 | *
11 | * 200:表示成功
12 | * 500:表示错误,错误信息在msg字段中
13 | * 501:bean验证错误,不管多少个错误都以map形式返回
14 | * 502:拦截器拦截到用户token出错
15 | * 555:异常抛出信息
16 | * 556: 用户qq校验异常
17 | * 557: 校验用户是否在CAS登录,用户门票的校验
18 | * @Copyright: Copyright (c) 2020
19 | * @Company: www.imooc.com
20 | * @author 慕课网 - 风间影月
21 | * @version V1.0
22 | */
23 | public class IMOOCJSONResult {
24 |
25 | // 响应业务状态
26 | private Integer status;
27 |
28 | // 响应消息
29 | private String msg;
30 |
31 | // 响应中的数据
32 | private Object data;
33 |
34 | private String ok; // 不使用
35 |
36 | public static IMOOCJSONResult build(Integer status, String msg, Object data) {
37 | return new IMOOCJSONResult(status, msg, data);
38 | }
39 |
40 | public static IMOOCJSONResult build(Integer status, String msg, Object data, String ok) {
41 | return new IMOOCJSONResult(status, msg, data, ok);
42 | }
43 |
44 | public static IMOOCJSONResult ok(Object data) {
45 | return new IMOOCJSONResult(data);
46 | }
47 |
48 | public static IMOOCJSONResult ok() {
49 | return new IMOOCJSONResult(null);
50 | }
51 |
52 | public static IMOOCJSONResult errorMsg(String msg) {
53 | return new IMOOCJSONResult(500, msg, null);
54 | }
55 |
56 | public static IMOOCJSONResult errorUserTicket(String msg) {
57 | return new IMOOCJSONResult(557, msg, null);
58 | }
59 |
60 | public static IMOOCJSONResult errorMap(Object data) {
61 | return new IMOOCJSONResult(501, "error", data);
62 | }
63 |
64 | public static IMOOCJSONResult errorTokenMsg(String msg) {
65 | return new IMOOCJSONResult(502, msg, null);
66 | }
67 |
68 | public static IMOOCJSONResult errorException(String msg) {
69 | return new IMOOCJSONResult(555, msg, null);
70 | }
71 |
72 | public static IMOOCJSONResult errorUserQQ(String msg) {
73 | return new IMOOCJSONResult(556, msg, null);
74 | }
75 |
76 | public IMOOCJSONResult() {
77 |
78 | }
79 |
80 | public IMOOCJSONResult(Integer status, String msg, Object data) {
81 | this.status = status;
82 | this.msg = msg;
83 | this.data = data;
84 | }
85 |
86 | public IMOOCJSONResult(Integer status, String msg, Object data, String ok) {
87 | this.status = status;
88 | this.msg = msg;
89 | this.data = data;
90 | this.ok = ok;
91 | }
92 |
93 | public IMOOCJSONResult(Object data) {
94 | this.status = 200;
95 | this.msg = "OK";
96 | this.data = data;
97 | }
98 |
99 | public Boolean isOK() {
100 | return this.status == 200;
101 | }
102 |
103 | public Integer getStatus() {
104 | return status;
105 | }
106 |
107 | public void setStatus(Integer status) {
108 | this.status = status;
109 | }
110 |
111 | public String getMsg() {
112 | return msg;
113 | }
114 |
115 | public void setMsg(String msg) {
116 | this.msg = msg;
117 | }
118 |
119 | public Object getData() {
120 | return data;
121 | }
122 |
123 | public void setData(Object data) {
124 | this.data = data;
125 | }
126 |
127 | public String getOk() {
128 | return ok;
129 | }
130 |
131 | public void setOk(String ok) {
132 | this.ok = ok;
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/grace/result/ResponseStatusEnum.java:
--------------------------------------------------------------------------------
1 | package com.imooc.grace.result;
2 |
3 | /**
4 | * 响应结果枚举,用于提供给GraceJSONResult返回给前端的
5 | * 本枚举类中包含了很多的不同的状态码供使用,可以自定义
6 | * 便于更优雅的对状态码进行管理,一目了然
7 | */
8 | public enum ResponseStatusEnum {
9 |
10 | SUCCESS(200, true, "操作成功!"),
11 | FAILED(500, false, "操作失败!"),
12 |
13 | // 50x
14 | UN_LOGIN(501,false,"请登录后再继续操作!"),
15 | TICKET_INVALID(502,false,"会话失效,请重新登录!"),
16 | NO_AUTH(503,false,"您的权限不足,无法继续操作!"),
17 | MOBILE_ERROR(504,false,"短信发送失败,请稍后重试!"),
18 | SMS_NEED_WAIT_ERROR(505,false,"短信发送太快啦~请稍后再试!"),
19 | SMS_CODE_ERROR(506,false,"验证码过期或不匹配,请稍后再试!"),
20 | USER_FROZEN(507,false,"用户已被冻结,请联系管理员!"),
21 | USER_UPDATE_ERROR(508,false,"用户信息更新失败,请联系管理员!"),
22 | USER_INACTIVE_ERROR(509,false,"请前往[账号设置]修改信息激活后再进行后续操作!"),
23 | USER_INFO_UPDATED_ERROR(5091,false,"用户信息修改失败!"),
24 | USER_INFO_UPDATED_NICKNAME_EXIST_ERROR(5092,false,"昵称已经存在!"),
25 | USER_INFO_UPDATED_IMOOCNUM_EXIST_ERROR(5092,false,"慕课号已经存在!"),
26 | USER_INFO_CANT_UPDATED_IMOOCNUM_ERROR(5092,false,"慕课号无法修改!"),
27 | FILE_UPLOAD_NULL_ERROR(510,false,"文件不能为空,请选择一个文件再上传!"),
28 | FILE_UPLOAD_FAILD(511,false,"文件上传失败!"),
29 | FILE_FORMATTER_FAILD(512,false,"文件图片格式不支持!"),
30 | FILE_MAX_SIZE_500KB_ERROR(5131,false,"仅支持500kb大小以下的图片上传!"),
31 | FILE_MAX_SIZE_2MB_ERROR(5132,false,"仅支持2MB大小以下的图片上传!"),
32 | FILE_NOT_EXIST_ERROR(514,false,"你所查看的文件不存在!"),
33 | USER_STATUS_ERROR(515,false,"用户状态参数出错!"),
34 | USER_NOT_EXIST_ERROR(516,false,"用户不存在!"),
35 |
36 | // 自定义系统级别异常 54x
37 | SYSTEM_INDEX_OUT_OF_BOUNDS(541, false, "系统错误,数组越界!"),
38 | SYSTEM_ARITHMETIC_BY_ZERO(542, false, "系统错误,无法除零!"),
39 | SYSTEM_NULL_POINTER(543, false, "系统错误,空指针!"),
40 | SYSTEM_NUMBER_FORMAT(544, false, "系统错误,数字转换异常!"),
41 | SYSTEM_PARSE(545, false, "系统错误,解析异常!"),
42 | SYSTEM_IO(546, false, "系统错误,IO输入输出异常!"),
43 | SYSTEM_FILE_NOT_FOUND(547, false, "系统错误,文件未找到!"),
44 | SYSTEM_CLASS_CAST(548, false, "系统错误,类型强制转换错误!"),
45 | SYSTEM_PARSER_ERROR(549, false, "系统错误,解析出错!"),
46 | SYSTEM_DATE_PARSER_ERROR(550, false, "系统错误,日期解析出错!"),
47 |
48 | // admin 管理系统 56x
49 | ADMIN_USERNAME_NULL_ERROR(561, false, "管理员登录名不能为空!"),
50 | ADMIN_USERNAME_EXIST_ERROR(562, false, "管理员登录名已存在!"),
51 | ADMIN_NAME_NULL_ERROR(563, false, "管理员负责人不能为空!"),
52 | ADMIN_PASSWORD_ERROR(564, false, "密码不能为空后者两次输入不一致!"),
53 | ADMIN_CREATE_ERROR(565, false, "添加管理员失败!"),
54 | ADMIN_PASSWORD_NULL_ERROR(566, false, "密码不能为空!"),
55 | ADMIN_NOT_EXIT_ERROR(567, false, "管理员不存在或密码错误!"),
56 | ADMIN_FACE_NULL_ERROR(568, false, "人脸信息不能为空!"),
57 | ADMIN_FACE_LOGIN_ERROR(569, false, "人脸识别失败,请重试!"),
58 | CATEGORY_EXIST_ERROR(570, false, "文章分类已存在,请换一个分类名!"),
59 |
60 | // 媒体中心 相关错误 58x
61 | ARTICLE_COVER_NOT_EXIST_ERROR(580, false, "文章封面不存在,请选择一个!"),
62 | ARTICLE_CATEGORY_NOT_EXIST_ERROR(581, false, "请选择正确的文章领域!"),
63 | ARTICLE_CREATE_ERROR(582, false, "创建文章失败,请重试或联系管理员!"),
64 | ARTICLE_QUERY_PARAMS_ERROR(583, false, "文章列表查询参数错误!"),
65 | ARTICLE_DELETE_ERROR(584, false, "文章删除失败!"),
66 | ARTICLE_WITHDRAW_ERROR(585, false, "文章撤回失败!"),
67 | ARTICLE_REVIEW_ERROR(585, false, "文章审核出错!"),
68 | ARTICLE_ALREADY_READ_ERROR(586, false, "文章重复阅读!"),
69 |
70 | // 人脸识别错误代码
71 | FACE_VERIFY_TYPE_ERROR(600, false, "人脸比对验证类型不正确!"),
72 | FACE_VERIFY_LOGIN_ERROR(601, false, "人脸登录失败!"),
73 |
74 | // 系统错误,未预期的错误 555
75 | SYSTEM_ERROR(555, false, "系统繁忙,请稍后再试!"),
76 | SYSTEM_OPERATION_ERROR(556, false, "操作失败,请重试或联系管理员"),
77 | SYSTEM_RESPONSE_NO_INFO(557, false, ""),
78 | SYSTEM_ERROR_GLOBAL(558, false, "全局降级:系统繁忙,请稍后再试!"),
79 | SYSTEM_ERROR_FEIGN(559, false, "客户端Feign降级:系统繁忙,请稍后再试!"),
80 | SYSTEM_ERROR_ZUUL(560, false, "请求系统过于繁忙,请稍后再试!");
81 |
82 |
83 | // 响应业务状态
84 | private Integer status;
85 | // 调用是否成功
86 | private Boolean success;
87 | // 响应消息,可以为成功或者失败的消息
88 | private String msg;
89 |
90 | ResponseStatusEnum(Integer status, Boolean success, String msg) {
91 | this.status = status;
92 | this.success = success;
93 | this.msg = msg;
94 | }
95 |
96 | public Integer status() {
97 | return status;
98 | }
99 | public Boolean success() {
100 | return success;
101 | }
102 | public String msg() {
103 | return msg;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/DesensitizationUtil.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | /**
4 | * 通用脱敏工具类
5 | * 可用于:
6 | * 用户名
7 | * 手机号
8 | * 邮箱
9 | * 地址等
10 | */
11 | public class DesensitizationUtil {
12 |
13 | private static final int SIZE = 6;
14 | private static final String SYMBOL = "*";
15 |
16 | public static void main(String[] args) {
17 | String name = commonDisplay("慕课网");
18 | String mobile = commonDisplay("13900000000");
19 | String mail = commonDisplay("admin@imooc.com");
20 | String address = commonDisplay("北京大运河东路888号");
21 |
22 | System.out.println(name);
23 | System.out.println(mobile);
24 | System.out.println(mail);
25 | System.out.println(address);
26 | }
27 |
28 | /**
29 | * 通用脱敏方法
30 | * @param value
31 | * @return
32 | */
33 | public static String commonDisplay(String value) {
34 | if (null == value || "".equals(value)) {
35 | return value;
36 | }
37 | int len = value.length();
38 | int pamaone = len / 2;
39 | int pamatwo = pamaone - 1;
40 | int pamathree = len % 2;
41 | StringBuilder stringBuilder = new StringBuilder();
42 | if (len <= 2) {
43 | if (pamathree == 1) {
44 | return SYMBOL;
45 | }
46 | stringBuilder.append(SYMBOL);
47 | stringBuilder.append(value.charAt(len - 1));
48 | } else {
49 | if (pamatwo <= 0) {
50 | stringBuilder.append(value.substring(0, 1));
51 | stringBuilder.append(SYMBOL);
52 | stringBuilder.append(value.substring(len - 1, len));
53 |
54 | } else if (pamatwo >= SIZE / 2 && SIZE + 1 != len) {
55 | int pamafive = (len - SIZE) / 2;
56 | stringBuilder.append(value.substring(0, pamafive));
57 | for (int i = 0; i < SIZE; i++) {
58 | stringBuilder.append(SYMBOL);
59 | }
60 | if ((pamathree == 0 && SIZE / 2 == 0) || (pamathree != 0 && SIZE % 2 != 0)) {
61 | stringBuilder.append(value.substring(len - pamafive, len));
62 | } else {
63 | stringBuilder.append(value.substring(len - (pamafive + 1), len));
64 | }
65 | } else {
66 | int pamafour = len - 2;
67 | stringBuilder.append(value.substring(0, 1));
68 | for (int i = 0; i < pamafour; i++) {
69 | stringBuilder.append(SYMBOL);
70 | }
71 | stringBuilder.append(value.substring(len - 1, len));
72 | }
73 | }
74 | return stringBuilder.toString();
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/IPUtil.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 |
5 | /**
6 | * 用户获得用户ip的工具类
7 | */
8 | public class IPUtil {
9 |
10 | /**
11 | * 获取请求IP:
12 | * 用户的真实IP不能使用request.getRemoteAddr()
13 | * 这是因为可能会使用一些代理软件,这样ip获取就不准确了
14 | * 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。
15 | * @param request
16 | * @return
17 | */
18 | public static String getRequestIp(HttpServletRequest request) {
19 | String ip = request.getHeader("x-forwarded-for");
20 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
21 | ip = request.getHeader("Proxy-Client-IP");
22 | }
23 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
24 | ip = request.getHeader("WL-Proxy-Client-IP");
25 | }
26 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
27 | ip = request.getHeader("HTTP_CLIENT_IP");
28 | }
29 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
30 | ip = request.getHeader("HTTP_X_FORWARDED_FOR");
31 | }
32 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
33 | ip = request.getRemoteAddr();
34 | }
35 | return ip;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/JsonUtils.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | import com.fasterxml.jackson.core.JsonProcessingException;
4 | import com.fasterxml.jackson.databind.JavaType;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * @Title: JsonUtils.java
12 | * @Package com.imooc.utils
13 | * @Description: json转换类
14 | * Copyright: Copyright (c)
15 | * Company: www.imooc.com
16 | *
17 | * @author imooc
18 | */
19 | public class JsonUtils {
20 |
21 | // 定义jackson对象
22 | private static final ObjectMapper MAPPER = new ObjectMapper();
23 |
24 | /**
25 | * 将对象转换成json字符串。
26 | * @param data
27 | * @return
28 | */
29 | public static String objectToJson(Object data) {
30 | try {
31 | String string = MAPPER.writeValueAsString(data);
32 | return string;
33 | } catch (JsonProcessingException e) {
34 | e.printStackTrace();
35 | }
36 | return null;
37 | }
38 |
39 | /**
40 | * 将json结果集转化为对象
41 | *
42 | * @param jsonData json数据
43 | * @param beanType 对象中的object类型
44 | * @return
45 | */
46 | public static T jsonToPojo(String jsonData, Class beanType) {
47 | try {
48 | T t = MAPPER.readValue(jsonData, beanType);
49 | return t;
50 | } catch (Exception e) {
51 | e.printStackTrace();
52 | }
53 | return null;
54 | }
55 |
56 | /**
57 | * 将json数据转换成pojo对象list
58 | * @param jsonData
59 | * @param beanType
60 | * @return
61 | */
62 | public static List jsonToList(String jsonData, Class beanType) {
63 | JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
64 | try {
65 | List list = MAPPER.readValue(jsonData, javaType);
66 | return list;
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | }
70 |
71 | return null;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/MyInfo.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | public class MyInfo {
4 |
5 | public static String getMobile() {
6 | return "";
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/PagedGridResult.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | *
7 | * @Title: PagedGridResult.java
8 | * @Package com.imooc.utils
9 | * @Description: 用来返回分页Grid的数据格式
10 | * Copyright: Copyright (c) 2021
11 | */
12 | public class PagedGridResult {
13 |
14 | private int page; // 当前页数
15 | private long total; // 总页数
16 | private long records; // 总记录数
17 | private List> rows; // 每行显示的内容
18 |
19 | public int getPage() {
20 | return page;
21 | }
22 | public void setPage(int page) {
23 | this.page = page;
24 | }
25 |
26 | public long getTotal() {
27 | return total;
28 | }
29 |
30 | public void setTotal(long total) {
31 | this.total = total;
32 | }
33 |
34 | public void setTotal(int total) {
35 | this.total = total;
36 | }
37 | public long getRecords() {
38 | return records;
39 | }
40 | public void setRecords(long records) {
41 | this.records = records;
42 | }
43 | public List> getRows() {
44 | return rows;
45 | }
46 | public void setRows(List> rows) {
47 | this.rows = rows;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/SMSUtils.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | import com.tencentcloudapi.common.Credential;
4 | import com.tencentcloudapi.common.exception.TencentCloudSDKException;
5 | import com.tencentcloudapi.common.profile.ClientProfile;
6 | import com.tencentcloudapi.common.profile.HttpProfile;
7 | import com.tencentcloudapi.sms.v20210111.SmsClient;
8 | import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
9 | import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.stereotype.Component;
12 |
13 | @Component
14 | public class SMSUtils {
15 | @Autowired
16 | private TencentCloudProperties tencentCloudProperties;
17 |
18 | public void sendSMS(String phone, String code) throws Exception {
19 | try {
20 | /* 必要步骤:
21 | * 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。
22 | * 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
23 | * 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
24 | * 以免泄露密钥对危及你的财产安全。
25 | * CAM密匙查询获取: https://console.cloud.tencent.com/cam/capi*/
26 | Credential cred = new Credential(tencentCloudProperties.getSecretId(),
27 | tencentCloudProperties.getSecretKey());
28 |
29 | // 实例化一个http选项,可选的,没有特殊需求可以跳过
30 | HttpProfile httpProfile = new HttpProfile();
31 |
32 | // httpProfile.setReqMethod("POST"); // 默认使用POST
33 |
34 | /* SDK会自动指定域名。通常是不需要特地指定域名的,但是如果你访问的是金融区的服务
35 | * 则必须手动指定域名,例如sms的上海金融区域名: sms.ap-shanghai-fsi.tencentcloudapi.com */
36 | httpProfile.setEndpoint("sms.tencentcloudapi.com");
37 |
38 | // 实例化一个client选项
39 | ClientProfile clientProfile = new ClientProfile();
40 | clientProfile.setHttpProfile(httpProfile);
41 | // 实例化要请求产品的client对象,clientProfile是可选的
42 | SmsClient client = new SmsClient(cred, "ap-nanjing", clientProfile);
43 |
44 | // 实例化一个请求对象,每个接口都会对应一个request对象
45 | SendSmsRequest req = new SendSmsRequest();
46 | String[] phoneNumberSet1 = {"+86" + phone};//电话号码
47 | req.setPhoneNumberSet(phoneNumberSet1);
48 | req.setSmsSdkAppId("1400822965"); // 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId
49 | req.setSignName("我们更爱保持沉默公众号"); // 签名
50 | req.setTemplateId("1802516"); // 模板id:必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看
51 |
52 | /* 模板参数(自定义占位变量): 若无模板参数,则设置为空 */
53 | String[] templateParamSet1 = {code};
54 | req.setTemplateParamSet(templateParamSet1);
55 |
56 | // 返回的resp是一个SendSmsResponse的实例,与请求对象对应
57 | SendSmsResponse resp = client.SendSms(req);
58 | // 输出json格式的字符串回包
59 | // System.out.println(SendSmsResponse.toJsonString(resp));
60 | } catch (TencentCloudSDKException e) {
61 | System.out.println(e.toString());
62 | }
63 | }
64 |
65 | public static void main(String[] args) {
66 | try {
67 | new SMSUtils().sendSMS("15237439161", "7896");
68 | } catch (Exception e) {
69 | e.printStackTrace();
70 | }
71 | }
72 | }
73 |
74 |
75 |
--------------------------------------------------------------------------------
/book-common/src/main/java/com/imooc/utils/TencentCloudProperties.java:
--------------------------------------------------------------------------------
1 | package com.imooc.utils;
2 |
3 | import lombok.Data;
4 | import org.springframework.boot.context.properties.ConfigurationProperties;
5 | import org.springframework.context.annotation.PropertySource;
6 | import org.springframework.stereotype.Component;
7 |
8 | /**
9 | * @author vercen
10 | * @version 1.0
11 | * @date 2023/5/25 10:21
12 | * 获取短信配置
13 | */
14 | @Component
15 | @Data
16 | @PropertySource("classpath:tencentcloud.properties")
17 | @ConfigurationProperties(prefix = "tencent.cloud")
18 | public class TencentCloudProperties {
19 |
20 | private String secretId;
21 | private String secretKey;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/Code.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | import org.n3r.idworker.strategy.DefaultRandomCodeStrategy;
4 |
5 | public class Code {
6 | private static RandomCodeStrategy strategy;
7 |
8 | static {
9 | RandomCodeStrategy strategy = new DefaultRandomCodeStrategy();
10 | strategy.init();
11 | configure(strategy);
12 | }
13 |
14 | public static synchronized void configure(RandomCodeStrategy custom) {
15 | if (strategy == custom) return;
16 | if (strategy != null) strategy.release();
17 |
18 | strategy = custom;
19 | }
20 |
21 | /**
22 | * Next Unique code.
23 | * The max length will be 1024-Integer.MAX-Integer.MAX(2147483647) which has 4+10+10+2*1=26 characters.
24 | * The min length will be 0-0.
25 | *
26 | * @return unique string code.
27 | */
28 | public static synchronized String next() {
29 | long workerId = Id.getWorkerId();
30 | int prefix = strategy.prefix();
31 | int next = strategy.next();
32 |
33 | return String.format("%d-%03d-%06d", workerId, prefix, next);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/DayCode.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | import org.n3r.idworker.strategy.DayPrefixRandomCodeStrategy;
4 |
5 | public class DayCode {
6 | static RandomCodeStrategy strategy;
7 |
8 | static {
9 | DayPrefixRandomCodeStrategy dayPrefixCodeStrategy = new DayPrefixRandomCodeStrategy("yyMM");
10 | dayPrefixCodeStrategy.setMinRandomSize(7);
11 | dayPrefixCodeStrategy.setMaxRandomSize(7);
12 | strategy = dayPrefixCodeStrategy;
13 | strategy.init();
14 | }
15 |
16 | public static synchronized String next() {
17 | return String.format("%d-%04d-%07d", Id.getWorkerId(), strategy.prefix(), strategy.next());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/Id.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | import org.n3r.idworker.strategy.DefaultWorkerIdStrategy;
4 |
5 | public class Id {
6 | private static WorkerIdStrategy workerIdStrategy;
7 | private static IdWorker idWorker;
8 |
9 | static {
10 | configure(DefaultWorkerIdStrategy.instance);
11 | }
12 |
13 | public static synchronized void configure(WorkerIdStrategy custom) {
14 | if (workerIdStrategy == custom) return;
15 |
16 | if (workerIdStrategy != null) workerIdStrategy.release();
17 | workerIdStrategy = custom;
18 | workerIdStrategy.initialize();
19 | idWorker = new IdWorker(workerIdStrategy.availableWorkerId());
20 | }
21 |
22 | public static long next() {
23 | return idWorker.nextId();
24 | }
25 |
26 | public static long getWorkerId() {
27 | return idWorker.getWorkerId();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/IdWorker.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | import java.security.SecureRandom;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | public class IdWorker {
9 | protected long epoch = 1288834974657L;
10 | // protected long epoch = 1387886498127L; // 2013-12-24 20:01:38.127
11 |
12 |
13 | protected long workerIdBits = 10L;
14 | protected long maxWorkerId = -1L ^ (-1L << workerIdBits);
15 | protected long sequenceBits = 11L;
16 |
17 | protected long workerIdShift = sequenceBits;
18 | protected long timestampLeftShift = sequenceBits + workerIdBits;
19 | protected long sequenceMask = -1L ^ (-1L << sequenceBits);
20 |
21 | protected long lastMillis = -1L;
22 |
23 | protected final long workerId;
24 | protected long sequence = 0L;
25 | protected Logger logger = LoggerFactory.getLogger(IdWorker.class);
26 |
27 | public IdWorker(long workerId) {
28 | this.workerId = checkWorkerId(workerId);
29 |
30 | logger.debug("worker starting. timestamp left shift {}, worker id {}", timestampLeftShift, workerId);
31 | }
32 |
33 | public long getEpoch() {
34 | return epoch;
35 | }
36 |
37 | private long checkWorkerId(long workerId) {
38 | // sanity check for workerId
39 | if (workerId > maxWorkerId || workerId < 0) {
40 | int rand = new SecureRandom().nextInt((int) maxWorkerId + 1);
41 | logger.warn("worker Id can't be greater than {} or less than 0, use a random {}", maxWorkerId, rand);
42 | return rand;
43 | }
44 |
45 | return workerId;
46 | }
47 |
48 | public synchronized long nextId() {
49 | long timestamp = millisGen();
50 |
51 | if (timestamp < lastMillis) {
52 | logger.error("clock is moving backwards. Rejecting requests until {}.", lastMillis);
53 | throw new InvalidSystemClock(String.format(
54 | "Clock moved backwards. Refusing to generate id for {} milliseconds", lastMillis - timestamp));
55 | }
56 |
57 | if (lastMillis == timestamp) {
58 | sequence = (sequence + 1) & sequenceMask;
59 | if (sequence == 0)
60 | timestamp = tilNextMillis(lastMillis);
61 | } else {
62 | sequence = 0;
63 | }
64 |
65 | lastMillis = timestamp;
66 | long diff = timestamp - getEpoch();
67 | return (diff << timestampLeftShift) |
68 | (workerId << workerIdShift) |
69 | sequence;
70 | }
71 |
72 | protected long tilNextMillis(long lastMillis) {
73 | long millis = millisGen();
74 | while (millis <= lastMillis)
75 | millis = millisGen();
76 |
77 | return millis;
78 | }
79 |
80 | protected long millisGen() {
81 | return System.currentTimeMillis();
82 | }
83 |
84 | public long getLastMillis() {
85 | return lastMillis;
86 | }
87 |
88 | public long getWorkerId() {
89 | return workerId;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/InvalidSystemClock.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | public class InvalidSystemClock extends RuntimeException {
4 | public InvalidSystemClock(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/RandomCodeStrategy.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | public interface RandomCodeStrategy {
4 | void init();
5 |
6 | int prefix();
7 |
8 | int next();
9 |
10 | void release();
11 | }
12 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/Sid.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | import org.n3r.idworker.strategy.DefaultWorkerIdStrategy;
4 | import org.n3r.idworker.utils.Utils;
5 | import org.springframework.stereotype.Component;
6 |
7 | import java.text.SimpleDateFormat;
8 | import java.util.Date;
9 |
10 | @Component
11 | public class Sid {
12 | private static WorkerIdStrategy workerIdStrategy;
13 | private static IdWorker idWorker;
14 |
15 | static {
16 | configure(DefaultWorkerIdStrategy.instance);
17 | }
18 |
19 |
20 | public static synchronized void configure(WorkerIdStrategy custom) {
21 | if (workerIdStrategy != null) {
22 | workerIdStrategy.release();
23 | }
24 | workerIdStrategy = custom;
25 | idWorker = new IdWorker(workerIdStrategy.availableWorkerId()) {
26 | @Override
27 | public long getEpoch() {
28 | return Utils.midnightMillis();
29 | }
30 | };
31 | }
32 |
33 | /**
34 | * 一天最大毫秒86400000,最大占用27比特
35 | * 27+10+11=48位 最大值281474976710655(15字),YK0XXHZ827(10字)
36 | * 6位(YYMMDD)+15位,共21位
37 | *
38 | * @return 固定21位数字字符串
39 | */
40 |
41 | public static String next() {
42 | long id = idWorker.nextId();
43 | String yyMMdd = new SimpleDateFormat("yyMMdd").format(new Date());
44 | return yyMMdd + String.format("%014d", id);
45 | }
46 |
47 |
48 | /**
49 | * 返回固定16位的字母数字混编的字符串。
50 | */
51 | public String nextShort() {
52 | long id = idWorker.nextId();
53 | String yyMMdd = new SimpleDateFormat("yyMMdd").format(new Date());
54 | return yyMMdd + Utils.padLeft(Utils.encode(id), 10, '0');
55 | }
56 |
57 | public static void main(String[] args) {
58 | String aa = new Sid().nextShort();
59 | String bb = new Sid().next();
60 |
61 | System.out.println(aa);
62 | System.out.println(bb);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/Test.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | public class Test {
4 |
5 | public static void main(String[] args) {
6 |
7 | for (int i = 0 ; i < 1000 ; i ++) {
8 | // System.out.println(Sid.nextShort());
9 | }
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/WorkerIdStrategy.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker;
2 |
3 | public interface WorkerIdStrategy {
4 | void initialize();
5 |
6 | long availableWorkerId();
7 |
8 | void release();
9 | }
10 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/strategy/DayPrefixRandomCodeStrategy.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.strategy;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | public class DayPrefixRandomCodeStrategy extends DefaultRandomCodeStrategy {
7 | private final String dayFormat;
8 | private String lastDay;
9 |
10 | public DayPrefixRandomCodeStrategy(String dayFormat) {
11 | this.dayFormat = dayFormat;
12 | }
13 |
14 | @Override
15 | public void init() {
16 | String day = createDate();
17 | if (day.equals(lastDay))
18 | throw new RuntimeException("init failed for day unrolled");
19 |
20 | lastDay = day;
21 |
22 | availableCodes.clear();
23 | release();
24 |
25 | prefixIndex = Integer.parseInt(lastDay);
26 | if (tryUsePrefix()) return;
27 |
28 | throw new RuntimeException("prefix is not available " + prefixIndex);
29 | }
30 |
31 | private String createDate() {
32 | return new SimpleDateFormat(dayFormat).format(new Date());
33 | }
34 |
35 | @Override
36 | public int next() {
37 | if (!lastDay.equals(createDate())) init();
38 |
39 | return super.next();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/strategy/DefaultRandomCodeStrategy.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.strategy;
2 |
3 | import org.n3r.idworker.Id;
4 | import org.n3r.idworker.RandomCodeStrategy;
5 | import org.n3r.idworker.utils.Utils;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.security.SecureRandom;
12 | import java.util.ArrayDeque;
13 | import java.util.BitSet;
14 | import java.util.Queue;
15 |
16 | public class DefaultRandomCodeStrategy implements RandomCodeStrategy {
17 | public static final int MAX_BITS = 1000000;
18 |
19 | Logger log = LoggerFactory.getLogger(DefaultRandomCodeStrategy.class);
20 |
21 | File idWorkerHome = Utils.createIdWorkerHome();
22 | volatile FileLock fileLock;
23 | BitSet codesFilter;
24 |
25 | int prefixIndex = -1;
26 | File codePrefixIndex;
27 |
28 | int minRandomSize = 6;
29 | int maxRandomSize = 6;
30 |
31 | public DefaultRandomCodeStrategy() {
32 | destroyFileLockWhenShutdown();
33 | }
34 |
35 | @Override
36 | public void init() {
37 | release();
38 |
39 | while (++prefixIndex < 1000) {
40 | if (tryUsePrefix()) return;
41 | }
42 |
43 | throw new RuntimeException("all prefixes are used up, the world maybe ends!");
44 | }
45 |
46 | public DefaultRandomCodeStrategy setMinRandomSize(int minRandomSize) {
47 | this.minRandomSize = minRandomSize;
48 | return this;
49 | }
50 |
51 | public DefaultRandomCodeStrategy setMaxRandomSize(int maxRandomSize) {
52 | this.maxRandomSize = maxRandomSize;
53 | return this;
54 | }
55 |
56 | protected boolean tryUsePrefix() {
57 | codePrefixIndex = new File(idWorkerHome, Id.getWorkerId() + ".code.prefix." + prefixIndex);
58 |
59 | if (!createPrefixIndexFile()) return false;
60 | if (!createFileLock()) return false;
61 | if (!createBloomFilter()) return false;
62 |
63 | log.info("get available prefix index file {}", codePrefixIndex);
64 |
65 | return true;
66 | }
67 |
68 | private boolean createFileLock() {
69 | if (fileLock != null) fileLock.destroy();
70 | fileLock = new FileLock(codePrefixIndex);
71 | return fileLock.tryLock();
72 | }
73 |
74 | private boolean createBloomFilter() {
75 | codesFilter = fileLock.readObject();
76 | if (codesFilter == null) {
77 | log.info("create new bloom filter");
78 | codesFilter = new BitSet(MAX_BITS); // 2^24
79 | } else {
80 | int size = codesFilter.cardinality();
81 | if (size >= MAX_BITS) {
82 | log.warn("bloom filter with prefix file {} is already full", codePrefixIndex);
83 | return false;
84 | }
85 | log.info("recreate bloom filter with cardinality {}", size);
86 | }
87 |
88 | return true;
89 | }
90 |
91 | private void destroyFileLockWhenShutdown() {
92 | Runtime.getRuntime().addShutdownHook(new Thread() {
93 | @Override
94 | public void run() {
95 | release();
96 | }
97 | });
98 | }
99 |
100 | private boolean createPrefixIndexFile() {
101 | try {
102 | codePrefixIndex.createNewFile();
103 | return codePrefixIndex.exists();
104 | } catch (IOException e) {
105 | e.printStackTrace();
106 | log.warn("create file {} error {}", codePrefixIndex, e.getMessage());
107 | }
108 | return false;
109 | }
110 |
111 | @Override
112 | public int prefix() {
113 | return prefixIndex;
114 | }
115 |
116 | static final int CACHE_CODES_NUM = 1000;
117 |
118 | SecureRandom secureRandom = new SecureRandom();
119 | Queue availableCodes = new ArrayDeque(CACHE_CODES_NUM);
120 |
121 | @Override
122 | public int next() {
123 | if (availableCodes.isEmpty()) generate();
124 |
125 | return availableCodes.poll();
126 | }
127 |
128 | @Override
129 | public synchronized void release() {
130 | if (fileLock != null) {
131 | fileLock.writeObject(codesFilter);
132 | fileLock.destroy();
133 | fileLock = null;
134 | }
135 | }
136 |
137 | private void generate() {
138 | for (int i = 0; i < CACHE_CODES_NUM; ++i)
139 | availableCodes.add(generateOne());
140 |
141 | fileLock.writeObject(codesFilter);
142 | }
143 |
144 | private int generateOne() {
145 | while (true) {
146 | int code = secureRandom.nextInt(max(maxRandomSize));
147 | boolean existed = contains(code);
148 |
149 | code = !existed ? add(code) : tryFindAvailableCode(code);
150 | if (code >= 0) return code;
151 |
152 | init();
153 | }
154 | }
155 |
156 | private int tryFindAvailableCode(int code) {
157 | int next = codesFilter.nextClearBit(code);
158 | if (next != -1 && next < max(maxRandomSize)) return add(next);
159 |
160 | next = codesFilter.previousClearBit(code);
161 | if (next != -1) return add(next);
162 |
163 | return -1;
164 | }
165 |
166 | private int add(int code) {
167 | codesFilter.set(code);
168 | return code;
169 | }
170 |
171 | private boolean contains(int code) {
172 | return codesFilter.get(code);
173 | }
174 |
175 |
176 | private int max(int size) {
177 | switch (size) {
178 | case 1: // fall through
179 | case 2: // fall through
180 | case 3: // fall through
181 | case 4:
182 | return 10000;
183 | case 5:
184 | return 100000;
185 | case 6:
186 | return 1000000;
187 | case 7:
188 | return 10000000;
189 | case 8:
190 | return 100000000;
191 | case 9:
192 | return 1000000000;
193 | default:
194 | return Integer.MAX_VALUE;
195 | }
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/strategy/DefaultWorkerIdStrategy.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.strategy;
2 |
3 | import org.n3r.idworker.WorkerIdStrategy;
4 | import org.n3r.idworker.utils.HttpReq;
5 | import org.n3r.idworker.utils.Ip;
6 | import org.n3r.idworker.utils.Props;
7 | import org.n3r.idworker.utils.Utils;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.io.File;
12 | import java.io.IOException;
13 | import java.security.SecureRandom;
14 | import java.util.Properties;
15 | import java.util.Random;
16 |
17 | public class DefaultWorkerIdStrategy implements WorkerIdStrategy {
18 | static long workerIdBits = 10L;
19 | static long maxWorkerId = -1L ^ (-1L << workerIdBits);
20 | static Random random = new SecureRandom();
21 |
22 | public static final WorkerIdStrategy instance = new DefaultWorkerIdStrategy();
23 |
24 | private final Properties props =
25 | Props.tryProperties("idworker-client.properties", Utils.DOT_IDWORKERS);
26 | private final String idWorkerServerUrl =
27 | props.getProperty("server.address", "http://id.worker.server:18001");
28 |
29 | String userName = System.getProperty("user.name");
30 |
31 | String ipDotUsername = Ip.ip + "." + userName;
32 | String ipudotlock = ipDotUsername + ".lock.";
33 | int workerIdIndex = ipudotlock.length();
34 | long workerId;
35 | FileLock fileLock;
36 |
37 | Logger logger = LoggerFactory.getLogger(DefaultWorkerIdStrategy.class);
38 | private boolean inited;
39 |
40 |
41 | private void init() {
42 | workerId = findAvailWorkerId();
43 | if (workerId >= 0) {
44 | destroyFileLockWhenShutdown();
45 | startSyncThread();
46 | } else {
47 | syncWithWorkerIdServer();
48 | workerId = findAvailWorkerId();
49 | if (workerId < 0) workerId = increaseWithWorkerIdServer();
50 | }
51 |
52 | if (workerId < 0) workerId = tryToCreateOnIp();
53 | if (workerId < 0) {
54 | logger.warn("DANGEROUS!!! Try to use random worker id.");
55 | workerId = tryToRandomOnIp(); // Try avoiding! it could cause duplicated
56 | }
57 |
58 | if (workerId < 0) {
59 | logger.warn("the world may be ended!");
60 | throw new RuntimeException("the world may be ended");
61 | }
62 | }
63 |
64 | private void destroyFileLockWhenShutdown() {
65 | Runtime.getRuntime().addShutdownHook(new Thread() {
66 | @Override
67 | public void run() {
68 | fileLock.destroy();
69 | }
70 | });
71 | }
72 |
73 | private void startSyncThread() {
74 | new Thread() {
75 | @Override
76 | public void run() {
77 | syncWithWorkerIdServer();
78 | }
79 | }.start();
80 | }
81 |
82 | private long increaseWithWorkerIdServer() {
83 | String incId = HttpReq.get(idWorkerServerUrl)
84 | .req("/inc")
85 | .param("ipu", ipDotUsername)
86 | .exec();
87 | if (incId == null || incId.trim().isEmpty()) return -1L;
88 |
89 | long lid = Long.parseLong(incId);
90 |
91 | return checkAvail(lid);
92 | }
93 |
94 | private long tryToCreateOnIp() {
95 | long wid = Ip.lip & maxWorkerId;
96 |
97 | return checkAvail(wid);
98 | }
99 |
100 | private long tryToRandomOnIp() {
101 | long avaiWorkerId = -1L;
102 | long tryTimes = -1;
103 |
104 | while (avaiWorkerId < 0 && ++tryTimes < maxWorkerId) {
105 | long wid = Ip.lip & random.nextInt((int) maxWorkerId);
106 |
107 | avaiWorkerId = checkAvail(wid);
108 | }
109 | return avaiWorkerId;
110 | }
111 |
112 | private long checkAvail(long wid) {
113 | long availWorkerId = -1L;
114 | try {
115 | File idWorkerHome = Utils.createIdWorkerHome();
116 | new File(idWorkerHome, ipudotlock + String.format("%04d", wid)).createNewFile();
117 | availWorkerId = findAvailWorkerId();
118 | } catch (IOException e) {
119 | logger.warn("checkAvail error", e);
120 | }
121 |
122 | return availWorkerId;
123 | }
124 |
125 | private void syncWithWorkerIdServer() {
126 | String syncIds = HttpReq.get(idWorkerServerUrl).req("/sync")
127 | .param("ipu", ipDotUsername).param("ids", buildWorkerIdsOfCurrentIp())
128 | .exec();
129 | if (syncIds == null || syncIds.trim().isEmpty()) return;
130 |
131 | String[] syncIdsArr = syncIds.split(",");
132 | File idWorkerHome = Utils.createIdWorkerHome();
133 | for (String syncId : syncIdsArr) {
134 | try {
135 | new File(idWorkerHome, ipudotlock + syncId).createNewFile();
136 | } catch (IOException e) {
137 | logger.warn("create workerid lock file error", e);
138 | }
139 | }
140 | }
141 |
142 | private String buildWorkerIdsOfCurrentIp() {
143 | StringBuilder sb = new StringBuilder();
144 | File idWorkerHome = Utils.createIdWorkerHome();
145 | for (File lockFile : idWorkerHome.listFiles()) {
146 | // check the format like 10.142.1.151.lock.0001
147 | if (!lockFile.getName().startsWith(ipudotlock)) continue;
148 |
149 | String workerId = lockFile.getName().substring(workerIdIndex);
150 | if (!workerId.matches("\\d\\d\\d\\d")) continue;
151 |
152 | if (sb.length() > 0) sb.append(',');
153 | sb.append(workerId);
154 | }
155 |
156 | return sb.toString();
157 | }
158 |
159 |
160 | /**
161 | * Find the local available worker id.
162 | *
163 | * @return -1 when N/A
164 | */
165 | private long findAvailWorkerId() {
166 | File idWorkerHome = Utils.createIdWorkerHome();
167 |
168 | for (File lockFile : idWorkerHome.listFiles()) {
169 | // check the format like 10.142.1.151.lock.0001
170 | if (!lockFile.getName().startsWith(ipudotlock)) continue;
171 |
172 | String workerId = lockFile.getName().substring(workerIdIndex);
173 | if (!workerId.matches("\\d\\d\\d\\d")) continue;
174 |
175 | FileLock fileLock = new FileLock(lockFile);
176 | if (!fileLock.tryLock()) {
177 | fileLock.destroy();
178 | continue;
179 | }
180 |
181 | this.fileLock = fileLock;
182 | return Long.parseLong(workerId);
183 | }
184 |
185 | return -1;
186 | }
187 |
188 | @Override
189 | public void initialize() {
190 | if (inited) return;
191 | init();
192 | this.inited = true;
193 | }
194 |
195 | @Override
196 | public long availableWorkerId() {
197 | return workerId;
198 | }
199 |
200 | @Override
201 | public void release() {
202 | if (fileLock != null) fileLock.destroy();
203 | inited = false;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/strategy/FileLock.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.strategy;
2 |
3 |
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.io.*;
8 | import java.nio.channels.Channels;
9 | import java.nio.channels.ClosedChannelException;
10 | import java.nio.channels.FileChannel;
11 | import java.nio.channels.OverlappingFileLockException;
12 |
13 | /**
14 | * A file lock a la flock/funlock
15 | *
16 | * The given path will be created and opened if it doesn't exist.
17 | */
18 | public class FileLock {
19 | private final File file;
20 | private FileChannel channel;
21 | private java.nio.channels.FileLock flock = null;
22 | Logger logger = LoggerFactory.getLogger(FileLock.class);
23 |
24 | public FileLock(File file) {
25 | this.file = file;
26 |
27 | try {
28 | file.createNewFile(); // create the file if it doesn't exist
29 | channel = new RandomAccessFile(file, "rw").getChannel();
30 | } catch (IOException e) {
31 | throw new RuntimeException(e);
32 | }
33 | }
34 |
35 |
36 | /**
37 | * Lock the file or throw an exception if the lock is already held
38 | */
39 | public void lock() {
40 | try {
41 | synchronized (this) {
42 | logger.trace("Acquiring lock on {}", file.getAbsolutePath());
43 | flock = channel.lock();
44 | }
45 | } catch (IOException e) {
46 | throw new RuntimeException(e);
47 | }
48 | }
49 |
50 | /**
51 | * Try to lock the file and return true if the locking succeeds
52 | */
53 | public boolean tryLock() {
54 | synchronized (this) {
55 | logger.trace("Acquiring lock on {}", file.getAbsolutePath());
56 | try {
57 | // weirdly this method will return null if the lock is held by another
58 | // process, but will throw an exception if the lock is held by this process
59 | // so we have to handle both cases
60 | flock = channel.tryLock();
61 | return flock != null;
62 | } catch (OverlappingFileLockException e) {
63 | return false;
64 | } catch (IOException e) {
65 | throw new RuntimeException(e);
66 | }
67 | }
68 | }
69 |
70 | /**
71 | * Unlock the lock if it is held
72 | */
73 | public void unlock() {
74 | synchronized (this) {
75 | logger.trace("Releasing lock on {}", file.getAbsolutePath());
76 | if (flock == null) return;
77 | try {
78 | flock.release();
79 | } catch (ClosedChannelException e) {
80 | // Ignore
81 | } catch (IOException e) {
82 | throw new RuntimeException(e);
83 | }
84 | }
85 | }
86 |
87 | /**
88 | * Destroy this lock, closing the associated FileChannel
89 | */
90 | public void destroy() {
91 | synchronized (this) {
92 | unlock();
93 | if (!channel.isOpen()) return;
94 |
95 | try {
96 | channel.close();
97 | } catch (IOException e) {
98 | throw new RuntimeException(e);
99 | }
100 | }
101 | }
102 |
103 |
104 | @SuppressWarnings("unchecked")
105 | public T readObject() {
106 | try {
107 | InputStream is = Channels.newInputStream(channel);
108 | ObjectInputStream objectReader = new ObjectInputStream(is);
109 | return (T) objectReader.readObject();
110 | } catch (EOFException e) {
111 | } catch (Exception e) {
112 | throw new RuntimeException(e);
113 | }
114 |
115 | return null;
116 | }
117 |
118 |
119 | public synchronized boolean writeObject(Object object) {
120 | if (!channel.isOpen()) return false;
121 |
122 | try {
123 | channel.position(0);
124 | OutputStream out = Channels.newOutputStream(channel);
125 | ObjectOutputStream objectOutput = new ObjectOutputStream(out);
126 | objectOutput.writeObject(object);
127 | return true;
128 | } catch (Exception e) {
129 | throw new RuntimeException(e);
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/HttpReq.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.io.UnsupportedEncodingException;
10 | import java.net.*;
11 |
12 | public class HttpReq {
13 | private final String baseUrl;
14 | private String req;
15 | private StringBuilder params = new StringBuilder();
16 | Logger logger = LoggerFactory.getLogger(HttpReq.class);
17 |
18 | public HttpReq(String baseUrl) {
19 | this.baseUrl = baseUrl;
20 | }
21 |
22 | public static HttpReq get(String baseUrl) {
23 | return new HttpReq(baseUrl);
24 | }
25 |
26 | public HttpReq req(String req) {
27 | this.req = req;
28 | return this;
29 | }
30 |
31 | public HttpReq param(String name, String value) {
32 | if (params.length() > 0) params.append('&');
33 | try {
34 | params.append(name).append('=').append(URLEncoder.encode(value, "UTF-8"));
35 | } catch (UnsupportedEncodingException e) {
36 | throw new RuntimeException(e);
37 | }
38 |
39 | return this;
40 | }
41 |
42 | public String exec() {
43 | HttpURLConnection http = null;
44 | try {
45 | http = (HttpURLConnection) new URL(baseUrl
46 | + (req == null ? "" : req)
47 | + (params.length() > 0 ? ("?" + params) : "")).openConnection();
48 | http.setRequestProperty("Accept-Charset", "UTF-8");
49 | HttpURLConnection.setFollowRedirects(false);
50 | http.setConnectTimeout(5 * 1000);
51 | http.setReadTimeout(5 * 1000);
52 | http.connect();
53 |
54 | int status = http.getResponseCode();
55 | String charset = getCharset(http.getHeaderField("Content-Type"));
56 |
57 | if (status == 200) {
58 | return readResponseBody(http, charset);
59 | } else {
60 | logger.warn("non 200 respoonse :" + readErrorResponseBody(http, status, charset));
61 | return null;
62 | }
63 | } catch (Exception e) {
64 | logger.error("exec error {}", e.getMessage());
65 | return null;
66 | } finally {
67 | if (http != null) http.disconnect();
68 | }
69 |
70 | }
71 |
72 | private static String readErrorResponseBody(HttpURLConnection http, int status, String charset) throws IOException {
73 | InputStream errorStream = http.getErrorStream();
74 | if (errorStream != null) {
75 | String error = toString(charset, errorStream);
76 | return ("STATUS CODE =" + status + "\n\n" + error);
77 | } else {
78 | return ("STATUS CODE =" + status);
79 | }
80 | }
81 |
82 | private static String readResponseBody(HttpURLConnection http, String charset) throws IOException {
83 | InputStream inputStream = http.getInputStream();
84 |
85 | return toString(charset, inputStream);
86 | }
87 |
88 | private static String toString(String charset, InputStream inputStream) throws IOException {
89 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
90 | byte[] buffer = new byte[1024];
91 |
92 | int length;
93 | while ((length = inputStream.read(buffer)) != -1) {
94 | baos.write(buffer, 0, length);
95 | }
96 |
97 | return new String(baos.toByteArray(), charset);
98 | }
99 |
100 | private static String getCharset(String contentType) {
101 | if (contentType == null) return "UTF-8";
102 |
103 | String charset = null;
104 | for (String param : contentType.replace(" ", "").split(";")) {
105 | if (param.startsWith("charset=")) {
106 | charset = param.split("=", 2)[1];
107 | break;
108 | }
109 | }
110 |
111 | return charset == null ? "UTF-8" : charset;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/IPv4Utils.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 | /**
4 | * This utility provides methods to either convert an IPv4 address to its long format or a 32bit dotted format.
5 | *
6 | * @author Aion
7 | * Created on 22/11/12
8 | */
9 | public class IPv4Utils {
10 |
11 | /**
12 | * Returns the long format of the provided IP address.
13 | *
14 | * @param ipAddress the IP address
15 | * @return the long format of ipAddress
16 | * @throws IllegalArgumentException if ipAddress
is invalid
17 | */
18 | public static long toLong(String ipAddress) {
19 | if (ipAddress == null || ipAddress.isEmpty()) {
20 | throw new IllegalArgumentException("ip address cannot be null or empty");
21 | }
22 | String[] octets = ipAddress.split(java.util.regex.Pattern.quote("."));
23 | if (octets.length != 4) {
24 | throw new IllegalArgumentException("invalid ip address");
25 | }
26 | long ip = 0;
27 | for (int i = 3; i >= 0; i--) {
28 | long octet = Long.parseLong(octets[3 - i]);
29 | if (octet > 255 || octet < 0) {
30 | throw new IllegalArgumentException("invalid ip address");
31 | }
32 | ip |= octet << (i * 8);
33 | }
34 | return ip;
35 | }
36 |
37 | /**
38 | * Returns the 32bit dotted format of the provided long ip.
39 | *
40 | * @param ip the long ip
41 | * @return the 32bit dotted format of ip
42 | * @throws IllegalArgumentException if ip
is invalid
43 | */
44 | public static String toString(long ip) {
45 | // if ip is bigger than 255.255.255.255 or smaller than 0.0.0.0
46 | if (ip > 4294967295l || ip < 0) {
47 | throw new IllegalArgumentException("invalid ip");
48 | }
49 | StringBuilder ipAddress = new StringBuilder();
50 | for (int i = 3; i >= 0; i--) {
51 | int shift = i * 8;
52 | ipAddress.append((ip & (0xff << shift)) >> shift);
53 | if (i > 0) {
54 | ipAddress.append(".");
55 | }
56 | }
57 | return ipAddress.toString();
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/Ip.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 |
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.net.Inet4Address;
8 | import java.net.InetAddress;
9 | import java.net.NetworkInterface;
10 | import java.net.SocketException;
11 | import java.util.Enumeration;
12 |
13 | public class Ip {
14 | static Logger logger = LoggerFactory.getLogger(Ip.class);
15 |
16 | public static String ip;
17 | public static long lip;
18 |
19 | static {
20 | try {
21 | InetAddress localHostLANAddress = getFirstNonLoopbackAddress();
22 | ip = localHostLANAddress.getHostAddress();
23 |
24 | byte[] address = localHostLANAddress.getAddress();
25 | lip = ((address [0] & 0xFFL) << (3*8)) +
26 | ((address [1] & 0xFFL) << (2*8)) +
27 | ((address [2] & 0xFFL) << (1*8)) +
28 | (address [3] & 0xFFL);
29 | } catch (Exception e) {
30 | logger.error("get ipv4 failed ", e);
31 | }
32 | }
33 |
34 | private static InetAddress getFirstNonLoopbackAddress() throws SocketException {
35 | Enumeration en = NetworkInterface.getNetworkInterfaces();
36 | while (en.hasMoreElements()) {
37 | NetworkInterface i = (NetworkInterface) en.nextElement();
38 | for (Enumeration en2 = i.getInetAddresses(); en2.hasMoreElements(); ) {
39 | InetAddress addr = (InetAddress) en2.nextElement();
40 | if (addr.isLoopbackAddress()) continue;
41 |
42 | if (addr instanceof Inet4Address) {
43 | return addr;
44 | }
45 | }
46 | }
47 | return null;
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/Props.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.io.*;
7 | import java.util.Properties;
8 |
9 | import static java.io.File.separator;
10 | import static org.n3r.idworker.utils.Serializes.closeQuietly;
11 |
12 | public class Props {
13 | static Logger log = LoggerFactory.getLogger(Props.class);
14 |
15 | public static Properties tryProperties(String propertiesFileName, String userHomeBasePath) {
16 | Properties properties = new Properties();
17 | InputStream is = null;
18 | try {
19 | is = Props.tryResource(propertiesFileName, userHomeBasePath, Silent.ON);
20 | if (is != null) properties.load(is);
21 | } catch (IOException e) {
22 | log.error("load properties error: {}", e.getMessage());
23 | } finally {
24 | closeQuietly(is);
25 | }
26 |
27 | return properties;
28 | }
29 |
30 |
31 | enum Silent {ON, OFF}
32 |
33 | public static InputStream tryResource(String propertiesFileName, String userHomeBasePath, Silent silent) {
34 | InputStream is = currentDirResource(new File(propertiesFileName));
35 | if (is != null) return is;
36 |
37 | is = userHomeResource(propertiesFileName, userHomeBasePath);
38 | if (is != null) return is;
39 |
40 | is = classpathResource(propertiesFileName);
41 | if (is != null || silent == Silent.ON) return is;
42 |
43 | throw new RuntimeException("fail to find " + propertiesFileName + " in current dir or classpath");
44 | }
45 |
46 | private static InputStream userHomeResource(String pathname, String appHome) {
47 | String filePath = System.getProperty("user.home") + separator + appHome;
48 | File dir = new File(filePath);
49 | if (!dir.exists()) return null;
50 |
51 | return currentDirResource(new File(dir, pathname));
52 | }
53 |
54 | private static InputStream currentDirResource(File file) {
55 | if (!file.exists()) return null;
56 |
57 | try {
58 | return new FileInputStream(file);
59 | } catch (FileNotFoundException e) {
60 | // This should not happened
61 | log.error("read file {} error", file, e);
62 | return null;
63 | }
64 | }
65 |
66 | public static InputStream classpathResource(String resourceName) {
67 | return Props.class.getClassLoader().getResourceAsStream(resourceName);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/Serializes.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 | import java.io.*;
4 | import java.nio.channels.FileChannel;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | public class Serializes {
9 |
10 | @SuppressWarnings("unchecked")
11 | public static List readObjects(File file) {
12 | ArrayList objects = new ArrayList();
13 | ObjectInputStream objectReader = null;
14 | FileInputStream fis = null;
15 | try {
16 | fis = new FileInputStream(file);
17 | objectReader = new ObjectInputStream(fis);
18 | while (true)
19 | objects.add((T) objectReader.readObject());
20 |
21 | } catch (EOFException e) {
22 | } catch (Exception e) {
23 | throw new RuntimeException(e);
24 | } finally {
25 | closeQuietly(objectReader);
26 | closeQuietly(fis);
27 | }
28 |
29 | return objects;
30 | }
31 |
32 |
33 | @SuppressWarnings("unchecked")
34 | public static T readObject(File file) {
35 | ObjectInputStream objectReader = null;
36 | FileInputStream fis = null;
37 | try {
38 | fis = new FileInputStream(file);
39 | objectReader = new ObjectInputStream(fis);
40 | return (T) objectReader.readObject();
41 |
42 | } catch (EOFException e) {
43 | } catch (Exception e) {
44 | throw new RuntimeException(e);
45 | } finally {
46 | closeQuietly(objectReader);
47 | closeQuietly(fis);
48 | }
49 |
50 | return null;
51 | }
52 |
53 | public static void writeObject(File file, Object object) {
54 | ObjectOutputStream objectOutput = null;
55 | FileOutputStream fos = null;
56 | try {
57 | fos = new FileOutputStream(file);
58 | objectOutput = new ObjectOutputStream(fos);
59 | objectOutput.writeObject(object);
60 | } catch (Exception e) {
61 | throw new RuntimeException(e);
62 | } finally {
63 | closeQuietly(objectOutput);
64 | closeQuietly(fos);
65 | }
66 | }
67 |
68 | public static void writeObject(FileOutputStream fos, Object object) {
69 | FileChannel channel = fos.getChannel();
70 | if (!channel.isOpen()) throw new RuntimeException("channel is closed");
71 |
72 | try {
73 | channel.position(0);
74 | ObjectOutputStream objectOutput = new ObjectOutputStream(fos);
75 | objectOutput.writeObject(object);
76 | fos.flush();
77 | } catch (Exception e) {
78 | throw new RuntimeException(e);
79 | } finally {
80 | }
81 | }
82 |
83 | public static void writeObjects(File file, Object... objects) {
84 | ObjectOutputStream objectOutput = null;
85 | FileOutputStream fos = null;
86 | try {
87 | fos = new FileOutputStream(file);
88 | objectOutput = new ObjectOutputStream(fos);
89 |
90 | for (Object object : objects)
91 | objectOutput.writeObject(object);
92 | } catch (Exception e) {
93 | throw new RuntimeException(e);
94 | } finally {
95 | closeQuietly(objectOutput);
96 | closeQuietly(fos);
97 | }
98 |
99 | }
100 |
101 | public static void closeQuietly(OutputStream os) {
102 | if (os != null) try {
103 | os.close();
104 | } catch (IOException e) {
105 | // ignore
106 | }
107 | }
108 |
109 |
110 | public static void closeQuietly(InputStream is) {
111 | if (is != null) try {
112 | is.close();
113 | } catch (IOException e) {
114 | // ignore
115 | }
116 |
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/book-common/src/main/java/org/n3r/idworker/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package org.n3r.idworker.utils;
2 |
3 | import java.io.*;
4 | import java.sql.Timestamp;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Calendar;
7 |
8 | public class Utils {
9 |
10 | public static final String DOT_IDWORKERS = ".idworkers";
11 |
12 | public static ClassLoader getClassLoader() {
13 | ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
14 | return contextClassLoader != null ? contextClassLoader : Utils.class.getClassLoader();
15 | }
16 |
17 |
18 | public static InputStream classResourceToStream(String resourceName) {
19 | return getClassLoader().getResourceAsStream(resourceName);
20 | }
21 |
22 |
23 | public static String firstLine(String classResourceName) {
24 | InputStream inputStream = null;
25 | try {
26 | inputStream = classResourceToStream(classResourceName);
27 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
28 |
29 | return bufferedReader.readLine();
30 | } catch (IOException e) {
31 | return null;
32 | } finally {
33 | if (inputStream != null) try {
34 | inputStream.close();
35 | } catch (IOException e) {
36 | // ignore
37 | }
38 | }
39 | }
40 |
41 | public static String checkNotEmpty(String param, String name) {
42 | if (param == null || param.isEmpty())
43 | throw new IllegalArgumentException(name + " is empty");
44 |
45 | return param;
46 | }
47 |
48 |
49 | public static long midnightMillis() {
50 | // today
51 | Calendar date = Calendar.getInstance();
52 | // reset hour, minutes, seconds and millis
53 | date.set(Calendar.HOUR_OF_DAY, 0);
54 | date.set(Calendar.MINUTE, 0);
55 | date.set(Calendar.SECOND, 0);
56 | date.set(Calendar.MILLISECOND, 0);
57 |
58 | return date.getTimeInMillis();
59 | }
60 |
61 | public static void main(String[] args) {
62 | // 2013-12-25 00:00:00.000
63 | System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Timestamp(midnightMillis())));
64 | System.out.println(encode(281474976710655L));
65 | }
66 |
67 | public static long decode(String s, String symbols) {
68 | final int B = symbols.length();
69 | long num = 0;
70 | for (char ch : s.toCharArray()) {
71 | num *= B;
72 | num += symbols.indexOf(ch);
73 | }
74 | return num;
75 | }
76 |
77 | public static String encode(long num) {
78 | return encode(num, defaultRange);
79 | }
80 |
81 | public static String encode(long num, String symbols) {
82 | final int B = symbols.length();
83 | StringBuilder sb = new StringBuilder();
84 | while (num != 0) {
85 | sb.append(symbols.charAt((int) (num % B)));
86 | num /= B;
87 | }
88 | return sb.reverse().toString();
89 | }
90 |
91 | // all un-clearly-recognized letters are skiped.
92 | static String defaultRange = "0123456789ABCDFGHKMNPRSTWXYZ";
93 |
94 | public static String padLeft(String str, int size, char padChar) {
95 | if (str.length() >= size) return str;
96 |
97 | StringBuilder s = new StringBuilder();
98 | for (int i = size - str.length(); i > 0; --i) {
99 | s.append(padChar);
100 | }
101 | s.append(str);
102 |
103 | return s.toString();
104 | }
105 |
106 | public static File createIdWorkerHome() {
107 | String userHome = System.getProperty("user.home");
108 | File idWorkerHome = new File(userHome + File.separator + DOT_IDWORKERS);
109 | idWorkerHome.mkdirs();
110 | if (idWorkerHome.isDirectory()) return idWorkerHome;
111 |
112 | throw new RuntimeException("failed to create .idworkers at user home");
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/book-common/src/main/resources/tencentcloud.properties:
--------------------------------------------------------------------------------
1 | tencent.cloud.secretId=AKIDDD3i7F6h26sOzLRGpBMIxPindfV9dvxk
2 | tencent.cloud.secretKey=A8sNn24siNo10mLfngQvHPH4i8KIDzXq
--------------------------------------------------------------------------------
/book-mapper/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.imooc
8 | imooc-red-book-dev
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | book-mapper
14 |
15 |
16 | 8
17 | 8
18 | UTF-8
19 |
20 |
21 |
22 |
23 | com.imooc
24 | book-model
25 | 1.0-SNAPSHOT
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/CommentMapper.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.Comment;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface CommentMapper extends MyMapper {
9 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/CommentMapperCustom.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.vo.CommentVO;
4 | import org.apache.ibatis.annotations.Param;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | @Repository
11 | public interface CommentMapperCustom {
12 |
13 | public List getCommentList(@Param("paramMap") Map map);
14 |
15 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/FansMapper.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.Fans;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface FansMapper extends MyMapper {
9 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/FansMapperCustom.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.Fans;
5 | import com.imooc.vo.FansVO;
6 | import com.imooc.vo.VlogerVO;
7 | import org.apache.ibatis.annotations.Param;
8 | import org.springframework.stereotype.Repository;
9 |
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | @Repository
14 | public interface FansMapperCustom extends MyMapper {
15 |
16 | public List queryMyFollows(@Param("paramMap") Map map);
17 |
18 | public List queryMyFans(@Param("paramMap") Map map);
19 |
20 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/MyLikedVlogMapper.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.MyLikedVlog;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface MyLikedVlogMapper extends MyMapper {
9 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/UsersMapper.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.Users;
5 | import org.apache.ibatis.annotations.Mapper;
6 |
7 | @Mapper
8 | public interface UsersMapper extends MyMapper {
9 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/VlogMapper.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.my.mapper.MyMapper;
4 | import com.imooc.pojo.Vlog;
5 | import org.springframework.stereotype.Repository;
6 |
7 |
8 | @Repository
9 | public interface VlogMapper extends MyMapper {
10 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/mapper/VlogMapperCustom.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mapper;
2 |
3 | import com.imooc.vo.IndexVlogVO;
4 | import org.apache.ibatis.annotations.Param;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | @Repository
11 | public interface VlogMapperCustom {
12 |
13 | public List getIndexVlogList(@Param("paramMap")Map map);
14 |
15 | public List getVlogDetailById(@Param("paramMap")Map map);
16 |
17 | public List getMyLikedVlogList(@Param("paramMap")Map map);
18 |
19 | public List getMyFollowVlogList(@Param("paramMap")Map map);
20 |
21 | public List getMyFriendVlogList(@Param("paramMap")Map map);
22 |
23 | }
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/my/mapper/MyMapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2014-2016 abel533@gmail.com
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package com.imooc.my.mapper;
26 |
27 | import tk.mybatis.mapper.common.Mapper;
28 | import tk.mybatis.mapper.common.MySqlMapper;
29 |
30 | /**
31 | * 继承自己的MyMapper
32 | */
33 | public interface MyMapper extends Mapper, MySqlMapper {
34 | }
35 |
--------------------------------------------------------------------------------
/book-mapper/src/main/java/com/imooc/repository/MessageRepository.java:
--------------------------------------------------------------------------------
1 | package com.imooc.repository;
2 |
3 | import com.imooc.mo.MessageMO;
4 | import org.springframework.data.domain.Pageable;
5 | import org.springframework.data.mongodb.repository.MongoRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 |
10 | @Repository
11 | public interface MessageRepository extends MongoRepository {
12 |
13 | // 通过实现Repository,自定义条件查询
14 | List findAllByToUserIdEqualsOrderByCreateTimeDesc(String toUserId,
15 | Pageable pageable);
16 | // void deleteAllByFromUserIdAndToUserIdAndMsgType();
17 | }
18 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/CommentMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/CommentMapperCustom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
45 |
46 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/FansMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/FansMapperCustom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
24 |
25 |
44 |
45 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/MyLikedVlogMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/UsersMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/VlogMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/book-mapper/src/main/resources/mapper/VlogMapperCustom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
34 |
35 |
36 |
59 |
60 |
92 |
93 |
125 |
126 |
160 |
161 |
--------------------------------------------------------------------------------
/book-model/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.imooc
8 | imooc-red-book-dev
9 | 1.0-SNAPSHOT
10 |
11 |
12 | book-model
13 |
14 |
15 | 8
16 | 8
17 | UTF-8
18 |
19 |
20 |
21 |
22 | com.imooc
23 | book-common
24 | 1.0-SNAPSHOT
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-validation
31 |
32 |
33 |
34 |
35 | mysql
36 | mysql-connector-java
37 | 8.0.26
38 |
39 |
40 |
41 | org.mybatis.spring.boot
42 | mybatis-spring-boot-starter
43 |
44 |
45 |
46 | tk.mybatis
47 | mapper-spring-boot-starter
48 |
49 |
50 |
51 | com.github.pagehelper
52 | pagehelper-spring-boot-starter
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-starter-data-mongodb
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/bo/CommentBO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.bo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 | import org.hibernate.validator.constraints.Length;
8 |
9 | import javax.validation.constraints.NotBlank;
10 |
11 | @Data
12 | @AllArgsConstructor
13 | @NoArgsConstructor
14 | @ToString
15 | public class CommentBO {
16 |
17 | @NotBlank(message = "留言信息不完整")
18 | private String vlogerId;
19 |
20 | @NotBlank(message = "留言信息不完整")
21 | private String fatherCommentId;
22 |
23 | @NotBlank(message = "留言信息不完整")
24 | private String vlogId;
25 |
26 | @NotBlank(message = "当前用户信息不正确,请尝试重新登录")
27 | private String commentUserId;
28 |
29 | @NotBlank(message = "评论内容不能为空")
30 | @Length(max = 50, message = "评论内容长度不能超过50")
31 | private String content;
32 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/bo/RegistLoginBO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.bo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 | import org.hibernate.validator.constraints.Length;
8 |
9 | import javax.validation.constraints.NotBlank;
10 |
11 | @Data
12 | @ToString
13 | @AllArgsConstructor
14 | @NoArgsConstructor
15 | public class RegistLoginBO {
16 |
17 | @NotBlank(message = "手机号不能为空")
18 | @Length(min = 11, max = 11, message = "手机长度不正确")
19 | private String mobile;
20 | @NotBlank(message = "验证码不能为空")
21 | private String smsCode;
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/bo/UpdatedUserBO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.bo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | import java.util.Date;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | @ToString
14 | public class UpdatedUserBO {
15 | private String id;
16 | private String nickname;
17 | private String imoocNum;
18 | private String face;
19 | private Integer sex;
20 | private Date birthday;
21 | private String country;
22 | private String province;
23 | private String city;
24 | private String district;
25 | private String description;
26 | private String bgImg;
27 | private Integer canImoocNumBeUpdated;
28 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/bo/VlogBO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.bo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @ToString
12 | public class VlogBO {
13 | private String id;
14 | private String vlogerId;
15 | private String url;
16 | private String cover;
17 | private String title;
18 | private Integer width;
19 | private Integer height;
20 | private Integer likeCounts;
21 | private Integer commentsCounts;
22 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/mo/MessageMO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.mo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 | import org.springframework.data.annotation.Id;
8 | import org.springframework.data.mongodb.core.mapping.Document;
9 | import org.springframework.data.mongodb.core.mapping.Field;
10 |
11 | import java.util.Date;
12 | import java.util.Map;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @ToString
18 | @Document("message")
19 | public class MessageMO {
20 |
21 | @Id
22 | private String id; // 消息主键id
23 |
24 | @Field("fromUserId")
25 | private String fromUserId; // 消息来自的用户id
26 | @Field("fromNickname")
27 | private String fromNickname; // 消息来自的用户昵称
28 | @Field("fromFace")
29 | private String fromFace; // 消息来自的用户头像
30 |
31 | @Field("toUserId")
32 | private String toUserId; // 消息发送到某对象的用户id
33 |
34 | @Field("msgType")
35 | private Integer msgType; // 消息类型 枚举
36 | @Field("msgContent")
37 | private Map msgContent; // 消息内容
38 |
39 | @Field("createTime")
40 | private Date createTime; // 消息创建时间
41 | }
42 |
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/pojo/Comment.java:
--------------------------------------------------------------------------------
1 | package com.imooc.pojo;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Id;
5 | import java.util.Date;
6 |
7 | public class Comment {
8 | @Id
9 | private String id;
10 |
11 | /**
12 | * 评论的视频是哪个作者(vloger)的关联id
13 | */
14 | @Column(name = "vloger_id")
15 | private String vlogerId;
16 |
17 | /**
18 | * 如果是回复留言,则本条为子留言,需要关联查询
19 | */
20 | @Column(name = "father_comment_id")
21 | private String fatherCommentId;
22 |
23 | /**
24 | * 回复的那个视频id
25 | */
26 | @Column(name = "vlog_id")
27 | private String vlogId;
28 |
29 | /**
30 | * 发布留言的用户id
31 | */
32 | @Column(name = "comment_user_id")
33 | private String commentUserId;
34 |
35 | /**
36 | * 留言内容
37 | */
38 | private String content;
39 |
40 | /**
41 | * 留言的点赞总数
42 | */
43 | @Column(name = "like_counts")
44 | private Integer likeCounts;
45 |
46 | /**
47 | * 留言时间
48 | */
49 | @Column(name = "create_time")
50 | private Date createTime;
51 |
52 | /**
53 | * @return id
54 | */
55 | public String getId() {
56 | return id;
57 | }
58 |
59 | /**
60 | * @param id
61 | */
62 | public void setId(String id) {
63 | this.id = id;
64 | }
65 |
66 | /**
67 | * 获取评论的视频是哪个作者(vloger)的关联id
68 | *
69 | * @return vloger_id - 评论的视频是哪个作者(vloger)的关联id
70 | */
71 | public String getVlogerId() {
72 | return vlogerId;
73 | }
74 |
75 | /**
76 | * 设置评论的视频是哪个作者(vloger)的关联id
77 | *
78 | * @param vlogerId 评论的视频是哪个作者(vloger)的关联id
79 | */
80 | public void setVlogerId(String vlogerId) {
81 | this.vlogerId = vlogerId;
82 | }
83 |
84 | /**
85 | * 获取如果是回复留言,则本条为子留言,需要关联查询
86 | *
87 | * @return father_comment_id - 如果是回复留言,则本条为子留言,需要关联查询
88 | */
89 | public String getFatherCommentId() {
90 | return fatherCommentId;
91 | }
92 |
93 | /**
94 | * 设置如果是回复留言,则本条为子留言,需要关联查询
95 | *
96 | * @param fatherCommentId 如果是回复留言,则本条为子留言,需要关联查询
97 | */
98 | public void setFatherCommentId(String fatherCommentId) {
99 | this.fatherCommentId = fatherCommentId;
100 | }
101 |
102 | /**
103 | * 获取回复的那个视频id
104 | *
105 | * @return vlog_id - 回复的那个视频id
106 | */
107 | public String getVlogId() {
108 | return vlogId;
109 | }
110 |
111 | /**
112 | * 设置回复的那个视频id
113 | *
114 | * @param vlogId 回复的那个视频id
115 | */
116 | public void setVlogId(String vlogId) {
117 | this.vlogId = vlogId;
118 | }
119 |
120 | /**
121 | * 获取发布留言的用户id
122 | *
123 | * @return comment_user_id - 发布留言的用户id
124 | */
125 | public String getCommentUserId() {
126 | return commentUserId;
127 | }
128 |
129 | /**
130 | * 设置发布留言的用户id
131 | *
132 | * @param commentUserId 发布留言的用户id
133 | */
134 | public void setCommentUserId(String commentUserId) {
135 | this.commentUserId = commentUserId;
136 | }
137 |
138 | /**
139 | * 获取留言内容
140 | *
141 | * @return content - 留言内容
142 | */
143 | public String getContent() {
144 | return content;
145 | }
146 |
147 | /**
148 | * 设置留言内容
149 | *
150 | * @param content 留言内容
151 | */
152 | public void setContent(String content) {
153 | this.content = content;
154 | }
155 |
156 | /**
157 | * 获取留言的点赞总数
158 | *
159 | * @return like_counts - 留言的点赞总数
160 | */
161 | public Integer getLikeCounts() {
162 | return likeCounts;
163 | }
164 |
165 | /**
166 | * 设置留言的点赞总数
167 | *
168 | * @param likeCounts 留言的点赞总数
169 | */
170 | public void setLikeCounts(Integer likeCounts) {
171 | this.likeCounts = likeCounts;
172 | }
173 |
174 | /**
175 | * 获取留言时间
176 | *
177 | * @return create_time - 留言时间
178 | */
179 | public Date getCreateTime() {
180 | return createTime;
181 | }
182 |
183 | /**
184 | * 设置留言时间
185 | *
186 | * @param createTime 留言时间
187 | */
188 | public void setCreateTime(Date createTime) {
189 | this.createTime = createTime;
190 | }
191 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/pojo/Fans.java:
--------------------------------------------------------------------------------
1 | package com.imooc.pojo;
2 |
3 | import org.springframework.data.annotation.Id;
4 |
5 | import javax.persistence.Column;
6 |
7 | public class Fans {
8 | @Id
9 | private String id;
10 |
11 | /**
12 | * 作家用户id
13 | */
14 | @Column(name = "vloger_id")
15 | private String vlogerId;
16 |
17 | /**
18 | * 粉丝用户id
19 | */
20 | @Column(name = "fan_id")
21 | private String fanId;
22 |
23 | /**
24 | * 粉丝是否是vloger的朋友,如果成为朋友,则本表的双方此字段都需要设置为1,如果有一人取关,则两边都需要设置为0
25 | */
26 | @Column(name = "is_fan_friend_of_mine")
27 | private Integer isFanFriendOfMine;
28 |
29 | /**
30 | * @return id
31 | */
32 | public String getId() {
33 | return id;
34 | }
35 |
36 | /**
37 | * @param id
38 | */
39 | public void setId(String id) {
40 | this.id = id;
41 | }
42 |
43 | /**
44 | * 获取作家用户id
45 | *
46 | * @return vloger_id - 作家用户id
47 | */
48 | public String getVlogerId() {
49 | return vlogerId;
50 | }
51 |
52 | /**
53 | * 设置作家用户id
54 | *
55 | * @param vlogerId 作家用户id
56 | */
57 | public void setVlogerId(String vlogerId) {
58 | this.vlogerId = vlogerId;
59 | }
60 |
61 | /**
62 | * 获取粉丝用户id
63 | *
64 | * @return fan_id - 粉丝用户id
65 | */
66 | public String getFanId() {
67 | return fanId;
68 | }
69 |
70 | /**
71 | * 设置粉丝用户id
72 | *
73 | * @param fanId 粉丝用户id
74 | */
75 | public void setFanId(String fanId) {
76 | this.fanId = fanId;
77 | }
78 |
79 | /**
80 | * 获取粉丝是否是vloger的朋友,如果成为朋友,则本表的双方此字段都需要设置为1,如果有一人取关,则两边都需要设置为0
81 | *
82 | * @return is_fan_friend_of_mine - 粉丝是否是vloger的朋友,如果成为朋友,则本表的双方此字段都需要设置为1,如果有一人取关,则两边都需要设置为0
83 | */
84 | public Integer getIsFanFriendOfMine() {
85 | return isFanFriendOfMine;
86 | }
87 |
88 | /**
89 | * 设置粉丝是否是vloger的朋友,如果成为朋友,则本表的双方此字段都需要设置为1,如果有一人取关,则两边都需要设置为0
90 | *
91 | * @param isFanFriendOfMine 粉丝是否是vloger的朋友,如果成为朋友,则本表的双方此字段都需要设置为1,如果有一人取关,则两边都需要设置为0
92 | */
93 | public void setIsFanFriendOfMine(Integer isFanFriendOfMine) {
94 | this.isFanFriendOfMine = isFanFriendOfMine;
95 | }
96 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/pojo/MyLikedVlog.java:
--------------------------------------------------------------------------------
1 | package com.imooc.pojo;
2 |
3 | import org.springframework.data.annotation.Id;
4 |
5 | import javax.persistence.Column;
6 | import javax.persistence.Table;
7 |
8 | @Table(name = "my_liked_vlog")
9 | public class MyLikedVlog {
10 | @Id
11 | private String id;
12 |
13 | /**
14 | * 用户id
15 | */
16 | @Column(name = "user_id")
17 | private String userId;
18 |
19 | /**
20 | * 喜欢的短视频id
21 | */
22 | @Column(name = "vlog_id")
23 | private String vlogId;
24 |
25 | /**
26 | * @return id
27 | */
28 | public String getId() {
29 | return id;
30 | }
31 |
32 | /**
33 | * @param id
34 | */
35 | public void setId(String id) {
36 | this.id = id;
37 | }
38 |
39 | /**
40 | * 获取用户id
41 | *
42 | * @return user_id - 用户id
43 | */
44 | public String getUserId() {
45 | return userId;
46 | }
47 |
48 | /**
49 | * 设置用户id
50 | *
51 | * @param userId 用户id
52 | */
53 | public void setUserId(String userId) {
54 | this.userId = userId;
55 | }
56 |
57 | /**
58 | * 获取喜欢的短视频id
59 | *
60 | * @return vlog_id - 喜欢的短视频id
61 | */
62 | public String getVlogId() {
63 | return vlogId;
64 | }
65 |
66 | /**
67 | * 设置喜欢的短视频id
68 | *
69 | * @param vlogId 喜欢的短视频id
70 | */
71 | public void setVlogId(String vlogId) {
72 | this.vlogId = vlogId;
73 | }
74 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/pojo/Vlog.java:
--------------------------------------------------------------------------------
1 | package com.imooc.pojo;
2 |
3 | import javax.persistence.Column;
4 | import javax.persistence.Id;
5 | import java.util.Date;
6 |
7 | public class Vlog {
8 | @Id
9 | private String id;
10 |
11 | /**
12 | * 对应用户表id,vlog视频发布者
13 | */
14 | @Column(name = "vloger_id")
15 | private String vlogerId;
16 |
17 | /**
18 | * 视频播放地址
19 | */
20 | private String url;
21 |
22 | /**
23 | * 视频封面
24 | */
25 | private String cover;
26 |
27 | /**
28 | * 视频标题,可以为空
29 | */
30 | private String title;
31 |
32 | /**
33 | * 视频width
34 | */
35 | private Integer width;
36 |
37 | /**
38 | * 视频height
39 | */
40 | private Integer height;
41 |
42 | /**
43 | * 点赞总数
44 | */
45 | @Column(name = "like_counts")
46 | private Integer likeCounts;
47 |
48 | /**
49 | * 评论总数
50 | */
51 | @Column(name = "comments_counts")
52 | private Integer commentsCounts;
53 |
54 | /**
55 | * 是否私密,用户可以设置私密,如此可以不公开给比人看
56 | */
57 | @Column(name = "is_private")
58 | private Integer isPrivate;
59 |
60 | /**
61 | * 创建时间 创建时间
62 | */
63 | @Column(name = "created_time")
64 | private Date createdTime;
65 |
66 | /**
67 | * 更新时间 更新时间
68 | */
69 | @Column(name = "updated_time")
70 | private Date updatedTime;
71 |
72 | /**
73 | * @return id
74 | */
75 | public String getId() {
76 | return id;
77 | }
78 |
79 | /**
80 | * @param id
81 | */
82 | public void setId(String id) {
83 | this.id = id;
84 | }
85 |
86 | /**
87 | * 获取对应用户表id,vlog视频发布者
88 | *
89 | * @return vloger_id - 对应用户表id,vlog视频发布者
90 | */
91 | public String getVlogerId() {
92 | return vlogerId;
93 | }
94 |
95 | /**
96 | * 设置对应用户表id,vlog视频发布者
97 | *
98 | * @param vlogerId 对应用户表id,vlog视频发布者
99 | */
100 | public void setVlogerId(String vlogerId) {
101 | this.vlogerId = vlogerId;
102 | }
103 |
104 | /**
105 | * 获取视频播放地址
106 | *
107 | * @return url - 视频播放地址
108 | */
109 | public String getUrl() {
110 | return url;
111 | }
112 |
113 | /**
114 | * 设置视频播放地址
115 | *
116 | * @param url 视频播放地址
117 | */
118 | public void setUrl(String url) {
119 | this.url = url;
120 | }
121 |
122 | /**
123 | * 获取视频封面
124 | *
125 | * @return cover - 视频封面
126 | */
127 | public String getCover() {
128 | return cover;
129 | }
130 |
131 | /**
132 | * 设置视频封面
133 | *
134 | * @param cover 视频封面
135 | */
136 | public void setCover(String cover) {
137 | this.cover = cover;
138 | }
139 |
140 | /**
141 | * 获取视频标题,可以为空
142 | *
143 | * @return title - 视频标题,可以为空
144 | */
145 | public String getTitle() {
146 | return title;
147 | }
148 |
149 | /**
150 | * 设置视频标题,可以为空
151 | *
152 | * @param title 视频标题,可以为空
153 | */
154 | public void setTitle(String title) {
155 | this.title = title;
156 | }
157 |
158 | /**
159 | * 获取视频width
160 | *
161 | * @return width - 视频width
162 | */
163 | public Integer getWidth() {
164 | return width;
165 | }
166 |
167 | /**
168 | * 设置视频width
169 | *
170 | * @param width 视频width
171 | */
172 | public void setWidth(Integer width) {
173 | this.width = width;
174 | }
175 |
176 | /**
177 | * 获取视频height
178 | *
179 | * @return height - 视频height
180 | */
181 | public Integer getHeight() {
182 | return height;
183 | }
184 |
185 | /**
186 | * 设置视频height
187 | *
188 | * @param height 视频height
189 | */
190 | public void setHeight(Integer height) {
191 | this.height = height;
192 | }
193 |
194 | /**
195 | * 获取点赞总数
196 | *
197 | * @return like_counts - 点赞总数
198 | */
199 | public Integer getLikeCounts() {
200 | return likeCounts;
201 | }
202 |
203 | /**
204 | * 设置点赞总数
205 | *
206 | * @param likeCounts 点赞总数
207 | */
208 | public void setLikeCounts(Integer likeCounts) {
209 | this.likeCounts = likeCounts;
210 | }
211 |
212 | /**
213 | * 获取评论总数
214 | *
215 | * @return comments_counts - 评论总数
216 | */
217 | public Integer getCommentsCounts() {
218 | return commentsCounts;
219 | }
220 |
221 | /**
222 | * 设置评论总数
223 | *
224 | * @param commentsCounts 评论总数
225 | */
226 | public void setCommentsCounts(Integer commentsCounts) {
227 | this.commentsCounts = commentsCounts;
228 | }
229 |
230 | /**
231 | * 获取是否私密,用户可以设置私密,如此可以不公开给比人看
232 | *
233 | * @return is_private - 是否私密,用户可以设置私密,如此可以不公开给比人看
234 | */
235 | public Integer getIsPrivate() {
236 | return isPrivate;
237 | }
238 |
239 | /**
240 | * 设置是否私密,用户可以设置私密,如此可以不公开给比人看
241 | *
242 | * @param isPrivate 是否私密,用户可以设置私密,如此可以不公开给比人看
243 | */
244 | public void setIsPrivate(Integer isPrivate) {
245 | this.isPrivate = isPrivate;
246 | }
247 |
248 | /**
249 | * 获取创建时间 创建时间
250 | *
251 | * @return created_time - 创建时间 创建时间
252 | */
253 | public Date getCreatedTime() {
254 | return createdTime;
255 | }
256 |
257 | /**
258 | * 设置创建时间 创建时间
259 | *
260 | * @param createdTime 创建时间 创建时间
261 | */
262 | public void setCreatedTime(Date createdTime) {
263 | this.createdTime = createdTime;
264 | }
265 |
266 | /**
267 | * 获取更新时间 更新时间
268 | *
269 | * @return updated_time - 更新时间 更新时间
270 | */
271 | public Date getUpdatedTime() {
272 | return updatedTime;
273 | }
274 |
275 | /**
276 | * 设置更新时间 更新时间
277 | *
278 | * @param updatedTime 更新时间 更新时间
279 | */
280 | public void setUpdatedTime(Date updatedTime) {
281 | this.updatedTime = updatedTime;
282 | }
283 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/vo/CommentVO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | import java.util.Date;
9 |
10 | @Data
11 | @AllArgsConstructor
12 | @NoArgsConstructor
13 | @ToString
14 | public class CommentVO {
15 | private String id;
16 | private String commentId;
17 | private String vlogerId;
18 | private String fatherCommentId;
19 | private String vlogId;
20 | private String commentUserId;
21 | private String commentUserNickname;
22 | private String commentUserFace;
23 | private String content;
24 | private Integer likeCounts;
25 | private String replyedUserNickname;
26 | private Date createTime;
27 | private Integer isLike = 0;
28 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/vo/FansVO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @ToString
12 | public class FansVO {
13 | private String fanId;
14 | private String nickname;
15 | private String face;
16 | private boolean isFriend = false;
17 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/vo/IndexVlogVO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @ToString
12 | public class IndexVlogVO {
13 | private String vlogId;
14 | private String vlogerId;
15 | private String vlogerFace;
16 | private String vlogerName;
17 | private String content;
18 | private String url;
19 | private String cover;
20 | private Integer width;
21 | private Integer height;
22 | private Integer likeCounts;
23 | private Integer commentsCounts;
24 | private Integer isPrivate;
25 | private boolean isPlay = false;
26 | private boolean doIFollowVloger = false;
27 | private boolean doILikeThisVlog = false;
28 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/vo/UsersVO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | import javax.persistence.Column;
9 | import javax.persistence.Id;
10 | import javax.validation.constraints.NotBlank;
11 | import java.util.Date;
12 |
13 | @Data
14 | @AllArgsConstructor
15 | @NoArgsConstructor
16 | @ToString
17 | public class UsersVO {
18 | private String id;
19 | private String mobile;
20 | private String nickname;
21 | private String imoocNum;
22 | private String face;
23 | private Integer sex;
24 | private Date birthday;
25 | private String country;
26 | private String province;
27 | private String city;
28 | private String district;
29 | private String description;
30 | private String bgImg;
31 | private Integer canImoocNumBeUpdated;
32 | private Date createdTime;
33 | private Date updatedTime;
34 |
35 | private String userToken; // 用户token,传递给前端
36 |
37 | private Integer myFollowsCounts; //我关注的
38 | private Integer myFansCounts; //我的粉丝数量
39 | //private Integer myLikedVlogCounts;
40 | private Integer totalLikeMeCounts;
41 |
42 | }
--------------------------------------------------------------------------------
/book-model/src/main/java/com/imooc/vo/VlogerVO.java:
--------------------------------------------------------------------------------
1 | package com.imooc.vo;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 | import lombok.ToString;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @ToString
12 | public class VlogerVO {
13 | private String vlogerId;
14 | private String nickname;
15 | private String face;
16 | private boolean isFollowed = true;
17 | }
--------------------------------------------------------------------------------
/book-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.imooc
8 | imooc-red-book-dev
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | book-service
14 |
15 |
16 | 8
17 | 8
18 | UTF-8
19 |
20 |
21 |
22 |
23 | com.imooc
24 | book-mapper
25 | 1.0-SNAPSHOT
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/base/BaseInfoProperties.java:
--------------------------------------------------------------------------------
1 | package com.imooc.base;
2 |
3 | import com.github.pagehelper.PageInfo;
4 | //import com.imooc.utils.PagedGridResult;
5 | import com.imooc.utils.PagedGridResult;
6 | import com.imooc.utils.RedisOperator;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 |
9 | import java.util.List;
10 |
11 | public class BaseInfoProperties {
12 |
13 | @Autowired
14 | public RedisOperator redis;
15 |
16 | public static final Integer COMMON_START_PAGE = 1;
17 | public static final Integer COMMON_START_PAGE_ZERO = 0;
18 | public static final Integer COMMON_PAGE_SIZE = 10;
19 |
20 | public static final String MOBILE_SMSCODE = "mobile:smscode";
21 | public static final String REDIS_USER_TOKEN = "redis_user_token";
22 | public static final String REDIS_USER_INFO = "redis_user_info";
23 |
24 | // 短视频的评论总数
25 | public static final String REDIS_VLOG_COMMENT_COUNTS = "redis_vlog_comment_counts";
26 | // 短视频的评论喜欢数量
27 | public static final String REDIS_VLOG_COMMENT_LIKED_COUNTS = "redis_vlog_comment_liked_counts";
28 | // 用户点赞评论
29 | public static final String REDIS_USER_LIKE_COMMENT = "redis_user_like_comment";
30 |
31 |
32 | //我的关注总数
33 | public static final String REDIS_MY_FOLLOWS_COUNTS = "redis_my_follows_counts";
34 | // 我的粉丝总数
35 | public static final String REDIS_MY_FANS_COUNTS = "redis_my_fans_counts";
36 |
37 | // 视频和发布者获赞数
38 | public static final String REDIS_VLOG_BE_LIKED_COUNTS = "redis_vlog_be_liked_counts";
39 | public static final String REDIS_VLOGER_BE_LIKED_COUNTS = "redis_vloger_be_liked_counts";
40 |
41 | // 博主和粉丝的关联关系,用于判断他们是否互粉
42 | public static final String REDIS_FANS_AND_VLOGGER_RELATIONSHIP = "redis_fans_and_vlogger_relationship";
43 |
44 | // 用户是否喜欢/点赞视频,取代数据库的关联关系,1:喜欢,0:不喜欢(默认) redis_user_like_vlog:{userId}:{vlogId}
45 | public static final String REDIS_USER_LIKE_VLOG = "redis_user_like_vlog";
46 |
47 | public PagedGridResult setterPagedGrid(List> list, Integer page) {
48 | PageInfo> pageList = new PageInfo<>(list);
49 | PagedGridResult gridResult = new PagedGridResult();
50 | gridResult.setRows(list);
51 | gridResult.setPage(page);
52 | gridResult.setRecords(pageList.getTotal());
53 | gridResult.setTotal(pageList.getPages());
54 | return gridResult;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/base/RabbitMQConfig.java:
--------------------------------------------------------------------------------
1 | package com.imooc.base;//package com.imooc;
2 |
3 | import org.springframework.amqp.core.*;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | @Configuration
9 | public class RabbitMQConfig {
10 |
11 | /**
12 | * 根据模型编写代码:
13 | * 1. 定义交换机
14 | * 2. 定义队列
15 | * 3. 创建交换机
16 | * 4. 创建队列
17 | * 5. 队列和交换机的绑定
18 | */
19 |
20 | public static final String EXCHANGE_MSG = "exchange_msg";
21 |
22 | public static final String QUEUE_SYS_MSG = "queue_sys_msg";
23 |
24 | @Bean(EXCHANGE_MSG)
25 | public Exchange exchange() {
26 | return ExchangeBuilder // 构建交换机
27 | .topicExchange(EXCHANGE_MSG) // 使用topic类型,参考:https://www.rabbitmq.com/getstarted.html
28 | .durable(true) // 设置持久化,重启mq后依然存在
29 | .build();
30 | }
31 |
32 | @Bean(QUEUE_SYS_MSG)
33 | public Queue queue() {
34 | return new Queue(QUEUE_SYS_MSG);
35 | }
36 |
37 | @Bean
38 | public Binding binding(@Qualifier(EXCHANGE_MSG) Exchange exchange,
39 | @Qualifier(QUEUE_SYS_MSG) Queue queue) {
40 |
41 | return BindingBuilder
42 | .bind(queue)
43 | .to(exchange)
44 | .with("sys.msg.*") // 定义路由规则(requestMapping)
45 | .noargs();
46 |
47 | // FIXME: * 和 # 分别代表什么意思?
48 | }
49 |
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/CommentService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service;
2 |
3 | import com.imooc.bo.CommentBO;
4 | import com.imooc.pojo.Comment;
5 | import com.imooc.pojo.Vlog;
6 | import com.imooc.utils.PagedGridResult;
7 | import com.imooc.vo.CommentVO;
8 |
9 | public interface CommentService {
10 |
11 | /**
12 | * 发表评论
13 | */
14 | public CommentVO createComment(CommentBO commentBO);
15 |
16 | /**
17 | * 查询评论的列表
18 | */
19 | public PagedGridResult queryVlogComments(String vlogId,
20 | String userId,
21 | Integer page,
22 | Integer pageSize);
23 |
24 | /**
25 | * 删除评论
26 | */
27 | public void deleteComment(String commentUserId,
28 | String commentId,
29 | String vlogId);
30 |
31 | /**
32 | * 根据主键查询comment
33 | */
34 | public Comment getComment(String id);
35 | }
36 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/FansService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service;
2 |
3 | import com.imooc.utils.PagedGridResult;
4 |
5 | public interface FansService {
6 |
7 | /**
8 | * 关注
9 | */
10 | public void doFollow(String myId, String vlogerId);
11 |
12 | /**
13 | * 取关
14 | */
15 | public void doCancel(String myId, String vlogerId);
16 |
17 | /**
18 | * 查询用户是否关注博主
19 | */
20 | public boolean queryDoIFollowVloger(String myId, String vlogerId);
21 |
22 | /**
23 | * 查询我关注的博主列表
24 | */
25 | public PagedGridResult queryMyFollows(String myId,
26 | Integer page,
27 | Integer pageSize);
28 |
29 | /**
30 | * 查询我的粉丝列表
31 | */
32 | public PagedGridResult queryMyFans(String myId,
33 | Integer page,
34 | Integer pageSize);
35 | }
36 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/MsgService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service;
2 |
3 | import com.imooc.bo.VlogBO;
4 | import com.imooc.mo.MessageMO;
5 |
6 | import javax.validation.constraints.Max;
7 | import java.util.List;
8 | import java.util.Map;
9 |
10 | public interface MsgService {
11 |
12 | /**
13 | * 创建消息
14 | */
15 | public void createMsg(String fromUserId,
16 | String toUserId,
17 | Integer type,
18 | Map msgContent);
19 |
20 | /**
21 | * 查询消息列表
22 | */
23 | public List queryList(String toUserId,
24 | Integer page,
25 | Integer pageSize);
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service;
2 |
3 | import com.imooc.bo.UpdatedUserBO;
4 | import com.imooc.pojo.Users;
5 |
6 | /**
7 | * @author vercen
8 | * @version 1.0
9 | * @date 2023/5/25 21:02
10 | */
11 | public interface UserService {
12 | /**
13 | * 判断用户是否存在,如果存在则返回用户信息
14 | */
15 | public Users queryMobileIsExist(String mobile);
16 |
17 |
18 | /**
19 | * 创建用户信息,并且返回用户对象
20 | */
21 | public Users createUser(String mobile);
22 |
23 | /**
24 | * 根据用户主键查询用户信息
25 | */
26 | public Users getUser(String userId);
27 |
28 | /**
29 | * 用户信息修改
30 | */
31 | public Users updateUserInfo(UpdatedUserBO updatedUserBO);
32 |
33 | /**
34 | * 用户信息修改
35 | */
36 | public Users updateUserInfo(UpdatedUserBO updatedUserBO, Integer type);
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/VlogService.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service;
2 |
3 | import com.imooc.bo.VlogBO;
4 | import com.imooc.pojo.Vlog;
5 | import com.imooc.utils.PagedGridResult;
6 | import com.imooc.vo.IndexVlogVO;
7 |
8 | public interface VlogService {
9 |
10 | /**
11 | * 新增vlog视频
12 | */
13 | public void createVlog(VlogBO vlogBO);
14 |
15 | /**
16 | * 查询首页/搜索的vlog列表
17 | */
18 | public PagedGridResult getIndexVlogList(String userId,
19 | String search,
20 | Integer page,
21 | Integer pageSize);
22 |
23 | /**
24 | * 根据视频主键查询vlog
25 | */
26 | public IndexVlogVO getVlogDetailById(String userId, String vlogId);
27 |
28 | /**
29 | * 用户把视频改为公开/私密的视频
30 | */
31 | public void changeToPrivateOrPublic(String userId,
32 | String vlogId,
33 | Integer yesOrNo);
34 |
35 | /**
36 | * 查询用的公开/私密的视频列表
37 | */
38 | public PagedGridResult queryMyVlogList(String userId,
39 | Integer page,
40 | Integer pageSize,
41 | Integer yesOrNo);
42 |
43 | /**
44 | * 用户点赞/喜欢视频
45 | */
46 | public void userLikeVlog(String userId, String vlogId);
47 |
48 | /**
49 | * 用户取消点赞/喜欢视频
50 | */
51 | public void userUnLikeVlog(String userId, String vlogId);
52 |
53 | /**
54 | * 获得用户点赞视频的总数
55 | */
56 | public Integer getVlogBeLikedCounts(String vlogId);
57 |
58 | /**
59 | * 查询用户点赞过的短视频
60 | */
61 | public PagedGridResult getMyLikedVlogList(String userId,
62 | Integer page,
63 | Integer pageSize);
64 |
65 | /**
66 | * 查询用户关注的博主发布的短视频列表
67 | */
68 | public PagedGridResult getMyFollowVlogList(String myId,
69 | Integer page,
70 | Integer pageSize);
71 |
72 | /**
73 | * 查询朋友发布的短视频列表
74 | */
75 | public PagedGridResult getMyFriendVlogList(String myId,
76 | Integer page,
77 | Integer pageSize);
78 |
79 | /**
80 | * 根据主键查询vlog
81 | */
82 | public Vlog getVlog(String id);
83 |
84 | /**
85 | * 把counts输入数据库
86 | */
87 | public void flushCounts(String vlogId, Integer counts);
88 | // /**
89 | // * 查询首页/搜索的vlog列表
90 | // */
91 | // public PagedGridResult getIndexVlogList(String userId,
92 | // String search,
93 | // Integer page,
94 | // Integer pageSize);
95 | //
96 | // /**
97 | // * 根据视频主键查询vlog
98 | // */
99 | // public IndexVlogVO getVlogDetailById(String userId, String vlogId);
100 | //
101 | // /**
102 | // * 用户把视频改为公开/私密的视频
103 | // */
104 | // public void changeToPrivateOrPublic(String userId,
105 | // String vlogId,
106 | // Integer yesOrNo);
107 | //
108 | // /**
109 | // * 查询用的公开/私密的视频列表
110 | // */
111 | // public PagedGridResult queryMyVlogList(String userId,
112 | // Integer page,
113 | // Integer pageSize,
114 | // Integer yesOrNo);
115 | //
116 | // /**
117 | // * 用户点赞/喜欢视频
118 | // */
119 | // public void userLikeVlog(String userId, String vlogId);
120 | //
121 | // /**
122 | // * 用户取消点赞/喜欢视频
123 | // */
124 | // public void userUnLikeVlog(String userId, String vlogId);
125 | //
126 | // /**
127 | // * 获得用户点赞视频的总数
128 | // */
129 | // public Integer getVlogBeLikedCounts(String vlogId);
130 | //
131 | // /**
132 | // * 查询用户点赞过的短视频
133 | // */
134 | // public PagedGridResult getMyLikedVlogList(String userId,
135 | // Integer page,
136 | // Integer pageSize);
137 | //
138 | // /**
139 | // * 查询用户关注的博主发布的短视频列表
140 | // */
141 | // public PagedGridResult getMyFollowVlogList(String myId,
142 | // Integer page,
143 | // Integer pageSize);
144 | //
145 | // /**
146 | // * 查询朋友发布的短视频列表
147 | // */
148 | // public PagedGridResult getMyFriendVlogList(String myId,
149 | // Integer page,
150 | // Integer pageSize);
151 | //
152 | // /**
153 | // * 根据主键查询vlog
154 | // */
155 | // public Vlog getVlog(String id);
156 | }
157 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/impl/CommentServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.github.pagehelper.PageHelper;
4 | import com.imooc.base.BaseInfoProperties;
5 | import com.imooc.bo.CommentBO;
6 | import com.imooc.enums.MessageEnum;
7 | import com.imooc.enums.YesOrNo;
8 | import com.imooc.mapper.CommentMapper;
9 | import com.imooc.mapper.CommentMapperCustom;
10 | import com.imooc.pojo.Comment;
11 | import com.imooc.pojo.Vlog;
12 | import com.imooc.service.CommentService;
13 | import com.imooc.service.MsgService;
14 | import com.imooc.service.VlogService;
15 | import com.imooc.utils.PagedGridResult;
16 | import com.imooc.vo.CommentVO;
17 | import org.apache.commons.lang3.StringUtils;
18 | import org.n3r.idworker.Sid;
19 | import org.springframework.beans.BeanUtils;
20 | import org.springframework.beans.factory.annotation.Autowired;
21 | import org.springframework.stereotype.Service;
22 |
23 | import java.util.Date;
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | @Service
29 | public class CommentServiceImpl extends BaseInfoProperties implements CommentService {
30 | //
31 | @Autowired
32 | private CommentMapper commentMapper;
33 | //
34 | @Autowired
35 | private CommentMapperCustom commentMapperCustom;
36 | //
37 | @Autowired
38 | private VlogService vlogService;
39 | @Autowired
40 | private MsgService msgService;
41 | //
42 | @Autowired
43 | private Sid sid;
44 | //
45 | @Override
46 | public CommentVO createComment(CommentBO commentBO) {
47 |
48 | String commentId = sid.nextShort();
49 |
50 | Comment comment = new Comment();
51 | comment.setId(commentId);
52 |
53 | comment.setVlogId(commentBO.getVlogId());
54 | comment.setVlogerId(commentBO.getVlogerId());
55 |
56 | comment.setCommentUserId(commentBO.getCommentUserId());
57 | comment.setFatherCommentId(commentBO.getFatherCommentId());
58 | comment.setContent(commentBO.getContent());
59 |
60 | comment.setLikeCounts(0);
61 | comment.setCreateTime(new Date());
62 |
63 | commentMapper.insert(comment);
64 |
65 | // redis操作放在service中,评论总数的累加
66 | redis.increment(REDIS_VLOG_COMMENT_COUNTS + ":" + commentBO.getVlogId(), 1);
67 |
68 | // 留言后的最新评论需要返回给前端进行展示
69 | CommentVO commentVO = new CommentVO();
70 | BeanUtils.copyProperties(comment, commentVO);
71 |
72 |
73 |
74 | // 系统消息:评论/回复
75 | Vlog vlog = vlogService.getVlog(commentBO.getVlogId());
76 | Map msgContent = new HashMap();
77 | msgContent.put("vlogId", vlog.getId());
78 | msgContent.put("vlogCover", vlog.getCover());
79 | msgContent.put("commentId", commentId);
80 | msgContent.put("commentContent", commentBO.getContent());
81 | Integer type = MessageEnum.COMMENT_VLOG.type;
82 | if (StringUtils.isNotBlank(commentBO.getFatherCommentId()) &&
83 | !commentBO.getFatherCommentId().equalsIgnoreCase("0") ) {
84 | type = MessageEnum.REPLY_YOU.type;
85 | }
86 |
87 | msgService.createMsg(commentBO.getCommentUserId(),
88 | commentBO.getVlogerId(),
89 | type,
90 | msgContent);
91 | //
92 | //
93 | //
94 | return commentVO;
95 | }
96 | //
97 | @Override
98 | public PagedGridResult queryVlogComments(String vlogId,
99 | String userId,
100 | Integer page,
101 | Integer pageSize) {
102 |
103 | Map map = new HashMap<>();
104 | map.put("vlogId", vlogId);
105 |
106 | PageHelper.startPage(page, pageSize);
107 |
108 | List list = commentMapperCustom.getCommentList(map);
109 |
110 | for (CommentVO cv:list) {
111 | String commentId = cv.getCommentId();
112 |
113 | // 当前短视频的某个评论的点赞总数
114 | String countsStr = redis.getHashValue(REDIS_VLOG_COMMENT_LIKED_COUNTS, commentId);
115 | Integer counts = 0;
116 | if (StringUtils.isNotBlank(countsStr)) {
117 | counts = Integer.valueOf(countsStr);
118 | }
119 | cv.setLikeCounts(counts);
120 |
121 | // 判断当前用户是否点赞过该评论
122 | String doILike = redis.hget(REDIS_USER_LIKE_COMMENT, userId + ":" + commentId);
123 | if (StringUtils.isNotBlank(doILike) && doILike.equalsIgnoreCase("1")) {
124 | cv.setIsLike(YesOrNo.YES.type);
125 | }
126 | }
127 |
128 | return setterPagedGrid(list, page);
129 | }
130 |
131 | @Override
132 | public void deleteComment(String commentUserId,
133 | String commentId,
134 | String vlogId) {
135 |
136 | Comment pendingDelete = new Comment();
137 | pendingDelete.setId(commentId);
138 | pendingDelete.setCommentUserId(commentUserId);
139 |
140 | commentMapper.delete(pendingDelete);
141 |
142 | // 评论总数的累减
143 | redis.decrement(REDIS_VLOG_COMMENT_COUNTS + ":" + vlogId, 1);
144 | }
145 |
146 | @Override
147 | public Comment getComment(String id) {
148 | return commentMapper.selectByPrimaryKey(id);
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/impl/FansServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.github.pagehelper.PageHelper;
4 | import com.imooc.base.BaseInfoProperties;
5 | import com.imooc.base.RabbitMQConfig;
6 | import com.imooc.enums.MessageEnum;
7 | import com.imooc.enums.YesOrNo;
8 | import com.imooc.mapper.FansMapper;
9 | import com.imooc.mapper.FansMapperCustom;
10 | import com.imooc.mo.MessageMO;
11 | import com.imooc.pojo.Fans;
12 | import com.imooc.service.FansService;
13 | import com.imooc.service.MsgService;
14 | import com.imooc.utils.JsonUtils;
15 | import com.imooc.utils.PagedGridResult;
16 | import com.imooc.vo.FansVO;
17 | import com.imooc.vo.VlogerVO;
18 | import org.apache.commons.lang3.StringUtils;
19 | import org.n3r.idworker.Sid;
20 | import org.springframework.amqp.rabbit.core.RabbitTemplate;
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.stereotype.Service;
23 | import org.springframework.transaction.annotation.Transactional;
24 | import tk.mybatis.mapper.entity.Example;
25 |
26 | import java.util.HashMap;
27 | import java.util.List;
28 | import java.util.Map;
29 |
30 | @Service
31 | public class FansServiceImpl extends BaseInfoProperties implements FansService {
32 |
33 | @Autowired
34 | private FansMapper fansMapper;
35 | @Autowired
36 | private FansMapperCustom fansMapperCustom;
37 | //
38 | @Autowired
39 | private MsgService msgService;
40 |
41 | @Autowired
42 | public RabbitTemplate rabbitTemplate;
43 | //
44 | @Autowired
45 | private Sid sid;
46 | //
47 | @Transactional
48 | @Override
49 | public void doFollow(String myId, String vlogerId) {
50 |
51 | String fid = sid.nextShort();
52 |
53 | Fans fans = new Fans();
54 | fans.setId(fid);
55 | fans.setFanId(myId);
56 | fans.setVlogerId(vlogerId);
57 |
58 | // 判断对方是否关注我,如果关注我,那么双方都要互为朋友关系
59 | Fans vloger = queryFansRelationship(vlogerId, myId);
60 | if (vloger != null) {
61 | fans.setIsFanFriendOfMine(YesOrNo.YES.type);
62 |
63 | vloger.setIsFanFriendOfMine(YesOrNo.YES.type);
64 | fansMapper.updateByPrimaryKeySelective(vloger);
65 | } else {
66 | fans.setIsFanFriendOfMine(YesOrNo.NO.type);
67 | }
68 |
69 | fansMapper.insert(fans);
70 |
71 |
72 | // 系统消息:关注
73 | // msgService.createMsg(myId, vlogerId, MessageEnum.FOLLOW_YOU.type, null);
74 | //优化使用mQEXCHANGE_MSG
75 |
76 | MessageMO messageMO = new MessageMO();
77 |
78 | messageMO.setFromUserId(myId);
79 | messageMO.setToUserId(vlogerId);
80 | rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_MSG, "sys.msg."+ MessageEnum.FOLLOW_YOU.enValue, JsonUtils.objectToJson(messageMO));
81 | }
82 |
83 | public Fans queryFansRelationship(String fanId, String vlogerId) {
84 | Example example = new Example(Fans.class);
85 | Example.Criteria criteria = example.createCriteria();
86 | criteria.andEqualTo("vlogerId", vlogerId);
87 | criteria.andEqualTo("fanId", fanId);
88 |
89 | List list = fansMapper.selectByExample(example);
90 |
91 | Fans fan = null;
92 | if (list != null && list.size() > 0 && !list.isEmpty()) {
93 | fan = (Fans)list.get(0);
94 | }
95 |
96 | return fan;
97 | }
98 |
99 | @Transactional
100 | @Override
101 | public void doCancel(String myId, String vlogerId) {
102 |
103 | // 判断我们是否朋友关系,如果是,则需要取消双方的关系
104 | Fans fan = queryFansRelationship(myId, vlogerId);
105 | if (fan != null && fan.getIsFanFriendOfMine() == YesOrNo.YES.type) {
106 | // 抹除双方的朋友关系,自己的关系删除即可
107 | Fans pendingFan = queryFansRelationship(vlogerId, myId);
108 | pendingFan.setIsFanFriendOfMine(YesOrNo.NO.type);
109 | fansMapper.updateByPrimaryKeySelective(pendingFan);
110 | }
111 |
112 | // 删除自己的关注关联表记录
113 | fansMapper.delete(fan);
114 | }
115 |
116 | @Override
117 | public boolean queryDoIFollowVloger(String myId, String vlogerId) {
118 | Fans vloger = queryFansRelationship(myId, vlogerId);
119 | return vloger != null;
120 | }
121 |
122 | @Override
123 | public PagedGridResult queryMyFollows(String myId,
124 | Integer page,
125 | Integer pageSize) {
126 | Map map = new HashMap<>();
127 | map.put("myId", myId);
128 |
129 | PageHelper.startPage(page, pageSize);
130 |
131 | List list = fansMapperCustom.queryMyFollows(map);
132 |
133 | return setterPagedGrid(list, page);
134 | }
135 |
136 | @Override
137 | public PagedGridResult queryMyFans(String myId,
138 | Integer page,
139 | Integer pageSize) {
140 |
141 | /**
142 | * <判断粉丝是否是我的朋友(互粉互关)>
143 | * 普通做法:
144 | * 多表关联+嵌套关联查询,这样会违反多表关联的规范,不可取,高并发下回出现性能问题
145 | *
146 | * 常规做法:
147 | * 1. 避免过多的表关联查询,先查询我的粉丝列表,获得fansList
148 | * 2. 判断粉丝关注我,并且我也关注粉丝 -> 循环fansList,获得每一个粉丝,再去数据库查询我是否关注他
149 | * 3. 如果我也关注他(粉丝),说明,我俩互为朋友关系(互关互粉),则标记flag为true,否则false
150 | *
151 | * 高端做法:
152 | * 1. 关注/取关的时候,关联关系保存在redis中,不要依赖数据库
153 | * 2. 数据库查询后,直接循环查询redis,避免第二次循环查询数据库的尴尬局面
154 | */
155 |
156 |
157 | Map map = new HashMap<>();
158 | map.put("myId", myId);
159 |
160 | PageHelper.startPage(page, pageSize);
161 |
162 | List list = fansMapperCustom.queryMyFans(map);
163 |
164 | for (FansVO f : list) {
165 | String relationship = redis.get(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + myId + ":" + f.getFanId());
166 | if (StringUtils.isNotBlank(relationship) && relationship.equalsIgnoreCase("1")) {
167 | f.setFriend(true);
168 | }
169 | }
170 |
171 | return setterPagedGrid(list, page);
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/impl/MsgServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.imooc.base.BaseInfoProperties;
4 | import com.imooc.enums.MessageEnum;
5 | import com.imooc.mo.MessageMO;
6 | import com.imooc.pojo.Users;
7 | import com.imooc.repository.MessageRepository;
8 | import com.imooc.service.MsgService;
9 | import com.imooc.service.UserService;
10 | import org.apache.commons.lang3.StringUtils;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.data.domain.PageRequest;
13 | import org.springframework.data.domain.Pageable;
14 | import org.springframework.data.domain.Sort;
15 | import org.springframework.stereotype.Service;
16 |
17 | import java.util.Date;
18 | import java.util.HashMap;
19 | import java.util.List;
20 | import java.util.Map;
21 |
22 | @Service
23 | public class MsgServiceImpl extends BaseInfoProperties implements MsgService {
24 |
25 | @Autowired
26 | private MessageRepository messageRepository;
27 |
28 | @Autowired
29 | private UserService userService;
30 |
31 | @Override
32 | public void createMsg(String fromUserId,
33 | String toUserId,
34 | Integer type,
35 | Map msgContent) {
36 |
37 | Users fromUser = userService.getUser(fromUserId);
38 |
39 | MessageMO messageMO = new MessageMO();
40 |
41 | messageMO.setFromUserId(fromUserId);
42 | messageMO.setFromNickname(fromUser.getNickname());
43 | messageMO.setFromFace(fromUser.getFace());
44 |
45 | messageMO.setToUserId(toUserId);
46 |
47 | messageMO.setMsgType(type);
48 | if (msgContent != null) {
49 | messageMO.setMsgContent(msgContent);
50 | }
51 |
52 | messageMO.setCreateTime(new Date());
53 |
54 | messageRepository.save(messageMO);
55 | }
56 | //
57 | @Override
58 | public List queryList(String toUserId,
59 | Integer page,
60 | Integer pageSize) {
61 |
62 | Pageable pageable = PageRequest.of(page,
63 | pageSize,
64 | Sort.Direction.DESC,
65 | "createTime");
66 |
67 | List list = messageRepository
68 | .findAllByToUserIdEqualsOrderByCreateTimeDesc(toUserId,
69 | pageable);
70 | for (MessageMO msg : list) {
71 | // 如果类型是关注消息,则需要查询我之前有没有关注过他,用于在前端标记“互粉”“互关”
72 | if (msg.getMsgType() != null && msg.getMsgType() == MessageEnum.FOLLOW_YOU.type) {
73 | Map map = msg.getMsgContent();
74 | if (map == null) {
75 | map = new HashMap();
76 | }
77 |
78 | String relationship = redis.get(REDIS_FANS_AND_VLOGGER_RELATIONSHIP + ":" + msg.getToUserId() + ":" + msg.getFromUserId());
79 | if (StringUtils.isNotBlank(relationship) && relationship.equalsIgnoreCase("1")) {
80 | map.put("isFriend", true);
81 | } else {
82 | map.put("isFriend", false);
83 | }
84 | msg.setMsgContent(map);
85 | }
86 | }
87 | return list;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/book-service/src/main/java/com/imooc/service/impl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.imooc.service.impl;
2 |
3 | import com.imooc.bo.UpdatedUserBO;
4 | import com.imooc.enums.Sex;
5 | import com.imooc.enums.UserInfoModifyType;
6 | import com.imooc.enums.YesOrNo;
7 | import com.imooc.exceptions.GraceException;
8 | import com.imooc.grace.result.ResponseStatusEnum;
9 | import com.imooc.mapper.UsersMapper;
10 | import com.imooc.pojo.Users;
11 | import com.imooc.service.UserService;
12 | import com.imooc.utils.DateUtil;
13 | import com.imooc.utils.DesensitizationUtil;
14 | import org.n3r.idworker.Sid;
15 | import org.springframework.beans.BeanUtils;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.stereotype.Service;
18 | import org.springframework.transaction.annotation.Transactional;
19 | import tk.mybatis.mapper.entity.Example;
20 |
21 | import java.util.Date;
22 |
23 | /**
24 | * @author vercen
25 | * @version 1.0
26 | * @date 2023/5/25 21:02
27 | */
28 | @Service
29 | public class UserServiceImpl implements UserService {
30 | @Autowired
31 | private UsersMapper usersMapper;
32 |
33 | @Autowired
34 | private Sid sid;
35 | private static final String USER_FACE1 = "http://122.152.205.72:88/group1/M00/00/05/CpoxxF6ZUySASMbOAABBAXhjY0Y649.png";
36 |
37 | @Override
38 | public Users queryMobileIsExist(String mobile) {
39 | Example userExample = new Example(Users.class);
40 | Example.Criteria criteria = userExample.createCriteria();
41 | criteria.andEqualTo("mobile", mobile);
42 | Users user = usersMapper.selectOneByExample(userExample);
43 | return user;
44 | }
45 |
46 | @Override
47 | public Users createUser(String mobile) {
48 | // 获得全局唯一主键
49 | String userId = sid.nextShort();
50 |
51 | Users user = new Users();
52 | user.setId(userId);
53 |
54 | user.setMobile(mobile);
55 | user.setNickname("用户:" + DesensitizationUtil.commonDisplay(mobile));
56 | user.setImoocNum("用户:" + DesensitizationUtil.commonDisplay(mobile));
57 | user.setFace(USER_FACE1);
58 |
59 | user.setBirthday(DateUtil.stringToDate("1900-01-01"));
60 | user.setSex(Sex.secret.type);
61 |
62 | user.setCountry("中国");
63 | user.setProvince("");
64 | user.setCity("");
65 | user.setDistrict("");
66 | user.setDescription("这家伙很懒,什么都没留下~");
67 | user.setCanImoocNumBeUpdated(YesOrNo.YES.type);
68 |
69 | user.setCreatedTime(new Date());
70 | user.setUpdatedTime(new Date());
71 |
72 | usersMapper.insert(user);
73 |
74 | return user;
75 | }
76 |
77 | @Override
78 | public Users getUser(String userId) {
79 | Users users = usersMapper.selectByPrimaryKey(userId);
80 | return users;
81 | }
82 |
83 | @Transactional
84 | @Override
85 | public Users updateUserInfo(UpdatedUserBO updatedUserBO) {
86 |
87 | Users users = new Users();
88 | BeanUtils.copyProperties(updatedUserBO, users);
89 | usersMapper.updateByPrimaryKeySelective(users);
90 | return getUser(updatedUserBO.getId());
91 | }
92 |
93 | @Transactional
94 | @Override
95 | public Users updateUserInfo(UpdatedUserBO updatedUserBO, Integer type) {
96 |
97 | Example example = new Example(Users.class);
98 | Example.Criteria criteria = example.createCriteria();
99 | if (type == UserInfoModifyType.NICKNAME.type) {
100 | criteria.andEqualTo("nickname", updatedUserBO.getNickname());
101 | Users user = usersMapper.selectOneByExample(example);
102 | if (user != null) {
103 | GraceException.display(ResponseStatusEnum.USER_INFO_UPDATED_NICKNAME_EXIST_ERROR);
104 | }
105 | }
106 |
107 | if (type == UserInfoModifyType.IMOOCNUM.type) {
108 | criteria.andEqualTo("imoocNum", updatedUserBO.getImoocNum());
109 | Users user = usersMapper.selectOneByExample(example);
110 | if (user != null) {
111 | GraceException.display(ResponseStatusEnum.USER_INFO_UPDATED_NICKNAME_EXIST_ERROR);
112 | }
113 |
114 | Users tempUser = getUser(updatedUserBO.getId());
115 | if (tempUser.getCanImoocNumBeUpdated() == YesOrNo.NO.type) {
116 | GraceException.display(ResponseStatusEnum.USER_INFO_CANT_UPDATED_IMOOCNUM_ERROR);
117 | }
118 |
119 | updatedUserBO.setCanImoocNumBeUpdated(YesOrNo.NO.type);
120 | }
121 |
122 | return updateUserInfo(updatedUserBO);
123 |
124 | }
125 | }
126 |
--------------------------------------------------------------------------------