├── .gitignore ├── LICENSE ├── README.md ├── java_navigation.sql ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── ujuji │ │ └── navigation │ │ ├── NavigationApplication.java │ │ ├── annotation │ │ └── FrequencyLimit.java │ │ ├── config │ │ ├── AsyncConfig.java │ │ ├── CorsDataConfig.java │ │ ├── MybatisPlusConfig.java │ │ ├── ObjectMapperConfig.java │ │ ├── RedisConfig.java │ │ ├── SecurityConfig.java │ │ └── WebConfig.java │ │ ├── controller │ │ ├── BoxController.java │ │ ├── IndexController.java │ │ ├── JobController.java │ │ ├── LeaveMsgController.java │ │ ├── LinkController.java │ │ ├── NoticeController.java │ │ ├── PublicController.java │ │ ├── SearchSiteController.java │ │ ├── SiteConfigController.java │ │ ├── UserController.java │ │ ├── admin │ │ │ ├── AdminBoxController.java │ │ │ ├── AdminCardCodeController.java │ │ │ ├── AdminController.java │ │ │ ├── AdminGlobalSettingController.java │ │ │ ├── AdminLinkController.java │ │ │ ├── AdminMsgController.java │ │ │ └── AdminUserController.java │ │ └── common │ │ │ └── ErrorController.java │ │ ├── core │ │ └── Constants.java │ │ ├── exception │ │ └── MyException.java │ │ ├── filter │ │ ├── JwtAuthenticationTokenFilter.java │ │ └── JwtLoginFilter.java │ │ ├── handler │ │ ├── MyAccessDeniedHandler.java │ │ ├── MyExceptionHandler.java │ │ └── MyMetaObjectHandler.java │ │ ├── interceptor │ │ └── FrequentInterceptor.java │ │ ├── mapper │ │ ├── BoxMapper.java │ │ ├── CardCodeMapper.java │ │ ├── GlobalSettingMapper.java │ │ ├── LeaveMsgMapper.java │ │ ├── LinkMapper.java │ │ ├── NoticeMapper.java │ │ ├── SearchSiteMapper.java │ │ ├── SiteConfigMapper.java │ │ └── UserMapper.java │ │ ├── model │ │ ├── WeatherResp.java │ │ ├── dto │ │ │ ├── BoxDto.java │ │ │ ├── ForgotPassDto.java │ │ │ ├── ImportBoxDto.java │ │ │ ├── InsertCardCodeDto.java │ │ │ ├── LeaveMsgDto.java │ │ │ ├── LinkDto.java │ │ │ ├── PageDto.java │ │ │ ├── ReplyMsgDto.java │ │ │ ├── SearchDto.java │ │ │ ├── SearchLinkDto.java │ │ │ ├── UpdatePassWithCodeDto.java │ │ │ ├── UserDto.java │ │ │ └── VerifyCodeDto.java │ │ ├── entity │ │ │ ├── BaseEntity.java │ │ │ ├── BoxEntity.java │ │ │ ├── CardCodeEntity.java │ │ │ ├── GlobalSettingEntity.java │ │ │ ├── LeaveMsgEntity.java │ │ │ ├── LinkEntity.java │ │ │ ├── NoticeEntity.java │ │ │ ├── SearchSiteEntity.java │ │ │ ├── SiteConfigEntity.java │ │ │ └── UserEntity.java │ │ └── vo │ │ │ ├── BoxVo.java │ │ │ └── UserVo.java │ │ ├── service │ │ ├── AdminBoxService.java │ │ ├── AdminLinkService.java │ │ ├── AdminMsgService.java │ │ ├── AdminUserService.java │ │ ├── BoxService.java │ │ ├── CardCodeService.java │ │ ├── CommonService.java │ │ ├── EmailService.java │ │ ├── GlobalSettingService.java │ │ ├── LeaveMsgService.java │ │ ├── LinkService.java │ │ ├── NoticeService.java │ │ ├── SearchSiteService.java │ │ ├── SiteConfigService.java │ │ ├── UserService.java │ │ └── impl │ │ │ ├── AdminBoxServiceImpl.java │ │ │ ├── AdminLinkServiceImpl.java │ │ │ ├── AdminMsgServiceImpl.java │ │ │ ├── AdminUserServiceImpl.java │ │ │ ├── BoxServiceImpl.java │ │ │ ├── CardCodeServiceImpl.java │ │ │ ├── CommonServiceImpl.java │ │ │ ├── EmailServiceImpl.java │ │ │ ├── GlobalSettingServiceImpl.java │ │ │ ├── LeaveMsgServiceImpl.java │ │ │ ├── LinkServiceImpl.java │ │ │ ├── NoticeServiceImpl.java │ │ │ ├── SearchSiteServiceImpl.java │ │ │ ├── SiteConfigServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── util │ │ ├── AppResult.java │ │ ├── AppResultBuilder.java │ │ ├── AuthInfo.java │ │ ├── HttpUtils.java │ │ ├── JwtUtils.java │ │ ├── MyBeanUtils.java │ │ ├── MyUtils.java │ │ ├── RedisUtils.java │ │ ├── ResultCode.java │ │ ├── SnowflakeIdUtils.java │ │ ├── VerifyCodeCheck.java │ │ └── VerifyCodeUtils.java └── resources │ ├── application.yml │ └── http │ ├── Admin.http │ ├── adminBox.http │ ├── adminCardCode.http │ ├── adminLink.http │ ├── adminMsg.http │ ├── adminSetting.http │ ├── adminUser.http │ ├── box.http │ ├── code.http │ ├── http-client.private.env.json │ ├── leaveMsg.http │ ├── link.http │ ├── notice.http │ ├── public.http │ ├── searchSite.http │ ├── siteConfig.http │ ├── test.http │ └── user.http └── test └── java └── com └── ujuji └── navigation ├── NavigationApplicationTests.java ├── service ├── UserServiceImplTest.java └── impl │ └── EmailServiceImplTest.java └── test └── Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 优聚集 2 | 3 | 2020年初,疫情肆虐,想着以后的规划,结果是毫无规划,可能我就是随波逐流、活在当下的人。 4 | 5 | 6 | 7 | 不管怎么说,我也希望以后能自由职业且能不饿肚子,为此,为了锻炼技能,写了优聚集这个前后端分离的项目。 8 | 9 | 10 | 11 | 这是第一次写较大规模的Vue.js 应用 12 | 13 | 这也是第一次写较大规模的SpringBoot应用 14 | 15 | 16 | 17 | 第一次写,肯定就是巨难看和维护,这点我有自知之明,但是我希望你们不要说出来。我自己知道就行。所以,于2021年我完全从零开始重构了优聚集,前端虽也是Vue.js,但是也是完全重写了。后端用golang重构。不得不说,golang没有像springboot这类似的大统一框架,对于某些方面来说也是好事,我可以完全决定我的后台应用怎么架构。而不是被springboot规定死了:你就该在这个目录写这个东西… 18 | 19 | 20 | 21 | ### 仓库 22 | 23 | 前端仓库(Vue.js):[https://github.com/Xwudao/ujuji_frontend](https://github.com/Xwudao/ujuji_frontend) 24 | 25 | 后端仓库(SpringBoot):[https://github.com/Xwudao/ujuji_backend](https://github.com/Xwudao/ujuji_backend) 26 | 27 | 28 | 29 | ### 声明 30 | 31 | 1、 32 | 33 | 尽管我已经仔细检查过代码,但是不可避免的可能代码中依旧有一些我个人的私密信息,尤其是诸如邮箱密码之类的,如果被发现了,那么请告知我,或者最起码请不要用它干一些危险的事情,谢谢合作。 34 | 35 | 2、 36 | 37 | 因为本套代码之初并不是为了开源而写的,所以对于一些测试中的敏感信息我都是直接写死在代码中的,所以如果您发现了一些私密信息请告知我。 38 | 39 | 40 | 41 | 3、 42 | 43 | 本套代码是基于SpringBoot 2.3.0.RELEASE 44 | 45 | 在当时,应该是最新的版本,但是在2021年来说,可能也许有点旧了,当然,不是很旧。 46 | 47 | 这套代码和现在的优聚集 [https://ujuji.com/](https://ujuji.com/) 有很大区别,因为现在的优聚集网站时是我完全在2021年通过golang重构了的。**所以当您发现这和优聚集https://ujuji.com/ 差别很大时,很正常,因为现有优聚集是重构之后的版本。** 48 | 49 | 50 | 51 | 4、 52 | 53 | 如果您想自己部署优聚集前后端项目,最起码得有以下知识点: 54 | 55 | - 数据库 56 | - Java 57 | - Maven 58 | - SpringBoot(如果不想修改增加功能,也就无伤大雅) 59 | - Vue.js 60 | 61 | 62 | 63 | ### 构建 64 | 65 | 1、修改配置文件 66 | 67 | `src\main\resources\application.yml` 68 | 69 | - 修改服务端口 70 | 71 | ```yml 72 | server: 73 | port: 4037 74 | ``` 75 | 76 | - 修改邮件服务 77 | 78 | ```yml 79 | mail: 80 | host: smtp.domain.com 81 | password: 123456@test 82 | username: ujuji@domain.com 83 | port: 25 84 | ``` 85 | 86 | - 修改数据库信息 87 | 88 | sql文件是:`java_navigation.sql` 89 | 90 | 将其导入数据库并修改如下信息: 91 | 92 | ```yml 93 | spring: 94 | profiles: dev 95 | datasource: 96 | driver-class-name: com.mysql.cj.jdbc.Driver 97 | username: root 98 | password: root 99 | url: jdbc:mysql://localhost:3306/java_navigation?useSSL=false&serverTimezone=UTC 100 | artemis: 101 | port: 4029 102 | ``` 103 | 104 | - Redis信息修改: 105 | 106 | ```yml 107 | redis: 108 | host: 127.0.0.1 109 | password: 110 | port: 6379 111 | lettuce: 112 | pool: 113 | max-active: 8 #最大连接数 114 | max-wait: -1 # 表示未限制 115 | max-idle: 8 # 接池中的最大空闲连接 116 | min-idle: 0 # 最小空闲链接 117 | timeout: 5000 # 超时时间 118 | cache: 119 | redis: 120 | time-to-live: 1m 121 | ``` 122 | 123 | - jwt的`secret`修改: 124 | 125 | ```yml 126 | jwt: 127 | secret: 21312142131232 128 | expiration: 86400000 129 | header: Authorization 130 | prefix: "Bearer " 131 | ``` 132 | 133 | - 跨域设置: 134 | 135 | 当在生产环境中使用是,您还需要修改跨域(当然,如果是开放子站注册的话,下面这个就无所谓了,所以在代码中src\main\java\com\ujuji\navigation\config\WebConfig.java 放行了所有origin) 136 | 137 | ```yml 138 | cors: 139 | origins: 140 | - http://localhost:8080 141 | ``` 142 | 143 | 144 | 145 | 2、当基本配置修改完后,就可以构建了: 146 | 147 | 执行(需要maven环境) 148 | 149 | ```bash 150 | mvn clean package 151 | ``` 152 | 153 | 成功后,会输出: 154 | 155 | ```ini 156 | [INFO] ------------------------------------------------------------------------ 157 | [INFO] BUILD SUCCESS 158 | [INFO] ------------------------------------------------------------------------ 159 | [INFO] Total time: 11.233 s 160 | [INFO] Finished at: 2021-02-06T10:08:10+08:00 161 | [INFO] ------------------------------------------------------------------------ 162 | ``` 163 | 164 | 构建出的产物是: 165 | 166 | `target\navigation-1.0.0.jar` 167 | 168 | 简单来说把他放到服务器中执行 `java -jar navigation-1.0.0.jar`就行 169 | 170 | 171 | 172 | **** 173 | 174 | 175 | 176 | 好了,基本配置的就完了,**懂Java会Spring不用我说都知道怎么弄,不会的,我写再多也是一脸懵** 177 | 178 | 179 | 180 | 之后的通过nginx反向代理到80端口之类的就不多讲了,如果有哪位大神愿意出一个详细的教程,有视频更好。欢迎@我 181 | 182 | 183 | 184 | ### 感谢 185 | 186 | 187 | 188 | 感谢Jetbrains 这家伟大的IDE开发公司,他们的全家桶极其好用 189 | 190 | [https://jetbrains.com/](https://jetbrains.com/) 191 | 192 | 193 | 194 | ### 协议 195 | 196 | 使用本代码请保留前端界面到 https://ujuji.com 的链接 197 | 198 | Apache License 2.0 199 | 200 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.3.0.RELEASE 9 | 10 | 11 | com.ujuji 12 | navigation 13 | 1.0.0 14 | navigation 15 | navigation by springboot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-security 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | com.squareup.okhttp3 32 | okhttp 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-devtools 38 | runtime 39 | true 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | runtime 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-configuration-processor 49 | true 50 | 51 | 52 | org.projectlombok 53 | lombok 54 | true 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-test 59 | test 60 | 61 | 62 | org.junit.vintage 63 | junit-vintage-engine 64 | 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-starter-cache 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-starter-data-redis 75 | 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-starter-mail 80 | 81 | 82 | 83 | org.apache.commons 84 | commons-pool2 85 | 86 | 87 | 88 | com.fasterxml.jackson.datatype 89 | jackson-datatype-jsr310 90 | 91 | 92 | 93 | com.github.whvcse 94 | easy-captcha 95 | 1.6.2 96 | 97 | 98 | org.springframework.security 99 | spring-security-test 100 | test 101 | 102 | 103 | io.jsonwebtoken 104 | jjwt 105 | 0.9.1 106 | 107 | 108 | com.baomidou 109 | mybatis-plus-boot-starter 110 | 3.3.1 111 | 112 | 113 | org.apache.commons 114 | commons-lang3 115 | 116 | 117 | org.springframework.boot 118 | spring-boot-starter-validation 119 | 120 | 121 | 122 | 123 | 124 | 125 | org.springframework.boot 126 | spring-boot-maven-plugin 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/NavigationApplication.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class NavigationApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(NavigationApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/annotation/FrequencyLimit.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | @Documented 6 | @Inherited 7 | @Target(ElementType.METHOD) 8 | @Retention(RetentionPolicy.RUNTIME) 9 | public @interface FrequencyLimit { 10 | int value() default 10; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.scheduling.annotation.AsyncConfigurer; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | 8 | import java.util.concurrent.Executor; 9 | import java.util.concurrent.ThreadPoolExecutor; 10 | 11 | @Configuration 12 | @EnableAsync 13 | public class AsyncConfig implements AsyncConfigurer { 14 | 15 | @Override 16 | public Executor getAsyncExecutor() { 17 | ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 18 | // 线程池维护线程的最少数量 19 | taskExecutor.setCorePoolSize(10); 20 | // 线程池维护线程的最大数量 21 | taskExecutor.setMaxPoolSize(50); 22 | // 缓存队列 23 | taskExecutor.setQueueCapacity(99999); 24 | // 对拒绝task的处理策略 25 | //(1) 默认的ThreadPoolExecutor.AbortPolicy 处理程序遭到拒绝将抛出运行时RejectedExecutionException; 26 | //(2) ThreadPoolExecutor.CallerRunsPolicy 线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度 27 | //(3) ThreadPoolExecutor.DiscardPolicy 不能执行的任务将被删除; 28 | //(4) ThreadPoolExecutor.DiscardOldestPolicy 如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程) 29 | taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 30 | // 线程名前缀,方便排查问题 31 | taskExecutor.setThreadNamePrefix("order-send-thread-"); 32 | // 注意一定要初始化 33 | taskExecutor.initialize(); 34 | 35 | return taskExecutor; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/CorsDataConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import lombok.Data; 4 | import org.springframework.boot.context.properties.ConfigurationProperties; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.List; 8 | 9 | @Configuration 10 | @ConfigurationProperties(prefix = "cors") 11 | @Data 12 | public class CorsDataConfig { 13 | List origins; 14 | List headers; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize; 5 | import com.ujuji.navigation.handler.MyMetaObjectHandler; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | @MapperScan("com.ujuji.navigation.mapper") 12 | public class MybatisPlusConfig { 13 | 14 | @Bean 15 | public MyMetaObjectHandler myMetaObjectHandler() { 16 | return new MyMetaObjectHandler(); 17 | } 18 | 19 | @Bean 20 | public PaginationInterceptor paginationInterceptor() { 21 | PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); 22 | // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false 23 | paginationInterceptor.setOverflow(true); 24 | // 设置最大单页限制数量,默认 500 条,-1 不受限制 25 | paginationInterceptor.setLimit(100); 26 | // 开启 count 的 join 优化,只针对部分 left join 27 | paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); 28 | return paginationInterceptor; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/ObjectMapperConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; 7 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.Primary; 13 | 14 | import java.time.LocalDateTime; 15 | 16 | @Configuration 17 | @Slf4j 18 | public class ObjectMapperConfig { 19 | @Bean 20 | @Primary 21 | @ConditionalOnMissingBean(ObjectMapper.class) 22 | public ObjectMapper objectMapper() { 23 | //注册时间处理Module,处理LocalDateTime等序列化问题 24 | ObjectMapper mapper = new ObjectMapper(); 25 | JavaTimeModule javaTimeModule = new JavaTimeModule(); 26 | javaTimeModule.addSerializer(LocalDateTime.class, new RedisConfig.LocalDateTimeSerializer()); 27 | javaTimeModule.addDeserializer(LocalDateTime.class, new RedisConfig.LocalDateTimeDeserializer()); 28 | mapper.registerModule(javaTimeModule); 29 | 30 | 31 | // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public 32 | mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 33 | // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 34 | mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); 35 | return mapper; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.*; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.cache.CacheManager; 9 | import org.springframework.cache.annotation.CachingConfigurerSupport; 10 | import org.springframework.cache.annotation.EnableCaching; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Configuration; 13 | import org.springframework.data.redis.cache.RedisCacheConfiguration; 14 | import org.springframework.data.redis.cache.RedisCacheManager; 15 | import org.springframework.data.redis.connection.RedisConnectionFactory; 16 | import org.springframework.data.redis.core.RedisTemplate; 17 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 18 | import org.springframework.data.redis.serializer.RedisSerializationContext; 19 | import org.springframework.data.redis.serializer.RedisSerializer; 20 | import org.springframework.data.redis.serializer.StringRedisSerializer; 21 | 22 | import javax.annotation.Resource; 23 | import java.io.IOException; 24 | import java.time.Duration; 25 | import java.time.LocalDateTime; 26 | import java.time.ZoneOffset; 27 | 28 | @Configuration 29 | @EnableCaching 30 | public class RedisConfig extends CachingConfigurerSupport { 31 | 32 | @Value("${spring.cache.redis.time-to-live}") 33 | private final Duration timeToLive = Duration.ZERO; 34 | 35 | @Resource 36 | ObjectMapper objectMapper; 37 | 38 | /** 39 | * 配置Jackson2JsonRedisSerializer序列化策略 40 | */ 41 | private Jackson2JsonRedisSerializer serializer() { 42 | // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 43 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 44 | // ObjectMapper objectMapper = new ObjectMapper();//直接注入就行 45 | 46 | jackson2JsonRedisSerializer.setObjectMapper(objectMapper); 47 | return jackson2JsonRedisSerializer; 48 | } 49 | 50 | @Bean 51 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 52 | RedisTemplate redisTemplate = new RedisTemplate<>(); 53 | redisTemplate.setConnectionFactory(redisConnectionFactory); 54 | // 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 55 | redisTemplate.setValueSerializer(serializer()); 56 | 57 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 58 | // 使用StringRedisSerializer来序列化和反序列化redis的key值 59 | redisTemplate.setKeySerializer(stringRedisSerializer); 60 | 61 | // hash的key也采用String的序列化方式 62 | redisTemplate.setHashKeySerializer(stringRedisSerializer); 63 | // hash的value序列化方式采用jackson 64 | redisTemplate.setHashValueSerializer(serializer()); 65 | redisTemplate.afterPropertiesSet(); 66 | return redisTemplate; 67 | } 68 | 69 | @Bean 70 | public CacheManager cacheManager(RedisConnectionFactory factory) { 71 | RedisSerializer redisSerializer = new StringRedisSerializer(); 72 | // 配置序列化(解决乱码的问题) 73 | RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() 74 | // 缓存有效期 75 | .entryTtl(timeToLive) 76 | // 使用StringRedisSerializer来序列化和反序列化redis的key值 77 | .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) 78 | // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 79 | .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer())) 80 | // 禁用空值 81 | .disableCachingNullValues(); 82 | 83 | return RedisCacheManager.builder(factory) 84 | .cacheDefaults(config) 85 | .build(); 86 | } 87 | 88 | static class LocalDateTimeSerializer extends JsonSerializer { 89 | @Override 90 | public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { 91 | jsonGenerator.writeNumber(localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); 92 | } 93 | } 94 | 95 | static class LocalDateTimeDeserializer extends JsonDeserializer { 96 | @Override 97 | public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 98 | long timestamp = jsonParser.getLongValue(); 99 | return LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8)); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import com.ujuji.navigation.filter.JwtAuthenticationTokenFilter; 4 | import com.ujuji.navigation.filter.JwtLoginFilter; 5 | import com.ujuji.navigation.handler.MyAccessDeniedHandler; 6 | import com.ujuji.navigation.service.UserService; 7 | import com.ujuji.navigation.util.JwtUtils; 8 | import com.ujuji.navigation.util.VerifyCodeCheck; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.http.HttpMethod; 11 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 12 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 14 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 15 | import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; 16 | import org.springframework.security.config.http.SessionCreationPolicy; 17 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 18 | import org.springframework.security.crypto.password.PasswordEncoder; 19 | import org.springframework.security.web.access.AccessDeniedHandler; 20 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 21 | import org.springframework.web.cors.CorsConfiguration; 22 | import org.springframework.web.cors.CorsConfigurationSource; 23 | import org.springframework.web.cors.CorsUtils; 24 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 25 | 26 | import javax.annotation.Resource; 27 | import java.util.Arrays; 28 | import java.util.Collections; 29 | 30 | @EnableWebSecurity 31 | @EnableGlobalMethodSecurity(prePostEnabled = true) 32 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 33 | @Resource 34 | private JwtUtils jwtUtils; 35 | @Resource 36 | private VerifyCodeCheck verifyCodeCheck; 37 | @Resource 38 | private UserService userService; 39 | 40 | 41 | @Bean 42 | public PasswordEncoder passwordEncoder() { 43 | return new BCryptPasswordEncoder(); 44 | } 45 | 46 | @Bean 47 | public AccessDeniedHandler accessDeniedHandler() { 48 | return new MyAccessDeniedHandler(); 49 | } 50 | 51 | @Override 52 | protected void configure(HttpSecurity http) throws Exception { 53 | 54 | ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = http.authorizeRequests(); 55 | //让Spring security放行所有preflight request,也即options预请求要放行 56 | registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll(); 57 | 58 | http.csrf().disable() 59 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 60 | .and() 61 | .authorizeRequests() 62 | .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 63 | .antMatchers("/auth/**", "/").permitAll() 64 | .antMatchers("/public/**", "/job/**").permitAll() 65 | .anyRequest().authenticated() 66 | .and() 67 | // .addFilterBefore(verifyCodeFilter, 68 | // UsernamePasswordAuthenticationFilter.class) 69 | .addFilterBefore(new JwtLoginFilter(authenticationManager(), jwtUtils, verifyCodeCheck), 70 | UsernamePasswordAuthenticationFilter.class) 71 | .addFilterBefore(new JwtAuthenticationTokenFilter(userService, jwtUtils), 72 | UsernamePasswordAuthenticationFilter.class) 73 | .headers().cacheControl(); 74 | http.cors(); 75 | 76 | } 77 | 78 | @Resource 79 | CorsDataConfig corsDataConfig; 80 | 81 | @Bean 82 | public CorsConfigurationSource corsConfigurationSource() { 83 | final CorsConfiguration configuration = new CorsConfiguration(); 84 | //指定允许跨域的请求(*所有):http://wap.ivt.guansichou.com 85 | configuration.setAllowedOrigins(Collections.singletonList("*")); 86 | // configuration.setAllowedOrigins(corsDataConfig.getOrigins()); 87 | configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH")); 88 | // setAllowCredentials(true) is important, otherwise: 89 | // The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. 90 | configuration.setAllowCredentials(true); 91 | // setAllowedHeaders is important! Without it, OPTIONS preflight request 92 | // will fail with 403 Invalid CORS request 93 | configuration.setAllowedHeaders(corsDataConfig.getHeaders()); 94 | final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 95 | source.registerCorsConfiguration("/**", configuration); 96 | return source; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.config; 2 | 3 | import com.ujuji.navigation.interceptor.FrequentInterceptor; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 6 | import org.springframework.web.servlet.config.annotation.EnableWebMvc; 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | import javax.annotation.Resource; 11 | 12 | @Configuration 13 | @EnableWebMvc 14 | public class WebConfig implements WebMvcConfigurer { 15 | 16 | @Resource 17 | CorsDataConfig corsDataConfig; 18 | @Resource 19 | FrequentInterceptor frequentInterceptor; 20 | 21 | @Override 22 | public void addCorsMappings(CorsRegistry registry) { 23 | // String[] strings = new String[corsDataConfig.getOrigins().size()]; 24 | // System.out.println(Arrays.toString(corsDataConfig.getOrigins().toArray(strings))); 25 | registry.addMapping("/**") 26 | .allowedOrigins("*")// 这里也就是公开的cors会用到,其余都是在security里面就拦截了 27 | .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") 28 | .maxAge(3600) 29 | .allowCredentials(true); 30 | } 31 | 32 | @Override 33 | public void addInterceptors(InterceptorRegistry registry) { 34 | // 注册Interceptor 35 | registry.addInterceptor(frequentInterceptor); 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/BoxController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.model.dto.ImportBoxDto; 4 | import com.ujuji.navigation.model.entity.BoxEntity; 5 | import com.ujuji.navigation.model.entity.UserEntity; 6 | import com.ujuji.navigation.service.BoxService; 7 | import com.ujuji.navigation.service.CommonService; 8 | import com.ujuji.navigation.util.AppResult; 9 | import com.ujuji.navigation.util.AppResultBuilder; 10 | import com.ujuji.navigation.util.AuthInfo; 11 | import com.ujuji.navigation.util.ResultCode; 12 | import org.springframework.security.access.prepost.PreAuthorize; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import javax.annotation.Resource; 16 | import javax.validation.Valid; 17 | import java.util.List; 18 | 19 | @RestController 20 | @RequestMapping("user/box") 21 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 22 | public class BoxController { 23 | 24 | @Resource(name = "userBoxService") 25 | BoxService boxService; 26 | @Resource 27 | CommonService commonService; 28 | 29 | @GetMapping("/user/{userId}") 30 | public AppResult> findByUserId(@PathVariable Integer userId) { 31 | UserEntity userInfo = AuthInfo.getUserInfo(); 32 | assert userInfo != null; 33 | List boxes = boxService.findByUserId(userInfo.getId()); 34 | return AppResultBuilder.success(boxes, ResultCode.SUCCESS); 35 | } 36 | 37 | @PostMapping 38 | public AppResult insert(@RequestBody @Valid BoxEntity boxEntity) { 39 | UserEntity userInfo = AuthInfo.getUserInfo(); 40 | boxEntity.setUserId(userInfo.getId());//设置id 41 | boolean b = boxService.insertOne(boxEntity, userInfo); 42 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 43 | AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_FAIL); 44 | } 45 | 46 | @PutMapping 47 | public AppResult update(@RequestBody BoxEntity boxEntity) { 48 | UserEntity userInfo = AuthInfo.getUserInfo(); 49 | boxEntity.setUserId(userInfo.getId());//设置id 50 | boolean b = boxService.updateById(boxEntity, userInfo); 51 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 52 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 53 | } 54 | 55 | @DeleteMapping("/{boxId}") 56 | public AppResult deleteOne(@PathVariable Integer boxId) { 57 | UserEntity userInfo = AuthInfo.getUserInfo(); 58 | boolean b = boxService.deleteById(boxId, userInfo); 59 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 60 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 61 | } 62 | 63 | @PostMapping("/import") 64 | public AppResult importBox(@RequestBody @Valid ImportBoxDto importBoxDto) { 65 | Integer integer = commonService.importBoxAndLinks(importBoxDto); 66 | return integer > 0 ? AppResultBuilder.success(integer, ResultCode.SUCCESS) : 67 | AppResultBuilder.successNoData(ResultCode.IMPORT_FAILED); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @Slf4j 9 | public class IndexController { 10 | @GetMapping("/") 11 | public String index() { 12 | return "hello world"; 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/JobController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | @RequestMapping("job") 9 | public class JobController { 10 | 11 | @GetMapping("/alive") 12 | public String alive() { 13 | return "I am alive"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/LeaveMsgController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.ujuji.navigation.model.dto.ReplyMsgDto; 6 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import com.ujuji.navigation.service.LeaveMsgService; 9 | import com.ujuji.navigation.util.AppResult; 10 | import com.ujuji.navigation.util.AppResultBuilder; 11 | import com.ujuji.navigation.util.AuthInfo; 12 | import com.ujuji.navigation.util.ResultCode; 13 | import org.springframework.security.access.prepost.PreAuthorize; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.annotation.Resource; 17 | import javax.validation.Valid; 18 | 19 | @RestController 20 | @RequestMapping("user/leaveMsg") 21 | 22 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 23 | public class LeaveMsgController { 24 | 25 | @Resource 26 | LeaveMsgService leaveMsgService; 27 | 28 | /*查询留言*/ 29 | @GetMapping("/search") 30 | public AppResult> searchMsg(@RequestParam String kw, @RequestParam int pageNo, 31 | @RequestParam int pageSize) { 32 | final UserEntity userInfo = AuthInfo.getUserInfo(); 33 | final IPage msgByUserIdWithNoFixed = leaveMsgService.searchMsg(kw, userInfo.getId(), pageSize, 34 | pageNo); 35 | return AppResultBuilder.success(msgByUserIdWithNoFixed, ResultCode.SUCCESS); 36 | } 37 | 38 | @GetMapping 39 | public AppResult> findByUserId(@RequestParam int pageSize, @RequestParam int pageNo) { 40 | final UserEntity userInfo = AuthInfo.getUserInfo(); 41 | final IPage byUserId = leaveMsgService.findByUserId(userInfo.getId(), pageSize, pageNo); 42 | return AppResultBuilder.success(byUserId, ResultCode.SUCCESS); 43 | } 44 | 45 | 46 | /*设置留言置顶*/ 47 | @GetMapping("/setFixed/{id}") 48 | public AppResult setFixed(@PathVariable int id) { 49 | final UserEntity userInfo = AuthInfo.getUserInfo(); 50 | final boolean b = leaveMsgService.setFixed(id, userInfo); 51 | return b ? AppResultBuilder.successNoData(ResultCode.SET_MSG_FIXED_SUCCESS) : 52 | AppResultBuilder.fail(ResultCode.SET_MSG_FIXED_FAIL); 53 | } 54 | 55 | /*设置留言已读*/ 56 | @GetMapping("/setRead/{id}") 57 | public AppResult setRead(@PathVariable int id) { 58 | final UserEntity userInfo = AuthInfo.getUserInfo(); 59 | final boolean b = leaveMsgService.setRead(id, userInfo); 60 | return b ? AppResultBuilder.successNoData(ResultCode.SET_MSG_READ_SUCCESS) : 61 | AppResultBuilder.fail(ResultCode.SET_MSG_READ_FAIL); 62 | } 63 | 64 | /*获取留言未读个数*/ 65 | @GetMapping("/getNonReadCount") 66 | public AppResult getNonReadCount() { 67 | final UserEntity userInfo = AuthInfo.getUserInfo(); 68 | final Integer nonReadMsg = leaveMsgService.findNonReadMsg(userInfo.getId()); 69 | return AppResultBuilder.success(nonReadMsg, ResultCode.SUCCESS); 70 | } 71 | 72 | 73 | /*修改*/ 74 | @PutMapping 75 | public AppResult update(@RequestBody @Valid LeaveMsgEntity leaveMsgEntity) { 76 | final boolean b = leaveMsgService.updateOne(leaveMsgEntity); 77 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 78 | AppResultBuilder.fail(ResultCode.SERVICE_UPDATE_FAIL); 79 | } 80 | 81 | /*回复留言*/ 82 | @PutMapping("/reply") 83 | public AppResult reply(@RequestBody @Valid ReplyMsgDto replyMsgDto) { 84 | 85 | LeaveMsgEntity leaveMsgEntity = new LeaveMsgEntity(); 86 | leaveMsgEntity.setReply(replyMsgDto.getReply()); 87 | leaveMsgEntity.setId(replyMsgDto.getId()); 88 | final boolean b = leaveMsgService.updateOne(leaveMsgEntity); 89 | return b ? AppResultBuilder.successNoData(ResultCode.REPLY_MSG_SUCCESS) : 90 | AppResultBuilder.fail(ResultCode.REPLY_MSG_FAIL); 91 | } 92 | 93 | /*删除留言*/ 94 | @DeleteMapping("/{id}") 95 | public AppResult deleteById(@PathVariable int id) { 96 | final UserEntity userInfo = AuthInfo.getUserInfo(); 97 | final boolean b = leaveMsgService.deleteOne(id, userInfo); 98 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 99 | AppResultBuilder.fail(ResultCode.SERVICE_DELETE_FAIL); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/LinkController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.model.entity.LinkEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | import com.ujuji.navigation.service.LinkService; 6 | import com.ujuji.navigation.service.UserService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.AuthInfo; 10 | import com.ujuji.navigation.util.ResultCode; 11 | import org.springframework.security.access.prepost.PreAuthorize; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import javax.annotation.Resource; 15 | import javax.validation.Valid; 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("user/link") 20 | 21 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 22 | public class LinkController { 23 | @Resource(name = "userLinkService") 24 | LinkService linkService; 25 | @Resource 26 | UserService userService; 27 | 28 | @PostMapping 29 | public AppResult insert(@RequestBody @Valid LinkEntity linkEntity) { 30 | UserEntity userInfo = AuthInfo.getUserInfo(); 31 | boolean b = linkService.insert(linkEntity, userInfo); 32 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 33 | AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_FAIL); 34 | } 35 | 36 | @PutMapping 37 | public AppResult update(@RequestBody LinkEntity linkEntity) { 38 | UserEntity userInfo = AuthInfo.getUserInfo(); 39 | boolean b = linkService.update(linkEntity, userInfo); 40 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 41 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 42 | } 43 | 44 | @DeleteMapping("/{linkId}") 45 | public AppResult deleteOne(@PathVariable Integer linkId) { 46 | UserEntity userInfo = AuthInfo.getUserInfo(); 47 | boolean b = linkService.deleteById(linkId, userInfo); 48 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 49 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 50 | } 51 | 52 | @GetMapping("/box/{boxId}") 53 | public AppResult> findByBoxId(@PathVariable Integer boxId) { 54 | UserEntity userInfo = AuthInfo.getUserInfo(); 55 | List boxes = linkService.findAllByBoxId(boxId); 56 | return AppResultBuilder.success(boxes, ResultCode.SUCCESS); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/NoticeController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.annotation.FrequencyLimit; 4 | import com.ujuji.navigation.model.entity.NoticeEntity; 5 | import com.ujuji.navigation.model.entity.UserEntity; 6 | import com.ujuji.navigation.service.NoticeService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.AuthInfo; 10 | import com.ujuji.navigation.util.ResultCode; 11 | import org.springframework.security.access.prepost.PreAuthorize; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import javax.annotation.Resource; 15 | import javax.validation.Valid; 16 | 17 | @RestController 18 | @RequestMapping("user/notice") 19 | 20 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 21 | public class NoticeController { 22 | @Resource 23 | NoticeService noticeService; 24 | 25 | @GetMapping 26 | public AppResult findOne() { 27 | final UserEntity userInfo = AuthInfo.getUserInfo(); 28 | if (userInfo != null) { 29 | final NoticeEntity notice = noticeService.findByUserId(userInfo.getId()); 30 | return AppResultBuilder.success(notice, ResultCode.SUCCESS); 31 | } else { 32 | return AppResultBuilder.fail(ResultCode.SERVICE_QUERY_FAIL); 33 | } 34 | } 35 | 36 | @PostMapping 37 | @FrequencyLimit 38 | public AppResult insert(@RequestBody @Valid NoticeEntity noticeEntity) { 39 | boolean b = noticeService.insertOne(noticeEntity); 40 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 41 | AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_FAIL); 42 | } 43 | 44 | @PutMapping 45 | @FrequencyLimit 46 | public AppResult update(@RequestBody @Valid NoticeEntity noticeEntity) { 47 | UserEntity userInfo = AuthInfo.getUserInfo(); 48 | noticeEntity.setUserId(userInfo.getId()); 49 | boolean b = noticeService.update(noticeEntity, userInfo.getId()); 50 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 51 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/SearchSiteController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.model.entity.SearchSiteEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | import com.ujuji.navigation.service.SearchSiteService; 6 | import com.ujuji.navigation.util.AppResult; 7 | import com.ujuji.navigation.util.AppResultBuilder; 8 | import com.ujuji.navigation.util.AuthInfo; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import javax.validation.Valid; 15 | import java.util.List; 16 | 17 | @RestController 18 | @RequestMapping("user/searchSite") 19 | 20 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 21 | public class SearchSiteController { 22 | 23 | @Resource 24 | SearchSiteService searchSiteService; 25 | 26 | /*查询所属用户的所有*/ 27 | @GetMapping 28 | public AppResult> findAll() { 29 | final UserEntity userInfo = AuthInfo.getUserInfo(); 30 | final List siteServiceByUserId = searchSiteService.findByUserId(userInfo.getId()); 31 | return AppResultBuilder.success(siteServiceByUserId, ResultCode.SUCCESS); 32 | } 33 | 34 | /*插入*/ 35 | @PostMapping 36 | public AppResult insert(@RequestBody @Valid SearchSiteEntity searchSiteEntity) { 37 | final UserEntity userInfo = AuthInfo.getUserInfo(); 38 | searchSiteEntity.setUserId(userInfo.getId()); 39 | final boolean b = searchSiteService.insertOne(searchSiteEntity); 40 | 41 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 42 | AppResultBuilder.fail(ResultCode.SERVICE_INSERT_FAIL); 43 | } 44 | 45 | /*删除留言*/ 46 | @DeleteMapping("/{id}") 47 | public AppResult deleteById(@PathVariable int id) { 48 | final UserEntity userInfo = AuthInfo.getUserInfo(); 49 | final boolean b = searchSiteService.deleteOneById(id, userInfo); 50 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 51 | AppResultBuilder.fail(ResultCode.SERVICE_DELETE_FAIL); 52 | } 53 | 54 | 55 | /*修改*/ 56 | @PutMapping 57 | public AppResult update(@RequestBody @Valid SearchSiteEntity searchSiteEntity) { 58 | final UserEntity userInfo = AuthInfo.getUserInfo(); 59 | final boolean b = searchSiteService.update(searchSiteEntity, userInfo); 60 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 61 | AppResultBuilder.fail(ResultCode.SERVICE_UPDATE_FAIL); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/SiteConfigController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.annotation.FrequencyLimit; 4 | import com.ujuji.navigation.model.entity.SiteConfigEntity; 5 | import com.ujuji.navigation.model.entity.UserEntity; 6 | import com.ujuji.navigation.service.SiteConfigService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.AuthInfo; 10 | import com.ujuji.navigation.util.ResultCode; 11 | import org.springframework.security.access.prepost.PreAuthorize; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import javax.annotation.Resource; 15 | import javax.validation.Valid; 16 | 17 | @RestController 18 | @RequestMapping("user/siteConfig") 19 | 20 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 21 | public class SiteConfigController { 22 | 23 | @Resource 24 | SiteConfigService siteConfigService; 25 | 26 | @PostMapping 27 | public AppResult insertOne(@RequestBody @Valid SiteConfigEntity siteConfigEntity) { 28 | UserEntity userInfo = AuthInfo.getUserInfo(); 29 | siteConfigEntity.setUserId(userInfo.getId()); 30 | boolean insertOne = siteConfigService.insertOne(siteConfigEntity, userInfo); 31 | return insertOne ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 32 | AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_FAIL); 33 | } 34 | 35 | @PutMapping 36 | @FrequencyLimit(10) 37 | public AppResult updateOne(@RequestBody @Valid SiteConfigEntity siteConfigEntity) { 38 | UserEntity userInfo = AuthInfo.getUserInfo(); 39 | siteConfigEntity.setUserId(userInfo.getId()); 40 | boolean b = siteConfigService.updateOne(siteConfigEntity, userInfo); 41 | 42 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 43 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 44 | 45 | } 46 | 47 | @GetMapping("/suffix/available/{suffix}") 48 | public AppResult available(@PathVariable String suffix) { 49 | boolean b = siteConfigService.suffixAvailable(suffix); 50 | return AppResultBuilder.success(b, ResultCode.SUCCESS); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller; 2 | 3 | import com.ujuji.navigation.model.dto.ForgotPassDto; 4 | import com.ujuji.navigation.model.dto.UpdatePassWithCodeDto; 5 | import com.ujuji.navigation.model.dto.UserDto; 6 | import com.ujuji.navigation.model.entity.BoxEntity; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import com.ujuji.navigation.model.vo.UserVo; 9 | import com.ujuji.navigation.service.UserService; 10 | import com.ujuji.navigation.util.AppResult; 11 | import com.ujuji.navigation.util.AppResultBuilder; 12 | import com.ujuji.navigation.util.AuthInfo; 13 | import com.ujuji.navigation.util.ResultCode; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.beans.BeanUtils; 16 | import org.springframework.security.access.prepost.PreAuthorize; 17 | import org.springframework.web.bind.annotation.*; 18 | 19 | import javax.annotation.Resource; 20 | import javax.validation.Valid; 21 | import java.util.List; 22 | 23 | @RestController 24 | 25 | @Slf4j 26 | public class UserController { 27 | @Resource 28 | UserService userService; 29 | 30 | @PostMapping("auth/register") 31 | public AppResult register(@RequestBody @Valid UserDto userDto) { 32 | // userEntity.setAuthority(null);// 不能从前台获取数据 33 | Boolean register = userService.register(userDto); 34 | return register ? AppResultBuilder.successNoData(ResultCode.USER_REGISTER_SUCCESS) : 35 | AppResultBuilder.successNoData(ResultCode.USER_REGISTER_FAIL); 36 | } 37 | 38 | @GetMapping("/auth/info") 39 | public AppResult userInfo() { 40 | UserEntity userInfo = AuthInfo.getUserInfo(); 41 | UserVo userVo = new UserVo(); 42 | assert userInfo != null; 43 | BeanUtils.copyProperties(userInfo, userVo); 44 | return AppResultBuilder.success(userVo, ResultCode.SUCCESS); 45 | } 46 | 47 | // 发送修改密码的邮箱验证 48 | @PostMapping("auth/sendUpdateMail") 49 | public AppResult sendUpdateMail(@RequestBody @Valid ForgotPassDto forgotPassDto) { 50 | boolean b = userService.sendForgotPasswordEmail(forgotPassDto); 51 | return AppResultBuilder.success(b, ResultCode.FIND_PASS_EMAIL_SEND_SUCCESS); 52 | } 53 | 54 | //修改密码 55 | @PostMapping("auth/updatePassWithCode") 56 | public AppResult updatePassWithCode(@RequestBody @Valid UpdatePassWithCodeDto updatePassWithCodeDto) { 57 | log.info("updatePassWithCode ==>> dto ==>> {}", updatePassWithCodeDto.toString()); 58 | boolean b = userService.updatePassWithCode(updatePassWithCodeDto); 59 | return b ? AppResultBuilder.successNoData(ResultCode.USER_PASSWORD_MODIFY_SUCCESS) : 60 | AppResultBuilder.successNoData(ResultCode.USER_PASSWORD_MODIFY_FAIL); 61 | } 62 | 63 | @PostMapping("/auth/token") 64 | public AppResult genToken() { 65 | String token = userService.generateAccessToken(); 66 | log.info("gen token: {}", token); 67 | UserEntity userInfo = AuthInfo.getUserInfo(); 68 | boolean b = userService.updateToken(userInfo, token); 69 | return b ? AppResultBuilder.success(token, ResultCode.GENERATE_TOKEN_SUCCESS) : 70 | AppResultBuilder.fail(ResultCode.GENERATE_TOKEN_FAIL); 71 | 72 | } 73 | 74 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 75 | @PostMapping("user/updatePassword") 76 | public AppResult updatePassword(@RequestParam String oldPass, @RequestParam String newPass) { 77 | UserEntity userInfo = AuthInfo.getUserInfo(); 78 | return userService.updatePassword(oldPass, newPass, userInfo) ? 79 | AppResultBuilder.successNoData(ResultCode.USER_PASSWORD_MODIFY_SUCCESS) : 80 | AppResultBuilder.successNoData(ResultCode.USER_PASSWORD_MODIFY_FAIL); 81 | } 82 | 83 | @PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')") 84 | @GetMapping("user/backup") 85 | public AppResult> backup() { 86 | UserEntity userInfo = AuthInfo.getUserInfo(); 87 | final List boxesBackup = userService.findBoxesBackup(userInfo); 88 | return AppResultBuilder.success(boxesBackup, ResultCode.SUCCESS); 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminBoxController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.dto.SearchDto; 5 | import com.ujuji.navigation.model.entity.BoxEntity; 6 | import com.ujuji.navigation.service.AdminBoxService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import javax.validation.Valid; 15 | 16 | @RestController 17 | @RequestMapping("admin/box") 18 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 19 | public class AdminBoxController { 20 | 21 | @Resource 22 | AdminBoxService adminBoxService; 23 | 24 | 25 | @GetMapping 26 | public AppResult> findAllByPage(@RequestParam int page, @RequestParam int size) { 27 | if (size <= 0) { 28 | size = 20; 29 | } 30 | if (page <= 0) { 31 | page = 1; 32 | } 33 | IPage allByPage = adminBoxService.findAllByPage(page, size); 34 | return AppResultBuilder.success(allByPage, ResultCode.SUCCESS); 35 | } 36 | 37 | @DeleteMapping("/{boxId}") 38 | public AppResult findAllByPage(@PathVariable Integer boxId) { 39 | boolean b = adminBoxService.deleteOne(boxId); 40 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 41 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 42 | } 43 | 44 | @PutMapping 45 | public AppResult updateOne(@RequestBody BoxEntity boxEntity) { 46 | boolean b = adminBoxService.updateOne(boxEntity); 47 | 48 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 49 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 50 | } 51 | 52 | @PostMapping("/search") 53 | public IPage search(@RequestBody @Valid SearchDto searchDto) { 54 | if (searchDto.getPageNo() <= 0) { 55 | searchDto.setPageNo(1); 56 | } 57 | if (searchDto.getPageSize() <= 0) { 58 | searchDto.setPageSize(25); 59 | } 60 | return adminBoxService.searchByPage(searchDto.getKey(), searchDto.getPageNo(), 61 | searchDto.getPageSize()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminCardCodeController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.core.Constants; 5 | import com.ujuji.navigation.model.dto.InsertCardCodeDto; 6 | import com.ujuji.navigation.model.dto.PageDto; 7 | import com.ujuji.navigation.model.dto.SearchDto; 8 | import com.ujuji.navigation.model.entity.CardCodeEntity; 9 | import com.ujuji.navigation.service.CardCodeService; 10 | import com.ujuji.navigation.util.AppResult; 11 | import com.ujuji.navigation.util.AppResultBuilder; 12 | import com.ujuji.navigation.util.ResultCode; 13 | import org.springframework.security.access.prepost.PreAuthorize; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import javax.annotation.Resource; 17 | import javax.validation.Valid; 18 | import java.util.List; 19 | 20 | @RestController 21 | @RequestMapping("admin/cardCode") 22 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 23 | public class AdminCardCodeController { 24 | 25 | 26 | @Resource 27 | CardCodeService cardCodeService; 28 | 29 | @GetMapping("/types") 30 | public AppResult findTypes() { 31 | Constants.CardCodeType[] values = Constants.CardCodeType.values(); 32 | 33 | return AppResultBuilder.success(values, ResultCode.SUCCESS); 34 | } 35 | 36 | //分页查询所有 37 | @PostMapping("/find") 38 | public AppResult> findAllByPage(@RequestBody PageDto pageDto) { 39 | if (pageDto.getPageSize() <= 0) { 40 | pageDto.setPageSize(20); 41 | } 42 | if (pageDto.getPageNo() <= 0) { 43 | pageDto.setPageNo(1); 44 | } 45 | IPage byPage = cardCodeService.findByPage(pageDto.getPageNo(), pageDto.getPageSize()); 46 | return AppResultBuilder.success(byPage, ResultCode.SUCCESS); 47 | } 48 | 49 | //搜索 50 | @PostMapping("/search") 51 | public AppResult> search(@RequestBody @Valid SearchDto searchDto) { 52 | IPage search = cardCodeService.search(searchDto); 53 | return AppResultBuilder.success(search, ResultCode.SUCCESS); 54 | } 55 | 56 | @DeleteMapping("/{cardCodeId}") 57 | public AppResult findAllByPage(@PathVariable Integer cardCodeId) { 58 | boolean b = cardCodeService.deleteById(cardCodeId); 59 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 60 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 61 | } 62 | 63 | //插入卡密 64 | @PostMapping 65 | public AppResult insertMany(@RequestBody @Valid InsertCardCodeDto cardCodeDto) { 66 | List strings = cardCodeService.insertMany(cardCodeDto.getType(), cardCodeDto.getNum()); 67 | return AppResultBuilder.success(strings, ResultCode.SUCCESS); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.ujuji.navigation.model.entity.SiteConfigEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | import com.ujuji.navigation.service.SiteConfigService; 6 | import com.ujuji.navigation.service.UserService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.PathVariable; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.HashMap; 17 | import java.util.Map; 18 | 19 | @RestController 20 | @RequestMapping("admin") 21 | public class AdminController { 22 | 23 | @Resource 24 | UserService userService; 25 | @Resource 26 | SiteConfigService siteConfigService; 27 | 28 | @GetMapping("/userInfo/{userId}") 29 | public AppResult findUserInfo(@PathVariable int userId) { 30 | final UserEntity user = userService.findById(userId); 31 | if (user != null) { 32 | final SiteConfigEntity siteConfigEntity = siteConfigService.findByUserId(userId); 33 | Map info = new HashMap<>(); 34 | info.put("user", user); 35 | info.put("config", siteConfigEntity); 36 | return AppResultBuilder.success(info, ResultCode.SUCCESS); 37 | } else { 38 | return AppResultBuilder.fail(ResultCode.USER_NOT_EXIST); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminGlobalSettingController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.ujuji.navigation.model.entity.GlobalSettingEntity; 4 | import com.ujuji.navigation.service.GlobalSettingService; 5 | import com.ujuji.navigation.util.AppResult; 6 | import com.ujuji.navigation.util.AppResultBuilder; 7 | import com.ujuji.navigation.util.ResultCode; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.annotation.Resource; 12 | import javax.validation.Valid; 13 | import java.util.List; 14 | 15 | @RestController 16 | @RequestMapping("admin/globalSetting") 17 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 18 | public class AdminGlobalSettingController { 19 | 20 | @Resource 21 | GlobalSettingService globalSettingService; 22 | 23 | /*查询所有*/ 24 | @GetMapping 25 | public AppResult> findAll() { 26 | return AppResultBuilder.success(globalSettingService.findAll(), ResultCode.SUCCESS); 27 | } 28 | 29 | @GetMapping("/{name}") 30 | public AppResult findByName(@PathVariable String name) { 31 | return AppResultBuilder.success(globalSettingService.findByName(name), ResultCode.SUCCESS); 32 | } 33 | 34 | 35 | @PostMapping 36 | public AppResult insertOne(@RequestBody @Valid GlobalSettingEntity globalSettingEntity) { 37 | final boolean b = globalSettingService.insertOne(globalSettingEntity); 38 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_SUCCESS) : 39 | AppResultBuilder.successNoData(ResultCode.SERVICE_INSERT_FAIL); 40 | } 41 | 42 | 43 | @PutMapping 44 | public AppResult update(@RequestBody GlobalSettingEntity globalSettingEntity) { 45 | 46 | boolean b = globalSettingService.updateById(globalSettingEntity); 47 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 48 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 49 | } 50 | 51 | @DeleteMapping("/{settingId}") 52 | public AppResult deleteOne(@PathVariable Integer settingId) { 53 | boolean b = globalSettingService.deleteById(settingId); 54 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 55 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminLinkController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.dto.SearchDto; 5 | import com.ujuji.navigation.model.entity.LinkEntity; 6 | import com.ujuji.navigation.service.AdminLinkService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import javax.validation.Valid; 15 | 16 | @RestController 17 | @RequestMapping("admin/link") 18 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 19 | public class AdminLinkController { 20 | 21 | @Resource 22 | AdminLinkService adminLinkService; 23 | 24 | 25 | @GetMapping 26 | public AppResult> findAllByPage(@RequestParam int page, @RequestParam int size) { 27 | if (size <= 0) { 28 | size = 20; 29 | } 30 | if (page <= 0) { 31 | page = 1; 32 | } 33 | IPage allByPage = adminLinkService.findAllByPage(page, size); 34 | return AppResultBuilder.success(allByPage, ResultCode.SUCCESS); 35 | } 36 | 37 | @DeleteMapping("/{linkId}") 38 | public AppResult findAllByPage(@PathVariable Integer linkId) { 39 | boolean b = adminLinkService.deleteOne(linkId); 40 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 41 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 42 | } 43 | 44 | @PutMapping 45 | public AppResult updateOne(@RequestBody LinkEntity boxEntity) { 46 | boolean b = adminLinkService.updateOne(boxEntity); 47 | 48 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 49 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 50 | } 51 | 52 | @PostMapping("/search") 53 | public IPage search(@RequestBody @Valid SearchDto searchDto) { 54 | if (searchDto.getPageNo() <= 0) { 55 | searchDto.setPageNo(1); 56 | } 57 | if (searchDto.getPageSize() <= 0) { 58 | searchDto.setPageSize(25); 59 | } 60 | return adminLinkService.searchByPage(searchDto.getKey(), searchDto.getPageNo(), 61 | searchDto.getPageSize()); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminMsgController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 6 | import com.ujuji.navigation.service.AdminMsgService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | 15 | @RestController 16 | @RequestMapping("admin/msg") 17 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 18 | public class AdminMsgController { 19 | 20 | @Resource 21 | AdminMsgService adminMsgService; 22 | 23 | 24 | //查询所有,分页 25 | @GetMapping 26 | public AppResult> findAllByPage(@RequestParam int page, @RequestParam int size) { 27 | if (size <= 0) { 28 | size = 20; 29 | } 30 | if (page <= 0) { 31 | page = 1; 32 | } 33 | IPage allByPage = adminMsgService.findByPage(page, size); 34 | return AppResultBuilder.success(allByPage, ResultCode.SUCCESS); 35 | } 36 | 37 | //更新 38 | @PutMapping 39 | public AppResult updateOne(@RequestBody LeaveMsgEntity leaveMsgEntity) { 40 | boolean b = adminMsgService.updateOneById(leaveMsgEntity); 41 | 42 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 43 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 44 | } 45 | 46 | //删除 47 | @DeleteMapping("/{msgId}") 48 | public AppResult findAllByPage(@PathVariable Integer msgId) { 49 | boolean b = adminMsgService.deleteOne(msgId); 50 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 51 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/admin/AdminUserController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.admin; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.dto.SearchDto; 5 | import com.ujuji.navigation.model.entity.UserEntity; 6 | import com.ujuji.navigation.service.AdminUserService; 7 | import com.ujuji.navigation.util.AppResult; 8 | import com.ujuji.navigation.util.AppResultBuilder; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | import javax.annotation.Resource; 14 | import javax.validation.Valid; 15 | 16 | @RestController 17 | @RequestMapping("admin/user") 18 | @PreAuthorize("hasAuthority('ROLE_ADMIN')") 19 | public class AdminUserController { 20 | 21 | @Resource 22 | AdminUserService adminUserService; 23 | 24 | @GetMapping 25 | public AppResult> findAllByPage(@RequestParam int page, @RequestParam int size) { 26 | if (size <= 0) { 27 | size = 20; 28 | } 29 | if (page <= 0) { 30 | page = 1; 31 | } 32 | IPage allByPage = adminUserService.findAllByPage(page, size); 33 | return AppResultBuilder.success(allByPage, ResultCode.SUCCESS); 34 | } 35 | 36 | @DeleteMapping("/{userId}") 37 | public AppResult findAllByPage(@PathVariable Integer userId) { 38 | boolean b = adminUserService.deleteOne(userId); 39 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_SUCCESS) : 40 | AppResultBuilder.successNoData(ResultCode.SERVICE_DELETE_FAIL); 41 | } 42 | 43 | @PutMapping 44 | public AppResult updateOne(@RequestBody UserEntity userEntity) { 45 | boolean b = adminUserService.updateOne(userEntity); 46 | 47 | return b ? AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_SUCCESS) : 48 | AppResultBuilder.successNoData(ResultCode.SERVICE_UPDATE_FAIL); 49 | } 50 | 51 | @PostMapping("/search") 52 | public IPage search(@RequestBody @Valid SearchDto searchDto) { 53 | if (searchDto.getPageNo() <= 0) { 54 | searchDto.setPageNo(1); 55 | } 56 | if (searchDto.getPageSize() <= 0) { 57 | searchDto.setPageSize(25); 58 | } 59 | return adminUserService.searchByPage(searchDto.getKey(), searchDto.getPageNo(), 60 | searchDto.getPageSize()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/controller/common/ErrorController.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.controller.common; 2 | 3 | import com.ujuji.navigation.exception.MyException; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | @RestController 10 | public class ErrorController { 11 | /** 12 | * 重新抛出异常 13 | */ 14 | @RequestMapping("/error/throw") 15 | public void rethrow(HttpServletRequest request) { 16 | throw ((MyException) request.getAttribute("filter.error")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/core/Constants.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.core; 2 | 3 | public class Constants { 4 | 5 | public interface REGEX { 6 | String LINK_REGEX = "^https?://.*"; 7 | } 8 | 9 | public interface Weather { 10 | String API_URL = 11 | "https://www.baidu.com/home/other/data/weatherInfo?city=[city]&indextype=manht&asyn=1"; 12 | String KEY_WEATHER = "key_weather::"; 13 | } 14 | 15 | 16 | public interface Common { 17 | String KEY_VERIFY_CODE = "key_verify_code::"; 18 | String KEY_MSG_INTERVAL = "key_msg_interval::"; 19 | String KEY_FREQUENT_LIMIT = "key_frequent_limit::"; 20 | 21 | String UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit"; 22 | 23 | } 24 | 25 | public interface Mail { 26 | String STRING_FORGET_MAIL_SUBJECT = "【优聚集】忘记密码重置邮件"; 27 | String STRING_FORGET_MAIL_FROM = "优聚集-ujuji.com"; 28 | String KEY_FORGET_CODE_PREFIX = "key_forgot_code_prefix::"; 29 | } 30 | 31 | public interface CardCode { 32 | Integer CARD_CODE_LENGTH = 15; 33 | } 34 | 35 | public enum CardCodeType { 36 | RENAME 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/exception/MyException.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.exception; 2 | 3 | import com.ujuji.navigation.util.ResultCode; 4 | 5 | public class MyException extends RuntimeException { 6 | private String message; 7 | private ResultCode code; 8 | 9 | public MyException() { 10 | super(); 11 | } 12 | 13 | public MyException(String message) { 14 | super(message); 15 | this.message = message; 16 | } 17 | 18 | public MyException(ResultCode code) { 19 | super(code.getMsg()); 20 | this.message = code.getMsg(); 21 | this.code = code; 22 | } 23 | 24 | @Override 25 | public String getMessage() { 26 | return message; 27 | } 28 | 29 | public void setMessage(String message) { 30 | this.message = message; 31 | } 32 | 33 | public ResultCode getCode() { 34 | return code; 35 | } 36 | 37 | public void setCode(ResultCode code) { 38 | this.code = code; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/filter/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.filter; 2 | 3 | 4 | import com.ujuji.navigation.service.UserService; 5 | import com.ujuji.navigation.util.JwtUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 12 | import org.springframework.web.filter.OncePerRequestFilter; 13 | 14 | import javax.servlet.FilterChain; 15 | import javax.servlet.ServletException; 16 | import javax.servlet.http.HttpServletRequest; 17 | import javax.servlet.http.HttpServletResponse; 18 | import java.io.IOException; 19 | 20 | @Slf4j 21 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 22 | 23 | 24 | /*通过构造参数注入*/ 25 | private final UserService userService; 26 | 27 | private final JwtUtils jwtutils; 28 | 29 | public JwtAuthenticationTokenFilter(UserService userService, JwtUtils jwtutils) { 30 | this.userService = userService; 31 | this.jwtutils = jwtutils; 32 | } 33 | 34 | 35 | @Override 36 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { 37 | String authHeader = request.getHeader(jwtutils.getHeader()); 38 | if (StringUtils.isNotEmpty(authHeader)) { 39 | 40 | String[] strings = authHeader.split("\\s"); 41 | if (strings.length >= 2) { 42 | authHeader = strings[1]; 43 | } 44 | 45 | String username = jwtutils.getUsernameFromToken(authHeader); 46 | log.info("加入凭证:{}", username); 47 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 48 | // 判断如果username不为空,且上下文中没有数据,那么就尝试验证, 49 | UserDetails userDetails = this.userService.loadUserByUsername(username); 50 | log.info("Details:{}", userDetails.toString()); 51 | 52 | 53 | if (jwtutils.validateToken(authHeader, userDetails)) { 54 | // 且验证成功后,在上下文中加入凭证 55 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 56 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 57 | SecurityContextHolder.getContext().setAuthentication(authentication); 58 | } 59 | } 60 | } 61 | chain.doFilter(request, response); 62 | } 63 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/filter/JwtLoginFilter.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.filter; 2 | 3 | 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import com.ujuji.navigation.exception.MyException; 6 | import com.ujuji.navigation.model.dto.UserDto; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import com.ujuji.navigation.util.*; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.authentication.DisabledException; 13 | import org.springframework.security.authentication.InternalAuthenticationServiceException; 14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 15 | import org.springframework.security.core.Authentication; 16 | import org.springframework.security.core.AuthenticationException; 17 | import org.springframework.security.core.GrantedAuthority; 18 | import org.springframework.security.core.context.SecurityContext; 19 | import org.springframework.security.core.context.SecurityContextHolder; 20 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 21 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 22 | 23 | import javax.servlet.FilterChain; 24 | import javax.servlet.ServletException; 25 | import javax.servlet.http.HttpServletRequest; 26 | import javax.servlet.http.HttpServletResponse; 27 | import java.io.IOException; 28 | import java.io.PrintWriter; 29 | import java.util.Collection; 30 | import java.util.HashMap; 31 | import java.util.Map; 32 | 33 | @Slf4j 34 | public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter { 35 | 36 | 37 | private final JwtUtils jwtUtils; 38 | private final VerifyCodeCheck verifyCodeCheck; 39 | private final AuthenticationManager authenticationManager; 40 | 41 | public JwtLoginFilter(AuthenticationManager authenticationManager, JwtUtils jwtUtils, VerifyCodeCheck verifyCodeCheck) { 42 | 43 | this.authenticationManager = authenticationManager; 44 | this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/auth/login", "POST")); 45 | this.jwtUtils = jwtUtils; 46 | this.verifyCodeCheck = verifyCodeCheck; 47 | } 48 | 49 | 50 | @Override 51 | public Authentication attemptAuthentication(HttpServletRequest request, 52 | HttpServletResponse response) throws AuthenticationException { 53 | 54 | log.info("Authentication-->>attemptAuthentication"); 55 | 56 | // 从输入流中获取到登录的信息 57 | try { 58 | final UserDto userDto = new ObjectMapper().readValue(request.getInputStream(), UserDto.class); 59 | // 验证 验证码 60 | final String verifyCode = userDto.getVerifyCode(); 61 | final String code = userDto.getCode(); 62 | log.info("verifyCode ==>>{}", verifyCode); 63 | log.info("code ==>>{}", code); 64 | 65 | try { 66 | verifyCodeCheck.checkVerifyCode(verifyCode, code); 67 | } catch (MyException e) { 68 | try { 69 | request.setAttribute("filter.error", e); 70 | request.getRequestDispatcher("/error/throw").forward(request, response); 71 | } catch (ServletException servletException) { 72 | // servletException.printStackTrace(); 73 | } 74 | // e.printStackTrace(); 75 | return null; 76 | } 77 | 78 | return this.authenticationManager.authenticate( 79 | new UsernamePasswordAuthenticationToken(userDto.getUsername(), userDto.getPassword()) 80 | ); 81 | 82 | } catch (IOException e) { 83 | e.printStackTrace(); 84 | return null; 85 | } 86 | } 87 | 88 | 89 | // 成功验证后调用的方法 90 | // 如果验证成功,就生成token并返回 91 | @Override 92 | protected void successfulAuthentication(HttpServletRequest request, 93 | HttpServletResponse response, 94 | FilterChain chain, 95 | Authentication authResult) throws IOException, ServletException { 96 | 97 | UserEntity user = (UserEntity) authResult.getPrincipal(); 98 | System.out.println("user:" + user.toString()); 99 | 100 | String role = ""; 101 | Collection authorities = user.getAuthorities(); 102 | for (GrantedAuthority authority : authorities) { 103 | role = authority.getAuthority(); 104 | } 105 | 106 | String token = jwtUtils.generateToken(user); 107 | //String token = JwtTokenUtils.createToken(user.getUsername(), false); 108 | // 返回创建成功的token 109 | // 但是这里创建的token只是单纯的token 110 | // 按照jwt的规定,最后请求的时候应该是 `Bearer token` 111 | // 获取用户信息 112 | final SecurityContext context = SecurityContextHolder.getContext(); 113 | Map res = new HashMap<>(); 114 | user.setPassword(null); 115 | res.put("userInfo", user); 116 | res.put("token", token); 117 | response.setCharacterEncoding("UTF-8"); 118 | response.setContentType("application/json; charset=utf-8"); 119 | AppResult appResult = AppResultBuilder.success(res, ResultCode.USER_LOGIN_SUCCESS); 120 | String s = new ObjectMapper().writeValueAsString(appResult); 121 | PrintWriter writer = response.getWriter(); 122 | writer.print(s);//输出 123 | writer.close(); 124 | } 125 | 126 | @Override 127 | protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { 128 | final String message = failed.getMessage(); 129 | 130 | response.setCharacterEncoding("UTF-8"); 131 | response.setContentType("application/json; charset=utf-8"); 132 | AppResult appResult; 133 | 134 | if (failed instanceof InternalAuthenticationServiceException) { 135 | appResult = AppResultBuilder.fail(ResultCode.USER_LOGIN_ERROR); 136 | } else if (failed instanceof DisabledException) { 137 | appResult = AppResultBuilder.fail(ResultCode.USER_ACCOUNT_FORBIDDEN); 138 | } else if (StringUtils.isNoneBlank(message)) { 139 | appResult = AppResultBuilder.fail(message); 140 | } else { 141 | appResult = AppResultBuilder.fail(ResultCode.USER_LOGIN_FAIL); 142 | } 143 | String s = new ObjectMapper().writeValueAsString(appResult); 144 | PrintWriter writer = response.getWriter(); 145 | writer.print(s);//输出 146 | writer.close(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/handler/MyAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.handler; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.ujuji.navigation.util.AppResult; 5 | import com.ujuji.navigation.util.AppResultBuilder; 6 | import com.ujuji.navigation.util.ResultCode; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.web.access.AccessDeniedHandler; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | import java.io.PrintWriter; 16 | 17 | @Component 18 | public class MyAccessDeniedHandler implements AccessDeniedHandler { 19 | @Override 20 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { 21 | 22 | AppResult fail = AppResultBuilder.fail(ResultCode.PERMISSION_NO_ACCESS); 23 | String string = new ObjectMapper().writeValueAsString(fail); 24 | 25 | response.setCharacterEncoding("UTF-8"); 26 | response.setContentType("application/json; charset=utf-8"); 27 | PrintWriter writer = response.getWriter(); 28 | writer.print(string);//输出 29 | writer.close(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/handler/MyExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.handler; 2 | 3 | import com.ujuji.navigation.exception.MyException; 4 | import com.ujuji.navigation.model.entity.BaseEntity; 5 | import com.ujuji.navigation.util.AppResult; 6 | import com.ujuji.navigation.util.AppResultBuilder; 7 | import com.ujuji.navigation.util.ResultCode; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.security.authentication.DisabledException; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.validation.FieldError; 13 | import org.springframework.web.bind.MethodArgumentNotValidException; 14 | import org.springframework.web.bind.annotation.ControllerAdvice; 15 | import org.springframework.web.bind.annotation.ExceptionHandler; 16 | import org.springframework.web.bind.annotation.RestControllerAdvice; 17 | 18 | @RestControllerAdvice 19 | @Slf4j 20 | @ControllerAdvice 21 | public class MyExceptionHandler { 22 | 23 | @ExceptionHandler(value = MyException.class) 24 | public AppResult entityHandler(MyException e) { 25 | log.info("Exception Handler: {} - {}", "entityHandler", e.getMessage()); 26 | return AppResultBuilder.fail(e.getMessage(), e.getCode()); 27 | } 28 | 29 | @ExceptionHandler(value = MethodArgumentNotValidException.class) 30 | public AppResult argumentsHandler(MethodArgumentNotValidException e) { 31 | log.info("Exception Handler: {}", "argumentsHandler"); 32 | BindingResult bindingResult = e.getBindingResult(); 33 | FieldError fieldError = bindingResult.getFieldError(); 34 | assert fieldError != null; 35 | log.info("MethodArgumentNotValidException: {}", fieldError.getDefaultMessage()); 36 | return AppResultBuilder.fail(fieldError.getDefaultMessage()); 37 | } 38 | 39 | @ExceptionHandler(value = Exception.class) 40 | public AppResult globalHandler(Exception e) { 41 | e.printStackTrace(); 42 | log.info("Exception Handler: {}", "globalHandler"); 43 | log.error("系统错误:{}", e.getMessage()); 44 | return AppResultBuilder.fail("系统错误,请联系管理员"); 45 | } 46 | 47 | @ExceptionHandler(value = DisabledException.class) 48 | public AppResult disabledExceptionHandler(DisabledException e) { 49 | e.printStackTrace(); 50 | log.info("disabledExceptionHandler Handler: {}", "DisabledException"); 51 | log.error("DisabledException:{}", e.getMessage()); 52 | return AppResultBuilder.fail("系统错误,请联系管理员"); 53 | } 54 | 55 | /** 56 | * 这里处理没有权限的异常,不能在SecurityConfig里面处理,因为要被Exception捕获了 57 | * 58 | * @param e 异常 59 | * @return 返回的信息 60 | */ 61 | @ExceptionHandler(value = AccessDeniedException.class) 62 | public AppResult accessDeniedHandler(Exception e) { 63 | log.info("Exception Handler: {}", "accessDeniedHandler"); 64 | log.error("accessDeniedHandler:{}", e.getMessage()); 65 | return AppResultBuilder.fail(ResultCode.PERMISSION_NO_ACCESS); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/handler/MyMetaObjectHandler.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.handler; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.ibatis.reflection.MetaObject; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @Slf4j 10 | public class MyMetaObjectHandler implements MetaObjectHandler { 11 | @Override 12 | public void insertFill(MetaObject metaObject) { 13 | log.info("开始插入填充....."); 14 | if (metaObject.hasSetter("createdAt")) { 15 | log.info("createdAt"); 16 | this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now()); 17 | } 18 | if (metaObject.hasSetter("updatedAt")) { 19 | log.info("updatedAt"); 20 | this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); 21 | } 22 | } 23 | 24 | @Override 25 | public void updateFill(MetaObject metaObject) { 26 | log.info("开始更新填充....."); 27 | if (metaObject.hasSetter("updatedAt")) { 28 | log.info("updatedAt"); 29 | this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now()); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/interceptor/FrequentInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.interceptor; 2 | 3 | import com.ujuji.navigation.annotation.FrequencyLimit; 4 | import com.ujuji.navigation.core.Constants; 5 | import com.ujuji.navigation.exception.MyException; 6 | import com.ujuji.navigation.util.RedisUtils; 7 | import com.ujuji.navigation.util.ResultCode; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.web.method.HandlerMethod; 11 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 12 | 13 | import javax.annotation.Resource; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | @Component 18 | @Slf4j 19 | public class FrequentInterceptor extends HandlerInterceptorAdapter { 20 | @Resource 21 | RedisUtils redisUtils; 22 | 23 | //肯定是preHandle 24 | @Override 25 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 26 | //返回true就是直接通过 27 | if (handler instanceof HandlerMethod) {//是方法 28 | HandlerMethod handlerMethod = (HandlerMethod) handler; 29 | String simpleName = 30 | handlerMethod.getMethod().getDeclaringClass().getSimpleName() + "." 31 | + handlerMethod.getMethod().getName(); 32 | FrequencyLimit methodAnnotation = handlerMethod.getMethodAnnotation(FrequencyLimit.class); 33 | if (methodAnnotation == null) return true;//直接返回true,放行 34 | boolean ok = isOk(simpleName, methodAnnotation, request); 35 | if (!ok) { 36 | // response 37 | //抛出错误 38 | request.setAttribute("filter.error", new MyException(ResultCode.VISIT_TOO_OFTEN)); 39 | request.getRequestDispatcher("/error/throw").forward(request, response); 40 | } 41 | return ok; 42 | } 43 | // return super.preHandle(request, response, handler); 44 | 45 | return false; 46 | } 47 | 48 | //判断是否redis中有此记录(有的话,说明采访问了此接口,暂停访问) 49 | public boolean isOk(String simpleName, FrequencyLimit frequencyLimit, HttpServletRequest request) { 50 | int value = frequencyLimit.value(); 51 | if (value == 0) {//为0直接false 52 | return false; 53 | } 54 | String ip = request.getRemoteAddr(); 55 | Object o = redisUtils.get(Constants.Common.KEY_FREQUENT_LIMIT + simpleName + "_" + ip); 56 | if (o == null) { 57 | //设置限制 58 | redisUtils.set(Constants.Common.KEY_FREQUENT_LIMIT + simpleName + "_" + ip, "true", value); 59 | return true; 60 | } 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/BoxMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.BoxEntity; 5 | 6 | public interface BoxMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/CardCodeMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.CardCodeEntity; 5 | 6 | public interface CardCodeMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/GlobalSettingMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.GlobalSettingEntity; 5 | 6 | public interface GlobalSettingMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/LeaveMsgMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 5 | 6 | public interface LeaveMsgMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/LinkMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.LinkEntity; 5 | 6 | public interface LinkMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/NoticeMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.NoticeEntity; 5 | 6 | public interface NoticeMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/SearchSiteMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.SearchSiteEntity; 5 | 6 | public interface SearchSiteMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/SiteConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.SiteConfigEntity; 5 | 6 | public interface SiteConfigMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | public interface UserMapper extends BaseMapper { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/WeatherResp.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model; 2 | 3 | import lombok.Data; 4 | import lombok.NoArgsConstructor; 5 | 6 | @NoArgsConstructor 7 | @Data 8 | public class WeatherResp { 9 | 10 | /** 11 | * cityid : 101272004 12 | * city : 成都 13 | * update_time : 13:45 14 | * wea : 多云 15 | * wea_img : yun 16 | * tem : 27 17 | * tem_day : 28 18 | * tem_night : 22 19 | * win : 东风 20 | * win_speed : 2级 21 | * win_meter : 小于12km/h 22 | * air : 16 23 | */ 24 | 25 | private String cityid; 26 | private String city; 27 | private String update_time; 28 | private String wea; 29 | private String wea_img; 30 | private String tem; 31 | private String tem_day; 32 | private String tem_night; 33 | private String win; 34 | private String win_speed; 35 | private String win_meter; 36 | private String air; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/BoxDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import com.ujuji.navigation.model.entity.BaseEntity; 6 | import com.ujuji.navigation.model.entity.LinkEntity; 7 | 8 | import javax.validation.constraints.Max; 9 | import javax.validation.constraints.Min; 10 | import javax.validation.constraints.NotBlank; 11 | import java.util.List; 12 | 13 | @TableName("boxes") 14 | public class BoxDto extends BaseEntity { 15 | public BoxDto() { 16 | } 17 | 18 | public BoxDto(@NotBlank(message = "标题不能为空") String title, String titleIcon, @Min(value = 1, message = "排序值只能1-100之间") @Max(value = 100, message = "排序值只能1-100之间") Integer boxOrder, String introduction, Boolean openToOther, List links, Integer userId) { 19 | this.title = title; 20 | this.titleIcon = titleIcon; 21 | this.boxOrder = boxOrder; 22 | this.introduction = introduction; 23 | this.openToOther = openToOther; 24 | this.links = links; 25 | this.userId = userId; 26 | } 27 | 28 | 29 | @NotBlank(message = "标题不能为空") 30 | private String title; 31 | private String titleIcon; 32 | @Min(value = 1, message = "排序值只能1-100之间") 33 | @Max(value = 100, message = "排序值只能1-100之间") 34 | private Integer boxOrder; 35 | 36 | private String introduction; 37 | 38 | private Boolean openToOther; 39 | 40 | @TableField(exist = false) 41 | List links; 42 | 43 | private Integer userId; 44 | 45 | 46 | public String getTitle() { 47 | return title; 48 | } 49 | 50 | public void setTitle(String title) { 51 | this.title = title; 52 | } 53 | 54 | public String getTitleIcon() { 55 | return titleIcon; 56 | } 57 | 58 | public void setTitleIcon(String titleIcon) { 59 | this.titleIcon = titleIcon; 60 | } 61 | 62 | public Integer getBoxOrder() { 63 | return boxOrder; 64 | } 65 | 66 | public void setBoxOrder(Integer boxOrder) { 67 | this.boxOrder = boxOrder; 68 | } 69 | 70 | public String getIntroduction() { 71 | return introduction; 72 | } 73 | 74 | public void setIntroduction(String introduction) { 75 | this.introduction = introduction; 76 | } 77 | 78 | public Boolean getOpenToOther() { 79 | return openToOther; 80 | } 81 | 82 | public void setOpenToOther(Boolean openToOther) { 83 | this.openToOther = openToOther; 84 | } 85 | 86 | public List getLinks() { 87 | return links; 88 | } 89 | 90 | public void setLinks(List links) { 91 | this.links = links; 92 | } 93 | 94 | public Integer getUserId() { 95 | return userId; 96 | } 97 | 98 | public void setUserId(Integer userId) { 99 | this.userId = userId; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/ForgotPassDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class ForgotPassDto { 13 | @NotBlank(message = "用户名不能为空") 14 | private String username; 15 | @NotBlank(message = "邮箱地址不能为空") 16 | private String email; 17 | @NotBlank(message = "验证码不能为空") 18 | private String verifyCode; 19 | @NotBlank(message = "验证码系统错误") 20 | private String code; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/ImportBoxDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.NotEmpty; 9 | import java.util.List; 10 | 11 | @Data 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class ImportBoxDto { 15 | @NotBlank(message = "盒子标题必须存在") 16 | private String boxTitle; 17 | @NotEmpty(message = "待导入的链接(书签)个数必须大于等于1") 18 | private List links; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/InsertCardCodeDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class InsertCardCodeDto { 14 | 15 | @NotNull(message = "数量必须有") 16 | private Integer num=1; 17 | @NotBlank(message = "卡密类型不能为空") 18 | private String type; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/LeaveMsgDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class LeaveMsgDto { 14 | // /* 15 | // 16 | // content: '', 17 | // nickname: '', 18 | // userId: -1, 19 | // verifyCode: '', 20 | // code: -1,*/ 21 | private String ip; 22 | @NotBlank(message = "内容不能为空") 23 | private String content; 24 | @NotBlank(message = "昵称不能为空") 25 | private String nickname; 26 | @NotBlank(message = "验证码不能为空") 27 | private String verifyCode; 28 | @NotNull(message = "用户ID不能为空") 29 | private Integer userId; 30 | @NotBlank(message = "验证码系统错误") 31 | private String code; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/LinkDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.Pattern; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class LinkDto { 14 | @NotBlank(message = "链接不能为空") 15 | @Pattern(regexp = "^https?://.*",message = "书签必须是链接") 16 | private String link; 17 | @NotBlank(message = "标题不能为空") 18 | private String title; 19 | private String titleIcon; 20 | private String description; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/PageDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class PageDto { 11 | private Integer pageNo = 1; 12 | private Integer pageSize = 20; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/ReplyMsgDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Data 11 | @AllArgsConstructor 12 | @NoArgsConstructor 13 | public class ReplyMsgDto { 14 | 15 | @NotNull(message = "留言ID不能为空") 16 | private Integer id; 17 | 18 | @NotBlank(message = "回复内容不能为空") 19 | private String reply; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/SearchDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class SearchDto { 13 | @NotBlank(message = "关键词不能为空") 14 | private String key; 15 | private int pageSize; 16 | private int pageNo; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/SearchLinkDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class SearchLinkDto { 11 | private String keyword; 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/UpdatePassWithCodeDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class UpdatePassWithCodeDto { 13 | @NotBlank(message = "新密码不能为空") 14 | private String newPass; 15 | @NotBlank(message = "验证码不能为空") 16 | private String code; 17 | @NotBlank(message = "邮箱不能为空") 18 | private String email; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.validation.constraints.NotBlank; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class UserDto { 13 | @NotBlank(message = "用户名不能为空") 14 | private String username; 15 | @NotBlank(message = "密码不能为空") 16 | private String password; 17 | @NotBlank(message = "验证码不能为空") 18 | private String verifyCode; 19 | @NotBlank(message = "验证码数据错误") 20 | private String code; 21 | private String email; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/dto/VerifyCodeDto.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @AllArgsConstructor 9 | @NoArgsConstructor 10 | public class VerifyCodeDto { 11 | private String code; 12 | private String image; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.IdType; 5 | import com.baomidou.mybatisplus.annotation.TableField; 6 | import com.baomidou.mybatisplus.annotation.TableId; 7 | import com.fasterxml.jackson.annotation.JsonFormat; 8 | import lombok.Data; 9 | import org.springframework.format.annotation.DateTimeFormat; 10 | 11 | import java.time.LocalDateTime; 12 | 13 | @Data 14 | public class BaseEntity { 15 | @TableId(type = IdType.AUTO) 16 | private Integer id; 17 | 18 | @TableField(fill = FieldFill.INSERT)//INSERT代表只在插入时填充 19 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//set 20 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//get 21 | protected LocalDateTime createdAt; 22 | 23 | @TableField(fill = FieldFill.INSERT_UPDATE)// INSERT_UPDATE 首次插入、其次更新时填充(或修改) 24 | @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")//set 25 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//get 26 | protected LocalDateTime updatedAt; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/BoxEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | 6 | import javax.validation.constraints.Max; 7 | import javax.validation.constraints.Min; 8 | import javax.validation.constraints.NotBlank; 9 | import java.util.List; 10 | 11 | @TableName("boxes") 12 | public class BoxEntity extends BaseEntity { 13 | public BoxEntity() { 14 | } 15 | 16 | public BoxEntity(@NotBlank(message = "标题不能为空") String title, String titleIcon, @Min(value = 1, message = "排序值只能1-100之间") @Max(value = 100, message = "排序值只能1-100之间") Integer boxOrder, String pwd, String introduction, Boolean openToOther, List links, Integer userId) { 17 | this.title = title; 18 | this.titleIcon = titleIcon; 19 | this.boxOrder = boxOrder; 20 | this.pwd = pwd; 21 | this.introduction = introduction; 22 | this.openToOther = openToOther; 23 | this.links = links; 24 | this.userId = userId; 25 | } 26 | 27 | @NotBlank(message = "标题不能为空") 28 | private String title; 29 | private String titleIcon; 30 | @Min(value = 1, message = "排序值只能1-100之间") 31 | @Max(value = 100, message = "排序值只能1-100之间") 32 | private Integer boxOrder; 33 | 34 | private String pwd; 35 | private String introduction; 36 | 37 | private Boolean openToOther; 38 | 39 | @TableField(exist = false) 40 | List links; 41 | 42 | private Integer userId; 43 | 44 | public String getTitle() { 45 | return title; 46 | } 47 | 48 | public void setTitle(String title) { 49 | this.title = title; 50 | } 51 | 52 | public String getTitleIcon() { 53 | return titleIcon; 54 | } 55 | 56 | public void setTitleIcon(String titleIcon) { 57 | this.titleIcon = titleIcon; 58 | } 59 | 60 | public Integer getBoxOrder() { 61 | return boxOrder; 62 | } 63 | 64 | public void setBoxOrder(Integer boxOrder) { 65 | this.boxOrder = boxOrder; 66 | } 67 | 68 | public String getPwd() { 69 | return pwd; 70 | } 71 | 72 | public void setPwd(String pwd) { 73 | this.pwd = pwd; 74 | } 75 | 76 | public String getIntroduction() { 77 | return introduction; 78 | } 79 | 80 | public void setIntroduction(String introduction) { 81 | this.introduction = introduction; 82 | } 83 | 84 | public Boolean getOpenToOther() { 85 | return openToOther; 86 | } 87 | 88 | public void setOpenToOther(Boolean openToOther) { 89 | this.openToOther = openToOther; 90 | } 91 | 92 | public List getLinks() { 93 | return links; 94 | } 95 | 96 | public void setLinks(List links) { 97 | this.links = links; 98 | } 99 | 100 | public Integer getUserId() { 101 | return userId; 102 | } 103 | 104 | public void setUserId(Integer userId) { 105 | this.userId = userId; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/CardCodeEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @TableName("card_code") 16 | //卡密系统 17 | public class CardCodeEntity extends BaseEntity { 18 | 19 | @NotBlank(message = "卡密内容不能为空") 20 | private String content; 21 | private Boolean used; 22 | @NotBlank(message = "卡密类型不能为空") 23 | private String type; 24 | private Integer usedBy;//由哪个用户使用 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/GlobalSettingEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | 11 | @Data 12 | @EqualsAndHashCode(callSuper = true) 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @TableName("global_settings") 16 | public class GlobalSettingEntity extends BaseEntity { 17 | @NotBlank(message = "名称不能为空") 18 | private String name; 19 | @NotBlank(message = "内容不能为空") 20 | private String value; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/LeaveMsgEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @AllArgsConstructor 14 | @NoArgsConstructor 15 | @TableName("leave_msg") 16 | public class LeaveMsgEntity extends BaseEntity { 17 | private Integer userId; 18 | private Integer fixed; 19 | @NotBlank(message = "昵称不能为空") 20 | private String nickname; 21 | @NotBlank(message = "内容不能为空") 22 | private String content; 23 | private Boolean isRead; 24 | private String reply; 25 | private String ip; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/LinkEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import javax.validation.constraints.NotNull; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @TableName("links") 17 | public class LinkEntity extends BaseEntity { 18 | 19 | @NotBlank(message = "链接不能为空") 20 | private String link; 21 | @NotBlank(message = "标题不能为空") 22 | private String title; 23 | private String titleIcon; 24 | private String description; 25 | private Boolean isShow; 26 | @NotNull(message = "Box Id 不能为空") 27 | private Integer boxId; 28 | private Integer linkOrder; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/NoticeEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | @EqualsAndHashCode(callSuper = true) 12 | @Data 13 | @TableName("notices") 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class NoticeEntity extends BaseEntity { 17 | 18 | @NotNull(message = "所属用户id不能为空") 19 | private Integer userId; 20 | private String content;// 短的,一句话提示 21 | private String longNotice;// 长的公告 22 | 23 | private Integer isShow; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/SearchSiteEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | @EqualsAndHashCode(callSuper = true) 10 | @Data 11 | @TableName("search_sites") 12 | @AllArgsConstructor 13 | @NoArgsConstructor 14 | public class SearchSiteEntity extends BaseEntity { 15 | 16 | private Integer userId; 17 | private String name;// 18 | private String notice;// 19 | private String searchUrl;// 20 | private Integer siteOrder; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/SiteConfigEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.validation.constraints.NotBlank; 10 | import javax.validation.constraints.Pattern; 11 | 12 | @EqualsAndHashCode(callSuper = true) 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | @TableName("site_config") 17 | public class SiteConfigEntity extends BaseEntity { 18 | 19 | @NotBlank(message = "站点名不能为空") 20 | private String siteName; 21 | @NotBlank(message = "站点描述不能为空") 22 | private String siteDesc; 23 | @Pattern(regexp = "^[a-zA-Z0-9]{4,23}$", message = "请填写站点标签,且只能为字母和数字,且4<=位数<=23") 24 | private String suffix; 25 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的站点颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 26 | private String siteColor; 27 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 28 | private String siteSubColor; 29 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 30 | private String descColor; 31 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 32 | private String boxTitleColor; 33 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 34 | private String listItemColor; 35 | 36 | @Pattern(regexp = "^#?[0-9a-zA-Z]{3,8}", message = "请输入正确的颜色配置,不要随意输入(该页面有多个地方都需要设置颜色[必须])") 37 | private String searchSiteColor; 38 | 39 | @Pattern(regexp = "(^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$)|(^rgba\\((\\d+),\\s*(\\d+),\\s*(\\d+)(,\\s*\\d+\\" + 40 | ".\\d+)*\\)$)", message = "请输入正确的[盒子]颜色配置,其格式为: rgba(x,x,x,0.x)") 41 | private String boxColor; 42 | 43 | private String backgroundMusic; 44 | 45 | private String backgroundEffect;//背景特效 46 | 47 | // @Pattern(regexp = "^(?:https?://)?([(\\w+).]+?)/?[\\w/]+\\w+(\\.png|\\.jpg)$", message = "目前只支持网络链接的图片哟,且只能以Png" + 48 | // "或Jpg结尾") 49 | private String backgroundImage; 50 | 51 | private Integer otherImg;//师傅启用每日bing的背景图片 52 | 53 | private String mobileImg;//手机壁纸 54 | 55 | private Boolean hidePwdBox;//隐藏私密盒子 56 | private Boolean hideSiteIcon;//隐藏站点图标 57 | 58 | private Integer userId; 59 | private Integer isShow; 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/entity/UserEntity.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import lombok.*; 6 | import org.hibernate.validator.constraints.Length; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | 11 | import javax.validation.constraints.NotBlank; 12 | import javax.validation.constraints.Null; 13 | import javax.validation.constraints.Pattern; 14 | import java.util.ArrayList; 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | @EqualsAndHashCode(callSuper = true) 19 | @Data 20 | @ToString(callSuper = true) 21 | @AllArgsConstructor 22 | @NoArgsConstructor 23 | @TableName("users") 24 | public class UserEntity extends BaseEntity implements UserDetails { 25 | @NotBlank(message = "用户名不能为空") 26 | private String username; 27 | 28 | 29 | @NotBlank(message = "密码不能为空") 30 | @Length(min = 6, message = "密码长度最少6位") 31 | // @JsonIgnore 32 | private String password; 33 | 34 | @NotBlank(message = "邮箱不能为空") 35 | @Pattern(regexp = "\\w+@\\w+(\\.\\w{2,3})*\\.\\w{2,3}", message = "邮箱格式不准确") 36 | private String email; 37 | 38 | private Integer enable; 39 | 40 | private String AccessToken;//token 41 | 42 | @Null(message = "请勿传入非法参数") 43 | private String authority; 44 | 45 | @TableField(exist = false) 46 | private List boxes; 47 | 48 | 49 | @Override 50 | public Collection getAuthorities() { 51 | List list = new ArrayList<>(); 52 | list.add(new SimpleGrantedAuthority(authority)); 53 | return list; 54 | } 55 | 56 | @Override 57 | public String getPassword() { 58 | return password; 59 | } 60 | 61 | @Override 62 | public String getUsername() { 63 | return username; 64 | } 65 | 66 | @Override 67 | public boolean isAccountNonExpired() { 68 | return true; 69 | } 70 | 71 | @Override 72 | public boolean isAccountNonLocked() { 73 | return true; 74 | } 75 | 76 | @Override 77 | public boolean isCredentialsNonExpired() { 78 | return true; 79 | } 80 | 81 | @Override 82 | public boolean isEnabled() { 83 | return enable == 1; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/vo/BoxVo.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @Data 10 | @AllArgsConstructor 11 | @NoArgsConstructor 12 | public class BoxVo { 13 | 14 | private Integer id; 15 | 16 | private String introduction; 17 | 18 | private String title; 19 | 20 | private String titleIcon; 21 | 22 | protected LocalDateTime updatedAt; 23 | protected LocalDateTime createdAt; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/model/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.model.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | public class UserVo { 12 | 13 | private String username; 14 | private String AccessToken;//token 15 | private String email; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/AdminBoxService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.entity.BoxEntity; 5 | 6 | public interface AdminBoxService { 7 | /** 8 | * 返回所有盒子 9 | * 10 | * @param pageNum 当前页数 11 | * @param pageSize 每页条数 12 | * @return IPage 13 | */ 14 | IPage findAllByPage(int pageNum, int pageSize); 15 | 16 | /** 17 | * 返回所有盒子 18 | * 19 | * @param pageNum 当前页数 20 | * @param pageSize 每页条数 21 | * @return IPage 22 | */ 23 | IPage searchByPage(String key, int pageNum, int pageSize); 24 | 25 | 26 | boolean deleteOne(Integer userId); 27 | 28 | boolean updateOne(BoxEntity userEntity); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/AdminLinkService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.entity.LinkEntity; 5 | 6 | public interface AdminLinkService { 7 | /** 8 | * 返回所有列表 9 | * 10 | * @param pageNum 当前页数 11 | * @param pageSize 每页条数 12 | * @return IPage 13 | */ 14 | IPage findAllByPage(int pageNum, int pageSize); 15 | 16 | /** 17 | * 搜索 18 | * 19 | * @param key 关键词 20 | * @param pageNum 当前页数 21 | * @param pageSize 每页条数 22 | * @return IPage 23 | */ 24 | IPage searchByPage(String key, int pageNum, int pageSize); 25 | 26 | 27 | boolean deleteOne(Integer userId); 28 | 29 | boolean updateOne(LinkEntity linkEntity); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/AdminMsgService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 5 | 6 | public interface AdminMsgService { 7 | 8 | IPage findByPage(int pageNo, int pageSize); 9 | 10 | boolean deleteOne(Integer id); 11 | 12 | boolean updateOneById(LeaveMsgEntity leaveMsgEntity); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/AdminUserService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | public interface AdminUserService { 7 | /** 8 | * 返回所有用户 9 | * 10 | * @param pageNum 当前页数 11 | * @param pageSize 每页条数 12 | * @return IPage 13 | */ 14 | IPage findAllByPage(int pageNum, int pageSize); 15 | 16 | /** 17 | * 返搜索回所有用户 18 | * 19 | * @param pageNum 当前页数 20 | * @param pageSize 每页条数 21 | * @return IPage 22 | */ 23 | IPage searchByPage(String key, int pageNum, int pageSize); 24 | 25 | 26 | boolean deleteOne(Integer userId); 27 | 28 | boolean updateOne(UserEntity userEntity); 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/BoxService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.BoxEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface BoxService { 9 | 10 | /** 11 | * 获取某个用户的所有分享盒子 12 | * 13 | * @param userId 用户id 14 | * @return 所属属于该用户的盒子 15 | */ 16 | List findByUserId(Integer userId); 17 | 18 | /** 19 | * 获取某个用户的所有分享盒子,不包含有密码的 20 | * 21 | * @param userId 用户id 22 | * @return 所属属于该用户的盒子不包含有密码的 23 | */ 24 | List findByUserIdWithoutPwd(Integer userId); 25 | 26 | /*根据id查询*/ 27 | BoxEntity findById(Integer id); 28 | 29 | /*通过id和密码查询*/ 30 | BoxEntity findByPwd(Integer id, String pwd); 31 | 32 | /*通过盒子标题和其所属用户ID查询*/ 33 | BoxEntity findByTitleAndUid(String title, Integer userId); 34 | 35 | /** 36 | * 根据id删除 37 | * 38 | * @param id 被删除id 39 | * @param userEntity 当前登录用户信息实体 40 | * @return 是否删除成功 41 | */ 42 | boolean deleteById(Integer id, UserEntity userEntity); 43 | 44 | /** 45 | * 插入 46 | * 47 | * @param boxEntity 实体 48 | * @param userEntity 当前登录用户信息实体 49 | * @return 是否插入成功 50 | */ 51 | boolean insertOne(BoxEntity boxEntity, UserEntity userEntity); 52 | 53 | /** 54 | * 通过盒子标题和当前登录用户Id查询盒子实体 55 | * 56 | * @param boxEntity 包含盒子标题和当前登录用户Id的实体 57 | * @return 查询到的盒子实体 58 | */ 59 | BoxEntity findByTitleAndUserId(BoxEntity boxEntity); 60 | 61 | /** 62 | * 修改 63 | * 64 | * @param boxEntity 实体 65 | * @param userEntity 当前登录用户信息实体 66 | * @return 是否修改成功 67 | */ 68 | boolean updateById(BoxEntity boxEntity, UserEntity userEntity); 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/CardCodeService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.dto.SearchDto; 5 | import com.ujuji.navigation.model.entity.CardCodeEntity; 6 | 7 | import java.util.List; 8 | 9 | public interface CardCodeService { 10 | 11 | /** 12 | * 分页查询 13 | * @param pageNo 页码 14 | * @param pageSize 页数 15 | * @return 结果 16 | */ 17 | IPage findByPage(Integer pageNo, Integer pageSize); 18 | /** 19 | * 通过ID查询 20 | * 21 | * @param id ID 22 | * @return CardCodeEntity 23 | */ 24 | CardCodeEntity findById(Integer id); 25 | 26 | /** 27 | * 批量生成卡密 28 | * 29 | * @param type 卡密类型 30 | * @param num 卡密数量 31 | * @return 生成的卡密 32 | */ 33 | List insertMany(String type, int num); 34 | 35 | /** 36 | * 搜索卡密 37 | * @param searchDto 卡密 38 | * @return 搜索到的卡密 39 | */ 40 | IPage search(SearchDto searchDto); 41 | 42 | /** 43 | * 生成单张卡密 44 | * 45 | * @param type 卡密类型 46 | * @return 生成的卡密 47 | */ 48 | String insertOne(String type); 49 | 50 | /** 51 | * 删除卡密 52 | * 53 | * @param id 卡密ID 54 | * @return 是否删除成功 55 | */ 56 | boolean deleteById(Integer id); 57 | 58 | /** 59 | * 设置该卡密已使用 60 | * 61 | * @param cardCodeId 卡密ID 62 | * @param usedBy 使用的用户ID 63 | * @return 是否设置成功 64 | */ 65 | boolean setUsed(Integer cardCodeId, Integer usedBy); 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/CommonService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.dto.ImportBoxDto; 4 | 5 | //专门处理包含多个其他service的操作 6 | public interface CommonService { 7 | 8 | Integer importBoxAndLinks(ImportBoxDto importBoxDto); 9 | 10 | String getWeather(String city); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/EmailService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.dto.ForgotPassDto; 4 | 5 | public interface EmailService { 6 | 7 | /** 8 | * 先检查是否已经发送过了 9 | * 10 | * @param forgotPassDto forgotPassDto 11 | */ 12 | boolean checkHasSent(ForgotPassDto forgotPassDto); 13 | 14 | /** 15 | * 发送重置密码的邮件 16 | * 17 | * @param email 待发送的邮箱地址 18 | */ 19 | void sendForgotPassEmail(String email); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/GlobalSettingService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.GlobalSettingEntity; 4 | 5 | import java.util.List; 6 | 7 | public interface GlobalSettingService { 8 | GlobalSettingEntity findById(Integer id); 9 | 10 | GlobalSettingEntity findByName(String name); 11 | 12 | List findAll(); 13 | 14 | boolean deleteById(Integer id); 15 | 16 | boolean insertOne(GlobalSettingEntity globalSettingEntity); 17 | 18 | boolean updateById(GlobalSettingEntity globalSettingEntity); 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/LeaveMsgService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.baomidou.mybatisplus.core.metadata.IPage; 4 | import com.ujuji.navigation.model.dto.LeaveMsgDto; 5 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 6 | import com.ujuji.navigation.model.entity.UserEntity; 7 | 8 | import java.util.List; 9 | 10 | public interface LeaveMsgService { 11 | /** 12 | * 搜索留言 13 | * 14 | * @param kw 关键词 15 | * @param pageSize 每页大小 16 | * @param pageNo 第几页 17 | * @return IPage对象 18 | */ 19 | 20 | IPage searchMsg(String kw, Integer userId, Integer pageSize, Integer pageNo); 21 | 22 | /** 23 | * 查询没有阅读的留言的个数 24 | * 25 | * @param userId 用户ID 26 | * @return 个数 27 | */ 28 | Integer findNonReadMsg(Integer userId); 29 | 30 | IPage findByUserId(Integer userId, Integer pageSize, Integer pageNo); 31 | 32 | /** 33 | * 根据ID查询留言 34 | * 35 | * @param id 留言的ID 36 | * @return 返回留言 37 | */ 38 | LeaveMsgEntity findById(Integer id); 39 | 40 | /** 41 | * 查询置顶的留言 42 | * 43 | * @param userId 用户id 44 | * @return 置顶的留言 45 | */ 46 | List findFixedByUserId(Integer userId); 47 | 48 | /** 49 | * 返回 50 | * 51 | * @param userId 用户ID 52 | * @return 返回留言 53 | */ 54 | IPage findMsgByUserIdWithNoFixed(Integer userId, int pageSize, int pageNo); 55 | 56 | /** 57 | * 设置置顶 58 | * 59 | * @param id 待置顶的ID 60 | * @param userEntity 登录的用户 61 | * @return 是否置顶成功 62 | */ 63 | boolean setFixed(Integer id, UserEntity userEntity); 64 | 65 | /** 66 | * 设置留言已读 67 | * 68 | * @param id 留言的ID 69 | * @param userEntity 用户信息 70 | * @return 操作是否成功 71 | */ 72 | boolean setRead(Integer id, UserEntity userEntity); 73 | 74 | /** 75 | * 查询个数 76 | * 77 | * @param userId 用户Id 78 | * @return 所属该用户的留言条数 79 | */ 80 | int findCountByUserId(Integer userId); 81 | 82 | /** 83 | * 留言 84 | * 85 | * @param leaveMsgDto 留言 86 | * @return 是否成功 87 | */ 88 | boolean insertOne(LeaveMsgDto leaveMsgDto); 89 | 90 | 91 | /** 92 | * 更新留言 93 | * 94 | * @param leaveMsgEntity 更新 95 | * @return 是否更新成功 96 | */ 97 | boolean updateOne(LeaveMsgEntity leaveMsgEntity); 98 | 99 | /** 100 | * 删除 101 | * 102 | * @param id 删除的留言ID 103 | * @param userEntity 登录的用户 104 | * @return 是否删除成功 105 | */ 106 | boolean deleteOne(Integer id, UserEntity userEntity); 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/LinkService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.LinkEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface LinkService { 9 | 10 | LinkEntity findById(Integer id); 11 | 12 | boolean insert(LinkEntity linkEntity, UserEntity userEntity); 13 | 14 | boolean update(LinkEntity linkEntity, UserEntity userEntity); 15 | 16 | boolean deleteById(Integer id, UserEntity userEntity); 17 | 18 | List findAllByBoxId(Integer boxId); 19 | 20 | /** 21 | * 根据盒子ID,找到其所有下所有链接 22 | * @param boxId 盒子id 23 | * @return 条数 24 | */ 25 | int findCountByBoxId(Integer boxId); 26 | 27 | /** 28 | * 删除所有所属于该盒子的链接 29 | * @param boxId 盒子id 30 | * @return 是否删除有 31 | */ 32 | boolean deleteByBoxId(Integer boxId); 33 | 34 | List search(String keyword); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/NoticeService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.NoticeEntity; 4 | 5 | public interface NoticeService { 6 | 7 | NoticeEntity findByUserId(Integer userId); 8 | 9 | boolean insertOne(NoticeEntity noticeEntity); 10 | 11 | boolean update(NoticeEntity noticeEntity, Integer userId); 12 | 13 | boolean deleteOneById(Integer id); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/SearchSiteService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.SearchSiteEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | import java.util.List; 7 | 8 | public interface SearchSiteService { 9 | 10 | // IPage findByUserIdAndPage(Integer userId); 11 | 12 | List findByUserId(Integer userId); 13 | 14 | SearchSiteEntity findById(Integer id); 15 | 16 | boolean insertOne(SearchSiteEntity noticeEntity); 17 | 18 | boolean update(SearchSiteEntity noticeEntity, UserEntity userEntity); 19 | 20 | boolean deleteOneById(Integer id, UserEntity userEntity); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/SiteConfigService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.SiteConfigEntity; 4 | import com.ujuji.navigation.model.entity.UserEntity; 5 | 6 | public interface SiteConfigService { 7 | 8 | SiteConfigEntity findById(Integer id); 9 | 10 | SiteConfigEntity findBySuffix(String suffix); 11 | 12 | SiteConfigEntity findByUserId(Integer userId); 13 | 14 | boolean insertOne(SiteConfigEntity siteConfigEntity, UserEntity userEntity); 15 | 16 | boolean updateOne(SiteConfigEntity siteConfigEntity, UserEntity userEntity); 17 | 18 | boolean deleteOne(Integer id, UserEntity userEntity); 19 | 20 | boolean suffixAvailable(String suffix); 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.dto.ForgotPassDto; 4 | import com.ujuji.navigation.model.dto.UpdatePassWithCodeDto; 5 | import com.ujuji.navigation.model.dto.UserDto; 6 | import com.ujuji.navigation.model.entity.BoxEntity; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | 10 | import java.util.List; 11 | 12 | public interface UserService extends UserDetailsService { 13 | UserEntity findByUsername(String username); 14 | 15 | UserEntity findById(Integer id); 16 | 17 | UserEntity findByEmail(String email); 18 | 19 | /** 20 | * 修改密码 21 | * 22 | * @param updatePassWithCodeDto 修改的密码的对象 23 | * @return 是否修改成 24 | */ 25 | boolean updatePassWithCode(UpdatePassWithCodeDto updatePassWithCodeDto); 26 | 27 | /** 28 | * 先判断用户和邮箱是否存在,存在的话就发送验证码码 29 | * 30 | * @return 是否发送验证码成功 31 | */ 32 | boolean sendForgotPasswordEmail(ForgotPassDto forgotPassDto); 33 | 34 | 35 | Boolean register(UserDto userDto); 36 | 37 | List findBoxesAndLinksBySuffix(String suffix); 38 | 39 | /** 40 | * 备份数据 41 | * 42 | * @param userEntity 用户信息 43 | * @return 备份信息 44 | */ 45 | List findBoxesBackup(UserEntity userEntity); 46 | 47 | 48 | /** 49 | * @param oldPass 旧密码 50 | * @param newPass 新密码 51 | * @param userEntity 通过security 得到的用户信息 52 | * @return 是否修改成功 53 | */ 54 | boolean updatePassword(String oldPass, String newPass, UserEntity userEntity); 55 | 56 | /** 57 | * 生成token 58 | * 59 | * @return 生成的token 60 | */ 61 | String generateAccessToken(); 62 | 63 | 64 | /** 65 | * 刷新token 66 | * 67 | * @param userEntity 用户 68 | * @param token token 69 | * @return 是否添加成功 70 | */ 71 | boolean updateToken(UserEntity userEntity, String token); 72 | 73 | UserEntity findUserByToken(String token); 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/AdminBoxServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.ujuji.navigation.exception.MyException; 7 | import com.ujuji.navigation.mapper.BoxMapper; 8 | import com.ujuji.navigation.model.entity.BoxEntity; 9 | import com.ujuji.navigation.service.AdminBoxService; 10 | import com.ujuji.navigation.service.BoxService; 11 | import com.ujuji.navigation.service.LinkService; 12 | import com.ujuji.navigation.util.ResultCode; 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.annotation.Resource; 17 | 18 | @Service 19 | public class AdminBoxServiceImpl implements AdminBoxService { 20 | @Resource 21 | BoxMapper boxMapper; 22 | 23 | @Override 24 | public IPage findAllByPage(int pageNum, int pageSize) { 25 | IPage page = new Page<>(pageNum, pageSize); 26 | QueryWrapper wrapper = new QueryWrapper<>(); 27 | wrapper.orderByDesc("id"); 28 | return boxMapper.selectPage(page, wrapper); 29 | } 30 | 31 | @Resource 32 | LinkService linkService; 33 | @Resource 34 | BoxService boxService; 35 | 36 | @Override 37 | public IPage searchByPage(String key, int pageNum, int pageSize) { 38 | QueryWrapper wrapper = new QueryWrapper<>(); 39 | IPage page = new Page<>(pageNum, pageSize); 40 | try { 41 | final Integer id = Integer.valueOf(key); 42 | wrapper.eq("id", id).or().like("title", key); 43 | } catch (NumberFormatException e) { 44 | wrapper.like("title", key); 45 | } 46 | return boxMapper.selectPage(page, wrapper); 47 | } 48 | 49 | @Override 50 | public boolean deleteOne(Integer boxId) { 51 | final BoxEntity box = boxService.findById(boxId); 52 | linkService.deleteByBoxId(box.getUserId());//删除所属该盒子的所有链接 53 | return boxMapper.deleteById(boxId) > 0; 54 | } 55 | 56 | @Override 57 | public boolean updateOne(BoxEntity boxEntity) { 58 | if (StringUtils.isBlank(boxEntity.getId().toString()) || boxEntity.getId() == 0) { 59 | throw new MyException(ResultCode.PLEASE_INPUT_ID); 60 | } 61 | 62 | return boxMapper.updateById(boxEntity) > 0; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/AdminLinkServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.ujuji.navigation.exception.MyException; 7 | import com.ujuji.navigation.mapper.LinkMapper; 8 | import com.ujuji.navigation.model.entity.LinkEntity; 9 | import com.ujuji.navigation.service.AdminLinkService; 10 | import com.ujuji.navigation.util.ResultCode; 11 | import org.springframework.stereotype.Service; 12 | 13 | import javax.annotation.Resource; 14 | 15 | @Service 16 | public class AdminLinkServiceImpl implements AdminLinkService { 17 | @Resource 18 | LinkMapper linkMapper; 19 | 20 | @Override 21 | public IPage findAllByPage(int pageNum, int pageSize) { 22 | IPage page = new Page<>(pageNum, pageSize); 23 | QueryWrapper wrapper = new QueryWrapper<>(); 24 | wrapper.orderByDesc("id"); 25 | return linkMapper.selectPage(page, wrapper); 26 | } 27 | 28 | @Override 29 | public boolean deleteOne(Integer linkId) { 30 | return linkMapper.deleteById(linkId) > 0; 31 | } 32 | 33 | @Override 34 | public IPage searchByPage(String key, int pageNum, int pageSize) { 35 | QueryWrapper wrapper = new QueryWrapper<>(); 36 | IPage page = new Page<>(pageNum, pageSize); 37 | try { 38 | final Integer id = Integer.valueOf(key); 39 | wrapper.eq("id", id).or().like("link", key).or().like("title", key).or().like("description", key); 40 | } catch (NumberFormatException e) { 41 | wrapper.like("link", key).or().like("title", key).or().like("description", key); 42 | } 43 | return linkMapper.selectPage(page, wrapper); 44 | } 45 | 46 | @Override 47 | public boolean updateOne(LinkEntity linkEntity) { 48 | if (linkEntity.getId() == null) { 49 | throw new MyException(ResultCode.PLEASE_INPUT_ID); 50 | } 51 | return linkMapper.updateById(linkEntity) > 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/AdminMsgServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.ujuji.navigation.exception.MyException; 7 | import com.ujuji.navigation.mapper.LeaveMsgMapper; 8 | import com.ujuji.navigation.model.entity.LeaveMsgEntity; 9 | import com.ujuji.navigation.service.AdminMsgService; 10 | import com.ujuji.navigation.service.LeaveMsgService; 11 | import com.ujuji.navigation.util.ResultCode; 12 | import org.springframework.stereotype.Service; 13 | 14 | import javax.annotation.Resource; 15 | 16 | @Service 17 | public class AdminMsgServiceImpl implements AdminMsgService { 18 | @Resource 19 | LeaveMsgService leaveMsgService; 20 | @Resource 21 | LeaveMsgMapper leaveMsgMapper; 22 | 23 | @Override 24 | public IPage findByPage( int pageNo,int pageSize) { 25 | QueryWrapper wrapper = new QueryWrapper<>(); 26 | wrapper.orderByDesc("id"); 27 | IPage page = new Page<>(pageNo, pageSize); 28 | return leaveMsgMapper.selectPage(page, wrapper); 29 | } 30 | 31 | @Override 32 | public boolean deleteOne(Integer id) { 33 | final LeaveMsgEntity msgEntity = leaveMsgService.findById(id); 34 | if (msgEntity == null) { 35 | throw new MyException(ResultCode.LEAVE_MSG_NOT_EXISTED); 36 | } 37 | return leaveMsgMapper.deleteById(id) > 0; 38 | } 39 | 40 | @Override 41 | public boolean updateOneById(LeaveMsgEntity leaveMsgEntity) { 42 | return leaveMsgService.updateOne(leaveMsgEntity); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/AdminUserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.ujuji.navigation.exception.MyException; 7 | import com.ujuji.navigation.mapper.UserMapper; 8 | import com.ujuji.navigation.model.entity.UserEntity; 9 | import com.ujuji.navigation.service.AdminUserService; 10 | import com.ujuji.navigation.service.UserService; 11 | import com.ujuji.navigation.util.ResultCode; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.annotation.Resource; 17 | 18 | @Service 19 | public class AdminUserServiceImpl implements AdminUserService { 20 | @Resource 21 | UserMapper userMapper; 22 | @Resource 23 | UserService userService; 24 | @Resource 25 | PasswordEncoder passwordEncoder; 26 | 27 | @Override 28 | public IPage findAllByPage(int pageNum, int pageSize) { 29 | IPage page = new Page<>(pageNum, pageSize); 30 | QueryWrapper wrapper = new QueryWrapper<>(); 31 | wrapper.orderByDesc("id"); 32 | return userMapper.selectPage(page, wrapper); 33 | } 34 | 35 | 36 | @Override 37 | public boolean deleteOne(Integer userId) { 38 | return userMapper.deleteById(userId) > 0; 39 | } 40 | 41 | @Override 42 | public IPage searchByPage(String key, int pageNum, int pageSize) { 43 | IPage page = new Page<>(pageNum, pageSize); 44 | QueryWrapper wrapper = new QueryWrapper<>(); 45 | try { 46 | final Integer id = Integer.valueOf(key); 47 | wrapper.eq("id", id); 48 | } catch (NumberFormatException e) { 49 | wrapper.like("username", key).or().like("email", key); 50 | } 51 | return userMapper.selectPage(page, wrapper); 52 | } 53 | 54 | @Override 55 | public boolean updateOne(UserEntity userEntity) { 56 | if (StringUtils.isBlank(userEntity.getId().toString()) || userEntity.getId() == 0) { 57 | throw new MyException(ResultCode.PLEASE_INPUT_ID); 58 | } 59 | UserEntity oldUser = userService.findById(userEntity.getId()); 60 | if (StringUtils.isNoneBlank(userEntity.getEmail()) && !userEntity.getEmail().equals(oldUser.getEmail())) { 61 | UserEntity byEmail = userService.findByEmail(userEntity.getEmail()); 62 | if (byEmail != null) { 63 | throw new MyException(ResultCode.EMAIL_EXISTED); 64 | } 65 | } 66 | 67 | //修改密码 68 | if (StringUtils.isNoneBlank(userEntity.getPassword())) { 69 | userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword())); 70 | } 71 | int i = userMapper.updateById(userEntity); 72 | return i > 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/BoxServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.BoxMapper; 6 | import com.ujuji.navigation.model.entity.BoxEntity; 7 | import com.ujuji.navigation.model.entity.LinkEntity; 8 | import com.ujuji.navigation.model.entity.UserEntity; 9 | import com.ujuji.navigation.service.BoxService; 10 | import com.ujuji.navigation.service.LinkService; 11 | import com.ujuji.navigation.service.UserService; 12 | import com.ujuji.navigation.util.ResultCode; 13 | import lombok.extern.slf4j.Slf4j; 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.springframework.stereotype.Service; 16 | 17 | import javax.annotation.Resource; 18 | import java.util.List; 19 | import java.util.Objects; 20 | 21 | @Service("userBoxService") 22 | @Slf4j 23 | public class BoxServiceImpl implements BoxService { 24 | @Resource 25 | BoxMapper boxMapper; 26 | 27 | @Resource 28 | LinkService linkService; 29 | @Resource 30 | UserService userService; 31 | 32 | @Override 33 | public List findByUserId(Integer userId) { 34 | QueryWrapper wrapper = new QueryWrapper<>(); 35 | wrapper.eq("user_id", userId).orderByDesc("box_order").orderByAsc("id"); 36 | return boxMapper.selectList(wrapper); 37 | } 38 | 39 | @Override 40 | public List findByUserIdWithoutPwd(Integer userId) { 41 | QueryWrapper wrapper = new QueryWrapper<>(); 42 | wrapper.eq("user_id", userId).eq("pwd", "").orderByDesc("box_order").orderByAsc("id"); 43 | return boxMapper.selectList(wrapper); 44 | } 45 | 46 | @Override 47 | public BoxEntity findById(Integer id) { 48 | log.info("find Box"); 49 | QueryWrapper wrapper = new QueryWrapper<>(); 50 | wrapper.eq("id", id); 51 | return boxMapper.selectOne(wrapper); 52 | } 53 | 54 | @Override 55 | public BoxEntity findByPwd(Integer id, String pwd) { 56 | 57 | QueryWrapper wrapper = new QueryWrapper<>(); 58 | wrapper.eq("id", id); 59 | final BoxEntity boxEntity = boxMapper.selectOne(wrapper); 60 | if (boxEntity == null) { 61 | throw new MyException(ResultCode.BOX_NOT_EXISTED); 62 | } 63 | if (!StringUtils.equals(boxEntity.getPwd(), pwd)) { 64 | throw new MyException(ResultCode.BOX_PWD_ERROR); 65 | } 66 | //查询出密码 67 | final List allByBoxId = linkService.findAllByBoxId(boxEntity.getId()); 68 | boxEntity.setLinks(allByBoxId); 69 | return boxEntity; 70 | } 71 | 72 | @Override 73 | public BoxEntity findByTitleAndUid(String title, Integer userId) { 74 | 75 | QueryWrapper wrapper = new QueryWrapper<>(); 76 | wrapper.eq("title", title).eq("user_id", userId); 77 | log.info("findByTitleAndUid {} - {}", title, userId); 78 | try { 79 | return boxMapper.selectOne(wrapper); 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | } 83 | return null; 84 | } 85 | 86 | @Override 87 | public boolean deleteById(Integer id, UserEntity userInfo) { 88 | log.info("delete box {} - {}", id, userInfo.toString()); 89 | BoxEntity box = findById(id); 90 | if (box != null) { 91 | if (!userInfo.getId().equals(Objects.requireNonNull(box.getUserId()))) { 92 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 93 | } 94 | 95 | int num = linkService.findCountByBoxId(box.getId()); 96 | if (num > 0) {// 删除其子分类 97 | linkService.deleteByBoxId(box.getId()); 98 | } 99 | 100 | return boxMapper.deleteById(id) > 0; 101 | } 102 | return false; 103 | } 104 | 105 | @Override 106 | public boolean insertOne(BoxEntity boxEntity, UserEntity userInfo) { 107 | log.info("insert box {}", boxEntity.toString()); 108 | BoxEntity box = findByTitleAndUserId(boxEntity); 109 | if (box != null) { 110 | throw new MyException(ResultCode.USER_HAS_BOX); 111 | } 112 | if (!userInfo.getId().equals(Objects.requireNonNull(boxEntity.getUserId()))) {//只能为 113 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 114 | } 115 | return boxMapper.insert(boxEntity) > 0; 116 | } 117 | 118 | @Override 119 | public BoxEntity findByTitleAndUserId(BoxEntity boxEntity) { 120 | QueryWrapper wrapper = new QueryWrapper<>(); 121 | wrapper.eq("user_id", boxEntity.getUserId()).eq("title", boxEntity.getTitle()); 122 | return boxMapper.selectOne(wrapper); 123 | } 124 | 125 | @Override 126 | public boolean updateById(BoxEntity boxEntity, UserEntity userInfo) { 127 | log.info("update box {}", boxEntity.toString()); 128 | if (boxEntity.getId() == null) { 129 | throw new MyException(ResultCode.PLEASE_INPUT_ID); 130 | } 131 | BoxEntity box2 = findById(boxEntity.getId()); 132 | if (box2 == null) { 133 | throw new MyException(ResultCode.BOX_NOT_EXISTED); 134 | } 135 | if (!box2.getUserId().equals(userInfo.getId())) { 136 | throw new MyException(ResultCode.NOT_HAS_PERMISSION_OPERATOR); 137 | } 138 | return boxMapper.updateById(boxEntity) > 0; 139 | } 140 | 141 | public List findBoxesByToken(String token) { 142 | UserEntity userByToken = userService.findUserByToken(token); 143 | if (userByToken == null) { 144 | return null; 145 | } 146 | 147 | return findByUserId(userByToken.getId()); 148 | } 149 | 150 | 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/CardCodeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.core.metadata.IPage; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 6 | import com.ujuji.navigation.core.Constants; 7 | import com.ujuji.navigation.exception.MyException; 8 | import com.ujuji.navigation.mapper.CardCodeMapper; 9 | import com.ujuji.navigation.model.dto.SearchDto; 10 | import com.ujuji.navigation.model.entity.CardCodeEntity; 11 | import com.ujuji.navigation.service.CardCodeService; 12 | import com.ujuji.navigation.util.ResultCode; 13 | import org.apache.commons.lang3.RandomStringUtils; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.annotation.Resource; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | @Service 21 | public class CardCodeServiceImpl implements CardCodeService { 22 | @Resource 23 | private CardCodeMapper cardCodeMapper; 24 | 25 | @Override 26 | public IPage findByPage(Integer pageNo, Integer pageSize) { 27 | 28 | IPage page = new Page<>(pageNo, pageSize); 29 | QueryWrapper wrapper = new QueryWrapper<>(); 30 | wrapper.orderByDesc("id"); 31 | return cardCodeMapper.selectPage(page, wrapper); 32 | } 33 | 34 | @Override 35 | public CardCodeEntity findById(Integer id) { 36 | try { 37 | return cardCodeMapper.selectById(id); 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | 44 | @Override 45 | public IPage search(SearchDto searchDto) { 46 | QueryWrapper wrapper = new QueryWrapper<>(); 47 | wrapper.like("content", searchDto.getKey()); 48 | IPage page = new Page<>(searchDto.getPageNo(), searchDto.getPageSize()); 49 | return cardCodeMapper.selectPage(page, wrapper); 50 | } 51 | 52 | @Override 53 | public List insertMany(String type, int num) { 54 | List cards = new ArrayList<>(); 55 | for (int i = 0; i < num; i++) { 56 | String card = RandomStringUtils.random(Constants.CardCode.CARD_CODE_LENGTH, true, true); 57 | CardCodeEntity cardCodeEntity = new CardCodeEntity(card, false, type, null); 58 | int insert = cardCodeMapper.insert(cardCodeEntity); 59 | if (insert > 0) { 60 | cards.add(card); 61 | } 62 | } 63 | return cards; 64 | } 65 | 66 | @Override 67 | public String insertOne(String type) { 68 | String card = RandomStringUtils.random(Constants.CardCode.CARD_CODE_LENGTH, true, true); 69 | CardCodeEntity cardCodeEntity = new CardCodeEntity(card, false, type, null); 70 | int insert = cardCodeMapper.insert(cardCodeEntity); 71 | return insert > 0 ? card : null; 72 | } 73 | 74 | @Override 75 | public boolean deleteById(Integer id) { 76 | return cardCodeMapper.deleteById(id) > 0; 77 | } 78 | 79 | @Override 80 | public boolean setUsed(Integer cardCodeId, Integer usedBy) { 81 | CardCodeEntity byId = findById(cardCodeId); 82 | if (byId != null) { 83 | byId.setUsed(true); 84 | byId.setUsedBy(usedBy); 85 | int i = cardCodeMapper.updateById(byId); 86 | return i > 0; 87 | } 88 | throw new MyException(ResultCode.SELECT_ONE_FAIL);//记录不存在 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/CommonServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.model.dto.ImportBoxDto; 6 | import com.ujuji.navigation.model.dto.LinkDto; 7 | import com.ujuji.navigation.model.entity.BoxEntity; 8 | import com.ujuji.navigation.model.entity.LinkEntity; 9 | import com.ujuji.navigation.model.entity.UserEntity; 10 | import com.ujuji.navigation.service.BoxService; 11 | import com.ujuji.navigation.service.CommonService; 12 | import com.ujuji.navigation.service.LinkService; 13 | import com.ujuji.navigation.util.*; 14 | import lombok.extern.slf4j.Slf4j; 15 | import org.springframework.stereotype.Service; 16 | 17 | import javax.annotation.Resource; 18 | import java.io.UnsupportedEncodingException; 19 | import java.net.URLEncoder; 20 | 21 | @Service 22 | @Slf4j 23 | public class CommonServiceImpl implements CommonService { 24 | 25 | @Resource 26 | BoxService boxService; 27 | @Resource 28 | LinkService linkService; 29 | @Resource 30 | RedisUtils redisUtils; 31 | 32 | @Override 33 | public Integer importBoxAndLinks(ImportBoxDto importBoxDto) { 34 | UserEntity userInfo = AuthInfo.getUserInfo(); 35 | if (userInfo == null) {// 未登录 36 | throw new MyException(ResultCode.USER_NOT_LOGGED_IN); 37 | } 38 | 39 | Integer userId = userInfo.getId(); 40 | String boxTitle = importBoxDto.getBoxTitle(); 41 | 42 | BoxEntity byTitleAndUid = boxService.findByTitleAndUid(boxTitle, userId); 43 | 44 | if (byTitleAndUid != null) {// 盒子已存在 45 | throw new MyException(ResultCode.IMPORTED_BOX_HAS_EXISTED); 46 | } 47 | BoxEntity boxEntity = new BoxEntity(); 48 | boxEntity.setTitle(importBoxDto.getBoxTitle()); 49 | boxEntity.setUserId(userId); 50 | boolean b = boxService.insertOne(boxEntity, userInfo); 51 | if (!b) {// 插入盒子失败,就不进行导入 52 | throw new MyException(ResultCode.INSERT_BOX_FAILED); 53 | } 54 | int result = 0; 55 | for (LinkDto link : importBoxDto.getLinks()) { 56 | if (!MyUtils.isLink(link.getLink())) continue; 57 | 58 | LinkEntity linkEntity = new LinkEntity(); 59 | linkEntity.setBoxId(boxEntity.getId()); 60 | linkEntity.setTitle(link.getTitle()); 61 | linkEntity.setLink(link.getLink()); 62 | 63 | boolean insert = linkService.insert(linkEntity, userInfo); 64 | if (insert) { 65 | result += 1; 66 | } 67 | } 68 | 69 | return result; 70 | } 71 | 72 | @Override 73 | public String getWeather(String city) { 74 | String apiUrl = Constants.Weather.API_URL; 75 | Object o = redisUtils.get(Constants.Weather.KEY_WEATHER + city); 76 | if (o != null) { 77 | return (String) o; 78 | } 79 | 80 | String url = null; 81 | try { 82 | url = apiUrl.replace("[city]", URLEncoder.encode(city, "utf-8")); 83 | String html = HttpUtils.getHtml(url); 84 | redisUtils.set(Constants.Weather.KEY_WEATHER + city, html, 10 * 60); 85 | return html; 86 | } catch (UnsupportedEncodingException e) { 87 | e.printStackTrace(); 88 | } 89 | return ""; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/EmailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.model.dto.ForgotPassDto; 6 | import com.ujuji.navigation.service.EmailService; 7 | import com.ujuji.navigation.util.RedisUtils; 8 | import com.ujuji.navigation.util.ResultCode; 9 | import com.ujuji.navigation.util.VerifyCodeCheck; 10 | import org.apache.commons.lang3.RandomStringUtils; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.mail.SimpleMailMessage; 13 | import org.springframework.mail.javamail.JavaMailSender; 14 | import org.springframework.scheduling.annotation.Async; 15 | import org.springframework.stereotype.Service; 16 | 17 | import javax.annotation.Resource; 18 | 19 | @Service 20 | public class EmailServiceImpl implements EmailService { 21 | @Resource 22 | JavaMailSender javaMailSender; 23 | @Value("${spring.mail.username}") 24 | private String from; 25 | @Resource 26 | RedisUtils redisUtils; 27 | @Resource 28 | VerifyCodeCheck verifyCodeCheck; 29 | 30 | @Override 31 | public boolean checkHasSent(ForgotPassDto forgotPassDto) { 32 | 33 | //0 先检测图片验证码是否准确 34 | verifyCodeCheck.checkVerifyCode(forgotPassDto.getVerifyCode(), forgotPassDto.getCode()); 35 | 36 | //1 先判断是否已经发送过了 37 | Object o = redisUtils.get(Constants.Mail.KEY_FORGET_CODE_PREFIX + forgotPassDto.getEmail()); 38 | if (o != null) { 39 | throw new MyException(ResultCode.SEND_FORGOT_PASS_TIME_TOO_SHORT); 40 | } 41 | return true; 42 | // sendForgotPassEmail(forgotPassDto.getEmail());//这里再调用真实发送的方法 43 | } 44 | 45 | @Override 46 | @Async 47 | public void sendForgotPassEmail(String email) { 48 | //这里返回void的话,就不能捕获抛出的一次了 49 | 50 | //2 如果没发送过,或者已经过期,那么再次发送 51 | 52 | String random = RandomStringUtils.random(10, true, false); 53 | 54 | redisUtils.set(Constants.Mail.KEY_FORGET_CODE_PREFIX + email, random, 10 * 60);//10min 55 | String content = email + ":您正在找回密码,请输入下面的验证码:\n"; 56 | content += "【" + random + "】" + "\n如果发送错误,请忽略此验证码\n【验证码10分钟内有效】"; 57 | 58 | SimpleMailMessage simpleMessage = new SimpleMailMessage(); 59 | simpleMessage.setTo(email); 60 | simpleMessage.setSubject(Constants.Mail.STRING_FORGET_MAIL_SUBJECT); 61 | simpleMessage.setFrom(from); 62 | simpleMessage.setText(content); 63 | javaMailSender.send(simpleMessage); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/GlobalSettingServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.GlobalSettingMapper; 6 | import com.ujuji.navigation.model.entity.GlobalSettingEntity; 7 | import com.ujuji.navigation.service.GlobalSettingService; 8 | import com.ujuji.navigation.util.ResultCode; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.List; 14 | import java.util.Objects; 15 | 16 | @Service 17 | public class GlobalSettingServiceImpl implements GlobalSettingService { 18 | @Resource 19 | GlobalSettingMapper globalSettingMapper; 20 | 21 | @Override 22 | public GlobalSettingEntity findById(Integer id) { 23 | try { 24 | return globalSettingMapper.selectById(id); 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | return null; 28 | } 29 | } 30 | 31 | @Override 32 | public GlobalSettingEntity findByName(String name) { 33 | QueryWrapper wrapper = new QueryWrapper<>(); 34 | wrapper.eq("name", name); 35 | 36 | try { 37 | return globalSettingMapper.selectOne(wrapper); 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | 44 | @Override 45 | public List findAll() { 46 | try { 47 | return globalSettingMapper.selectList(null); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | return null; 51 | } 52 | } 53 | 54 | @Override 55 | public boolean deleteById(Integer id) { 56 | // 这里因为在Controller层就验证了权限,只有管理员才能增删改查,所以不用验证用户是谁 57 | return globalSettingMapper.deleteById(id) > 0; 58 | } 59 | 60 | @Override 61 | @Transactional 62 | public boolean insertOne(GlobalSettingEntity globalSettingEntity) { 63 | final GlobalSettingEntity byName = findByName(globalSettingEntity.getName()); 64 | if (byName != null) { 65 | throw new MyException(ResultCode.NAME_EXISTED); 66 | } 67 | return globalSettingMapper.insert(globalSettingEntity) > 0; 68 | } 69 | 70 | @Override 71 | @Transactional 72 | public boolean updateById(GlobalSettingEntity globalSettingEntity) { 73 | if (Objects.isNull(globalSettingEntity.getId())) { 74 | throw new MyException(ResultCode.PLEASE_INPUT_ID); 75 | } 76 | return globalSettingMapper.updateById(globalSettingEntity) > 0; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/LinkServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.LinkMapper; 6 | import com.ujuji.navigation.model.entity.BoxEntity; 7 | import com.ujuji.navigation.model.entity.LinkEntity; 8 | import com.ujuji.navigation.model.entity.UserEntity; 9 | import com.ujuji.navigation.service.BoxService; 10 | import com.ujuji.navigation.service.LinkService; 11 | import com.ujuji.navigation.util.ResultCode; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.stereotype.Service; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.List; 17 | 18 | @Service("userLinkService") 19 | @Slf4j 20 | public class LinkServiceImpl implements LinkService { 21 | @Resource 22 | LinkMapper linkMapper; 23 | @Resource(name = "userBoxService") 24 | BoxService boxService; 25 | 26 | @Override 27 | public LinkEntity findById(Integer id) { 28 | 29 | QueryWrapper wrapper = new QueryWrapper<>(); 30 | wrapper.eq("id", id); 31 | try { 32 | return linkMapper.selectOne(wrapper); 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | return null; 36 | } 37 | } 38 | 39 | @Override 40 | public boolean insert(LinkEntity linkEntity, UserEntity userEntity) { 41 | log.info("insert Link {}", linkEntity.toString()); 42 | BoxEntity box = boxService.findById(linkEntity.getBoxId()); 43 | // 想要增加的链接的盒子不属于他 44 | if (!box.getUserId().equals(userEntity.getId())) { 45 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 46 | } 47 | 48 | int insert = linkMapper.insert(linkEntity); 49 | return insert > 0; 50 | } 51 | 52 | @Override 53 | public boolean update(LinkEntity linkEntity, UserEntity userEntity) { 54 | log.info("update link {}", linkEntity.toString()); 55 | BoxEntity box = boxService.findById(linkEntity.getBoxId()); 56 | if (box == null) { 57 | throw new MyException(ResultCode.BOX_NOT_EXISTED); 58 | } 59 | // 想要操作的链接的盒子不属于他 60 | if (!box.getUserId().equals(userEntity.getId())) { 61 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 62 | } 63 | 64 | return linkMapper.updateById(linkEntity) > 0; 65 | 66 | } 67 | 68 | @Override 69 | public boolean deleteById(Integer id, UserEntity userEntity) { 70 | log.info("delete link {} - {}", id, userEntity.toString()); 71 | LinkEntity linkEntity = findById(id); 72 | if (linkEntity == null) { 73 | throw new MyException(ResultCode.LINK_NOT_EXISTED); 74 | } 75 | BoxEntity box = boxService.findById(linkEntity.getBoxId()); 76 | if (box == null) { 77 | throw new MyException(ResultCode.BOX_NOT_EXISTED); 78 | } 79 | // 想要操作的链接的盒子不属于他 80 | if (!box.getUserId().equals(userEntity.getId())) { 81 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 82 | } 83 | return linkMapper.deleteById(linkEntity.getId()) > 0; 84 | 85 | } 86 | 87 | /* @Override 88 | public boolean deleteById(LinkEntity linkEntity, UserEntity userEntity) { 89 | BoxEntity box = boxService.findById(linkEntity.getBoxId()); 90 | if (box == null) { 91 | throw new MyException(ResultCode.BOX_NOT_EXISTED); 92 | } 93 | // 想要操作的链接的盒子不属于他 94 | if (!box.getUserId().equals(userEntity.getId())) { 95 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 96 | } 97 | return linkMapper.deleteById(linkEntity.getId()) > 0; 98 | }*/ 99 | 100 | //暂时先不增加缓存,没到必要的地步 101 | @Override 102 | // @Cacheable(key = "#p0", cacheNames = "cache_links") 103 | public List findAllByBoxId(Integer boxId) { 104 | QueryWrapper wrapper = new QueryWrapper<>(); 105 | wrapper.eq("box_id", boxId).orderByDesc("link_order"); 106 | return linkMapper.selectList(wrapper); 107 | } 108 | 109 | @Override 110 | public int findCountByBoxId(Integer boxId) { 111 | 112 | QueryWrapper wrapper = new QueryWrapper<>(); 113 | wrapper.eq("box_id", boxId); 114 | return linkMapper.selectCount(wrapper); 115 | } 116 | 117 | @Override 118 | public boolean deleteByBoxId(Integer boxId) { 119 | 120 | log.info("deleteByBoxId link boxId:{}", boxId); 121 | QueryWrapper wrapper = new QueryWrapper<>(); 122 | wrapper.eq("box_id", boxId); 123 | return linkMapper.delete(wrapper) > 0; 124 | } 125 | 126 | @Override 127 | public List search(String keyword) { 128 | QueryWrapper wrapper = new QueryWrapper<>(); 129 | wrapper.like("title", keyword).or().like("description", keyword).or().like("link", keyword); 130 | return linkMapper.selectList(wrapper); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/NoticeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.NoticeMapper; 6 | import com.ujuji.navigation.model.entity.NoticeEntity; 7 | import com.ujuji.navigation.service.NoticeService; 8 | import com.ujuji.navigation.util.ResultCode; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | 13 | @Service 14 | public class NoticeServiceImpl implements NoticeService { 15 | @Resource 16 | NoticeMapper noticeMapper; 17 | 18 | @Override 19 | public NoticeEntity findByUserId(Integer userId) { 20 | QueryWrapper wrapper = new QueryWrapper<>(); 21 | wrapper.eq("user_id", userId); 22 | return noticeMapper.selectOne(wrapper); 23 | } 24 | 25 | @Override 26 | public boolean insertOne(NoticeEntity noticeEntity) { 27 | NoticeEntity userId = findByUserId(noticeEntity.getUserId()); 28 | if (userId != null) { 29 | throw new MyException(ResultCode.USER_HAS_NOTICE); 30 | } 31 | return noticeMapper.insert(noticeEntity) > 0; 32 | } 33 | 34 | @Override 35 | public boolean update(NoticeEntity noticeEntity, Integer userId) { 36 | final NoticeEntity old = findByUserId(userId); 37 | if (old != null) { 38 | QueryWrapper wrapper = new QueryWrapper<>(); 39 | wrapper.eq("id", noticeEntity.getId()).eq("user_id", userId); 40 | return noticeMapper.update(noticeEntity, wrapper) > 0; 41 | }else{ 42 | return insertOne(noticeEntity); 43 | } 44 | } 45 | 46 | @Override 47 | public boolean deleteOneById(Integer id) { 48 | return noticeMapper.deleteById(id) > 0; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/SearchSiteServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.SearchSiteMapper; 6 | import com.ujuji.navigation.model.entity.SearchSiteEntity; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import com.ujuji.navigation.service.SearchSiteService; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.springframework.stereotype.Service; 11 | 12 | import javax.annotation.Resource; 13 | import java.util.List; 14 | 15 | @Service 16 | public class SearchSiteServiceImpl implements SearchSiteService { 17 | 18 | @Resource 19 | SearchSiteMapper searchSiteMapper; 20 | 21 | @Override 22 | public List findByUserId(Integer userId) { 23 | QueryWrapper wrapper = new QueryWrapper<>(); 24 | wrapper.eq("user_id", userId).orderByDesc("site_order"); 25 | return searchSiteMapper.selectList(wrapper); 26 | } 27 | 28 | @Override 29 | public SearchSiteEntity findById(Integer id) { 30 | try { 31 | return searchSiteMapper.selectById(id); 32 | } catch (Exception e) { 33 | e.printStackTrace(); 34 | return null; 35 | } 36 | } 37 | 38 | @Override 39 | public boolean insertOne(SearchSiteEntity noticeEntity) { 40 | return searchSiteMapper.insert(noticeEntity) > 0; 41 | } 42 | 43 | @Override 44 | public boolean update(SearchSiteEntity searchSiteEntity, UserEntity userEntity) { 45 | final SearchSiteEntity byId = findById(searchSiteEntity.getId()); 46 | if (byId == null) { 47 | throw new MyException(ResultCode.ITEM_NOT_EXISTS); 48 | } 49 | if (!byId.getUserId().equals(userEntity.getId())) { 50 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 51 | } 52 | return searchSiteMapper.updateById(searchSiteEntity) > 0; 53 | } 54 | 55 | @Override 56 | public boolean deleteOneById(Integer id, UserEntity userEntity) { 57 | final SearchSiteEntity byId = findById(id); 58 | if (byId == null) { 59 | throw new MyException(ResultCode.ITEM_NOT_EXISTS); 60 | } 61 | if (!byId.getUserId().equals(userEntity.getId())) { 62 | throw new MyException(ResultCode.PERMISSION_NOT_MATCH_OPERATION); 63 | } 64 | return searchSiteMapper.deleteById(id) > 0; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/service/impl/SiteConfigServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.ujuji.navigation.exception.MyException; 5 | import com.ujuji.navigation.mapper.SiteConfigMapper; 6 | import com.ujuji.navigation.model.entity.SiteConfigEntity; 7 | import com.ujuji.navigation.model.entity.UserEntity; 8 | import com.ujuji.navigation.service.SiteConfigService; 9 | import com.ujuji.navigation.util.ResultCode; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.stereotype.Service; 12 | 13 | import javax.annotation.Resource; 14 | 15 | @Service 16 | public class SiteConfigServiceImpl implements SiteConfigService { 17 | @Resource 18 | SiteConfigMapper siteConfigMapper; 19 | 20 | @Override 21 | public SiteConfigEntity findById(Integer id) { 22 | 23 | QueryWrapper wrapper = new QueryWrapper<>(); 24 | wrapper.eq("id", id); 25 | try { 26 | return siteConfigMapper.selectOne(wrapper); 27 | } catch (Exception e) { 28 | e.printStackTrace(); 29 | return null; 30 | } 31 | } 32 | 33 | @Override 34 | public SiteConfigEntity findBySuffix(String suffix) { 35 | QueryWrapper wrapper = new QueryWrapper<>(); 36 | wrapper.eq("suffix", suffix); 37 | try { 38 | return siteConfigMapper.selectOne(wrapper); 39 | } catch (Exception e) { 40 | e.printStackTrace(); 41 | throw new MyException(ResultCode.SELECT_ONE_FAIL); 42 | } 43 | } 44 | 45 | @Override 46 | public SiteConfigEntity findByUserId(Integer userId) { 47 | QueryWrapper wrapper = new QueryWrapper<>(); 48 | wrapper.eq("user_id", userId); 49 | try { 50 | return siteConfigMapper.selectOne(wrapper); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | throw new MyException(ResultCode.SELECT_ONE_FAIL); 54 | } 55 | } 56 | 57 | @Override 58 | public boolean insertOne(SiteConfigEntity siteConfigEntity, UserEntity userEntity) { 59 | return siteConfigMapper.insert(siteConfigEntity) > 0; 60 | } 61 | 62 | @Override 63 | public boolean updateOne(SiteConfigEntity siteConfigEntity, UserEntity userEntity) { 64 | SiteConfigEntity site = findByUserId(userEntity.getId()); 65 | if (site == null) { 66 | //等于空的话,就新建一个,不然就更新 67 | return insertOne(siteConfigEntity, userEntity); 68 | } 69 | 70 | 71 | siteConfigEntity.setId(site.getId()); 72 | 73 | if (StringUtils.isNoneBlank(site.getSuffix())) { 74 | siteConfigEntity.setSuffix(null); 75 | } else { 76 | if (StringUtils.isNoneBlank(siteConfigEntity.getSuffix())) { 77 | boolean b = suffixAvailable(siteConfigEntity.getSuffix()); 78 | if (!b) { 79 | throw new MyException(ResultCode.SUFFIX_NOT_AVAILABLE); 80 | } 81 | } 82 | } 83 | return siteConfigMapper.updateById(siteConfigEntity) > 0; 84 | 85 | } 86 | 87 | @Override 88 | public boolean deleteOne(Integer id, UserEntity userEntity) { 89 | SiteConfigEntity siteConfig = findById(id); 90 | if (siteConfig != null) { 91 | if (!siteConfig.getUserId().equals(userEntity.getId())) { 92 | throw new MyException(ResultCode.NOT_HAS_PERMISSION_OPERATOR); 93 | } 94 | return siteConfigMapper.deleteById(id) > 0; 95 | } 96 | return false; 97 | } 98 | 99 | @Override 100 | public boolean suffixAvailable(String suffix) { 101 | 102 | QueryWrapper wrapper = new QueryWrapper<>(); 103 | wrapper.eq("suffix", suffix); 104 | SiteConfigEntity one = siteConfigMapper.selectOne(wrapper); 105 | return one == null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/AppResult.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | public class AppResult { 4 | 5 | private int code; 6 | private String msg; 7 | private T data;// 数据 8 | 9 | public int getCode() { 10 | return code; 11 | } 12 | 13 | public void setCode(int code) { 14 | this.code = code; 15 | } 16 | 17 | public String getMsg() { 18 | return msg; 19 | } 20 | 21 | public void setMsg(String msg) { 22 | this.msg = msg; 23 | } 24 | 25 | public T getData() { 26 | return data; 27 | } 28 | 29 | public void setData(T data) { 30 | this.data = data; 31 | } 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/AppResultBuilder.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | public class AppResultBuilder { 4 | 5 | //成功,不返回具体数据 6 | public static AppResult successNoData(ResultCode code) { 7 | AppResult result = new AppResult(); 8 | result.setCode(code.getCode()); 9 | result.setMsg(code.getMsg()); 10 | return result; 11 | } 12 | 13 | //成功,返回数据 14 | public static AppResult success(T t, ResultCode code) { 15 | AppResult result = new AppResult(); 16 | result.setCode(code.getCode()); 17 | result.setMsg(code.getMsg()); 18 | result.setData(t); 19 | return result; 20 | } 21 | 22 | //失败,返回失败信息 23 | public static AppResult fail(ResultCode code) { 24 | AppResult result = new AppResult(); 25 | result.setCode(code.getCode()); 26 | result.setMsg(code.getMsg()); 27 | return result; 28 | } 29 | 30 | //失败,返回失败信息 31 | public static AppResult fail(String msg, ResultCode code) { 32 | AppResult result = new AppResult(); 33 | result.setCode(code.getCode()); 34 | result.setMsg(msg); 35 | return result; 36 | } //失败,返回失败信息 37 | 38 | public static AppResult fail(String msg) { 39 | AppResult result = new AppResult(); 40 | result.setMsg(msg); 41 | return result; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/AuthInfo.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.model.entity.UserEntity; 4 | import org.springframework.security.core.context.SecurityContext; 5 | import org.springframework.security.core.context.SecurityContextHolder; 6 | 7 | public class AuthInfo { 8 | 9 | public static UserEntity getUserInfo() { 10 | try { 11 | SecurityContext context = SecurityContextHolder.getContext(); 12 | return (UserEntity) context.getAuthentication().getPrincipal(); 13 | } catch (Exception e) { 14 | e.printStackTrace(); 15 | return null; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | import okhttp3.Call; 5 | import okhttp3.OkHttpClient; 6 | import okhttp3.Request; 7 | import okhttp3.Response; 8 | 9 | import java.io.IOException; 10 | 11 | public class HttpUtils { 12 | 13 | public static String getHtml(String url) { 14 | OkHttpClient client = new OkHttpClient(); 15 | 16 | Request request = new Request.Builder() 17 | .url(url) 18 | .addHeader("User-Agent", Constants.Common.UA) 19 | .build(); 20 | 21 | Call call = client.newCall(request); 22 | try { 23 | Response response = call.execute(); 24 | assert response.body() != null; 25 | return response.body().string(); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | return ""; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/JwtUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.model.entity.UserEntity; 4 | import io.jsonwebtoken.Claims; 5 | import io.jsonwebtoken.Jwts; 6 | import io.jsonwebtoken.SignatureAlgorithm; 7 | import lombok.Data; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.boot.context.properties.ConfigurationProperties; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.io.Serializable; 14 | import java.util.Date; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | @Data 19 | @ConfigurationProperties(prefix = "jwt") 20 | @Component 21 | @Slf4j 22 | public class JwtUtils implements Serializable { 23 | 24 | private String secret; 25 | 26 | private Long expiration; 27 | 28 | private String header; 29 | 30 | private String prefix; 31 | 32 | 33 | 34 | /** 35 | * 从数据声明生成令牌 36 | * 37 | * @param claims 数据声明 38 | * @return 令牌 39 | */ 40 | private String generateToken(Map claims) { 41 | Date expirationDate = new Date(System.currentTimeMillis() + expiration); 42 | return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact(); 43 | } 44 | 45 | /** 46 | * 从令牌中获取数据声明 47 | * 48 | * @param token 令牌 49 | * @return 数据声明 50 | */ 51 | private Claims getClaimsFromToken(String token) { 52 | Claims claims; 53 | try { 54 | claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); 55 | } catch (Exception e) { 56 | claims = null; 57 | } 58 | return claims; 59 | } 60 | 61 | /** 62 | * 生成令牌 63 | * 64 | * @param userDetails 用户 65 | * @return 令牌 66 | */ 67 | public String generateToken(UserDetails userDetails) { 68 | Map claims = new HashMap<>(2); 69 | claims.put("sub", userDetails.getUsername()); 70 | claims.put("created", new Date()); 71 | return generateToken(claims); 72 | } 73 | 74 | /** 75 | * 从令牌中获取用户名 76 | * 77 | * @param token 令牌 78 | * @return 用户名 79 | */ 80 | public String getUsernameFromToken(String token) { 81 | String username; 82 | try { 83 | Claims claims = getClaimsFromToken(token); 84 | username = claims.getSubject(); 85 | } catch (Exception e) { 86 | username = null; 87 | } 88 | return username; 89 | } 90 | 91 | /** 92 | * 判断令牌是否过期 93 | * 94 | * @param token 令牌 95 | * @return 是否过期 96 | */ 97 | public Boolean isTokenExpired(String token) { 98 | try { 99 | Claims claims = getClaimsFromToken(token); 100 | Date expiration = claims.getExpiration(); 101 | return expiration.before(new Date()); 102 | } catch (Exception e) { 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * 刷新令牌 109 | * 110 | * @param token 原令牌 111 | * @return 新令牌 112 | */ 113 | public String refreshToken(String token) { 114 | String refreshedToken; 115 | try { 116 | Claims claims = getClaimsFromToken(token); 117 | claims.put("created", new Date()); 118 | refreshedToken = generateToken(claims); 119 | } catch (Exception e) { 120 | refreshedToken = null; 121 | } 122 | return refreshedToken; 123 | } 124 | 125 | /** 126 | * 验证令牌 127 | * 128 | * @param token 令牌 129 | * @param userDetails 用户 130 | * @return 是否有效 131 | */ 132 | public Boolean validateToken(String token, UserDetails userDetails) { 133 | UserEntity user = (UserEntity) userDetails; 134 | String username = getUsernameFromToken(token); 135 | return (username.equals(user.getUsername()) && !isTokenExpired(token)); 136 | } 137 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/MyBeanUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import org.springframework.beans.BeanUtils; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.function.Supplier; 8 | 9 | public class MyBeanUtils extends BeanUtils { 10 | public static List copyListProperties(List sources, Supplier target) { 11 | return copyListProperties(sources, target, null); 12 | } 13 | 14 | /** 15 | * @author Johnson 16 | * 使用场景:Entity、Bo、Vo层数据的复制,因为BeanUtils.copyProperties只能给目标对象的属性赋值,却不能在List集合下循环赋值,因此添加该方法 17 | * 如:List 赋值到 List ,List中的 AdminVo 属性都会被赋予到值 18 | * S: 数据源类 ,T: 目标类::new(eg: AdminVo::new) 19 | */ 20 | public static List copyListProperties(List sources, Supplier target, MyBeanUtilsCallBack callBack) { 21 | List list = new ArrayList<>(sources.size()); 22 | for (S source : sources) { 23 | T t = target.get(); 24 | copyProperties(source, t); 25 | list.add(t); 26 | if (callBack != null) { 27 | // 回调 28 | callBack.callBack(source, t); 29 | } 30 | } 31 | return list; 32 | } 33 | } 34 | 35 | @FunctionalInterface 36 | interface MyBeanUtilsCallBack { 37 | 38 | void callBack(S t, T s); 39 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/MyUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | 5 | import java.util.regex.Matcher; 6 | import java.util.regex.Pattern; 7 | 8 | public class MyUtils { 9 | public static Boolean isLink(String link) { 10 | Pattern compile = Pattern.compile(Constants.REGEX.LINK_REGEX); 11 | Matcher matcher = compile.matcher(link); 12 | return matcher.find(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/ResultCode.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | //状态码 4 | public enum ResultCode { 5 | /* 成功状态码 */ 6 | SUCCESS(1000, "成功"), 7 | 8 | /* 参数错误:10001-19999 */ 9 | PARAM_IS_INVALID(10001, "参数无效"), 10 | PARAM_IS_BLANK(10002, "参数为空"), 11 | PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"), 12 | PARAM_NOT_COMPLETE(10004, "参数缺失"), 13 | 14 | /* 用户错误:20001-29999*/ 15 | USER_NOT_LOGGED_IN(20001, "用户未登录"), 16 | USER_LOGIN_ERROR(20002, "账号不存在或密码错误"), 17 | USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"), 18 | USER_NOT_EXIST(20004, "用户不存在"), 19 | USER_HAS_EXISTED(20005, "用户已存在"), 20 | USER_PASSWORD_ERROR(20006, "用户密码错误"), 21 | USER_PASSWORD_MODIFY_SUCCESS(20007, "修改密码成功"), 22 | USER_PASSWORD_MODIFY_FAIL(20008, "修改密码失败"), 23 | USER_LOGIN_SUCCESS(20009, "登录成功"), 24 | USER_LOGIN_FAIL(20010, "登录失败,请检查用户名和密码"), 25 | USER_REGISTER_SUCCESS(20011, "注册成功"), 26 | USER_REGISTER_FAIL(20012, "注册失败"), 27 | USER_OLD_PASS_ERROR(20013, "旧密码错误"), 28 | EMAIL_EXISTED(20014, "邮箱已存在"), 29 | VERIFY_CODE_ERROR(20015, "验证码错误"), 30 | VERIFY_CODE_EXPIRED(20016, "验证码过期请重新验证"), 31 | PLEASE_VERIFY_CODE(20017, "请输入验证码"), 32 | USERNAME_EMAIL_NOT_MATCH(20018, "请确认用户名和邮箱匹配"), 33 | FIND_PASS_EMAIL_SEND_SUCCESS(20019, "重置密码邮件验证码已发送成功"), 34 | GENERATE_TOKEN_SUCCESS(20020, "生成access_token成功"), 35 | GENERATE_TOKEN_FAIL(20021, "生成access_token失败"), 36 | 37 | 38 | /*业务:30001-39999*/ 39 | SERVICE_QUERY_FAIL(30001, "查询失败"), 40 | SERVICE_INSERT_SUCCESS(30002, "添加成功"), 41 | SERVICE_INSERT_FAIL(30003, "添加失败"), 42 | SERVICE_DELETE_SUCCESS(30004, "删除成功"), 43 | SERVICE_DELETE_FAIL(30005, "删除失败"), 44 | SERVICE_UPDATE_SUCCESS(30006, "修改成功"), 45 | SERVICE_UPDATE_FAIL(30007, "修改失败"), 46 | 47 | USER_HAS_NOTICE(31001, "用户已存在一个公告,不能再次创建"), 48 | USER_HAS_BOX(31002, "存在相同的一个盒子,不能创建"), 49 | PLEASE_INPUT_USER_ID(31003, "抱歉,请输入用户ID"), 50 | NOT_HAS_PERMISSION_OPERATOR(31004, "您没有操作此项操作的权限"), 51 | PLEASE_INPUT_ID(31005, "请输入ID"), 52 | BOX_NOT_EXISTED(31006, "盒子不存在,请检查"), 53 | LINK_NOT_EXISTED(31007, "链接不存在,请检查"), 54 | BOX_NOT_FOUND(31008, "未找到该导航"), 55 | SELECT_ONE_FAIL(31009, "查询单条记录失败"), 56 | SUFFIX_NOT_AVAILABLE(31010, "此后缀(标签)不可用,请更换"), 57 | NAME_EXISTED(31011, "名称已存在"), 58 | SUFFIX_NOT_EXISTED(31012, "此后缀不存在"), 59 | BOX_PWD_ERROR(31013, "盒子密码错误"), 60 | SUFFIX_LENGTH_ERROR(31014, "站点后缀长度小于规定"), 61 | LEAVE_MSG_NOT_EXISTED(31015, "留言不存在"), 62 | SET_MSG_FIXED_SUCCESS(31016, "留言置/取顶成功"), 63 | SET_MSG_FIXED_FAIL(31017, "留言置/取顶失败"), 64 | REPLY_MSG_SUCCESS(31018, "回复留言成功"), 65 | REPLY_MSG_FAIL(31019, "回复留言失败"), 66 | ITEM_NOT_EXISTS(31020, "该条目不存在"), 67 | SET_MSG_READ_FAIL(31021, "设置留言已读失败"), 68 | SET_MSG_READ_SUCCESS(31022, "设置留言已读成功"), 69 | GENERATE_VERIFY_CODE_FAIL(31023, "生成验证码失败"), 70 | UNKNOWN_ERROR(31024, "未知错误"), 71 | MSG_TIME_TOO_SHORT(31025, "距离上次留言时间过短,暂不可留言"), 72 | SEND_FORGOT_PASS_TIME_TOO_SHORT(31026, "验证码已经发送过了,请检查您的垃圾箱"), 73 | IMPORTED_BOX_HAS_EXISTED(31027, "用户已存在相同标题的一个,请删除后导入!"), 74 | INSERT_BOX_FAILED(31028, "创建盒子失败,此次导入失败"), 75 | IMPORT_FAILED(31029, "导入失败,请收好重试"), 76 | TOKEN_EMPTY(31030, "AccessToken错误"), 77 | 78 | 79 | /* 权限错误:70001-79999 */ 80 | PERMISSION_NO_ACCESS(70001, "无访问权限"), 81 | PERMISSION_NO_OPERATION(70002, "无操作权限"), 82 | PERMISSION_NOT_MATCH_OPERATION(70003, "无操作权限"), 83 | VISIT_TOO_OFTEN(70004, "操作太频繁了,请稍后重试"), 84 | ACCESS_TOKEN_ERROR(70005, "AccessToken无效"); 85 | 86 | private final Integer code; 87 | private final String msg; 88 | 89 | ResultCode(Integer code, String msg) { 90 | this.code = code; 91 | this.msg = msg; 92 | } 93 | 94 | public Integer getCode() { 95 | return code; 96 | } 97 | 98 | public String getMsg() { 99 | return msg; 100 | } 101 | } -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/SnowflakeIdUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | public class SnowflakeIdUtils { 4 | // ==============================Fields=========================================== 5 | 6 | /** 7 | * 机器id所占的位数 8 | */ 9 | private final long workerIdBits = 5L; 10 | 11 | /** 12 | * 数据标识id所占的位数 13 | */ 14 | private final long datacenterIdBits = 5L; 15 | 16 | /** 17 | * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) 18 | */ 19 | private final long maxWorkerId = -1L ^ (-1L << workerIdBits); 20 | 21 | /** 22 | * 支持的最大数据标识id,结果是31 23 | */ 24 | private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 25 | 26 | /** 27 | * 序列在id中占的位数 28 | */ 29 | private final long sequenceBits = 12L; 30 | 31 | /** 32 | * 机器ID向左移12位 33 | */ 34 | private final long workerIdShift = sequenceBits; 35 | 36 | /** 37 | * 数据标识id向左移17位(12+5) 38 | */ 39 | private final long datacenterIdShift = sequenceBits + workerIdBits; 40 | 41 | /** 42 | * 时间截向左移22位(5+5+12) 43 | */ 44 | private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 45 | 46 | /** 47 | * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) 48 | */ 49 | private final long sequenceMask = -1L ^ (-1L << sequenceBits); 50 | 51 | /** 52 | * 工作机器ID(0~31) 53 | */ 54 | private long workerId; 55 | 56 | /** 57 | * 数据中心ID(0~31) 58 | */ 59 | private long datacenterId; 60 | 61 | /** 62 | * 毫秒内序列(0~4095) 63 | */ 64 | private long sequence = 0L; 65 | 66 | /** 67 | * 上次生成ID的时间截 68 | */ 69 | private long lastTimestamp = -1L; 70 | 71 | //==============================Constructors===================================== 72 | 73 | /** 74 | * 构造函数 75 | * 76 | * @param workerId 工作ID (0~31) 77 | * @param dataCenterId 数据中心ID (0~31) 78 | */ 79 | public SnowflakeIdUtils(long workerId, long dataCenterId) { 80 | if (workerId > maxWorkerId || workerId < 0) { 81 | throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 82 | } 83 | if (dataCenterId > maxDatacenterId || dataCenterId < 0) { 84 | throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 85 | } 86 | this.workerId = workerId; 87 | this.datacenterId = dataCenterId; 88 | } 89 | 90 | // ==============================Methods========================================== 91 | 92 | /** 93 | * 获得下一个ID (该方法是线程安全的) 94 | * 95 | * @return SnowflakeId 96 | */ 97 | public synchronized long nextId() { 98 | long timestamp = timeGen(); 99 | 100 | //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 101 | if (timestamp < lastTimestamp) { 102 | throw new RuntimeException( 103 | String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 104 | } 105 | 106 | //如果是同一时间生成的,则进行毫秒内序列 107 | if (lastTimestamp == timestamp) { 108 | sequence = (sequence + 1) & sequenceMask; 109 | //毫秒内序列溢出 110 | if (sequence == 0) { 111 | //阻塞到下一个毫秒,获得新的时间戳 112 | timestamp = tilNextMillis(lastTimestamp); 113 | } 114 | } 115 | //时间戳改变,毫秒内序列重置 116 | else { 117 | sequence = 0L; 118 | } 119 | 120 | //上次生成ID的时间截 121 | lastTimestamp = timestamp; 122 | 123 | //移位并通过或运算拼到一起组成64位的ID 124 | /** 125 | * 开始时间截 (2015-01-01) 126 | */ 127 | long twepoch = 1420041600000L; 128 | return ((timestamp - twepoch) << timestampLeftShift) // 129 | | (datacenterId << datacenterIdShift) // 130 | | (workerId << workerIdShift) // 131 | | sequence; 132 | } 133 | 134 | /** 135 | * 阻塞到下一个毫秒,直到获得新的时间戳 136 | * 137 | * @param lastTimestamp 上次生成ID的时间截 138 | * @return 当前时间戳 139 | */ 140 | protected long tilNextMillis(long lastTimestamp) { 141 | long timestamp = timeGen(); 142 | while (timestamp <= lastTimestamp) { 143 | timestamp = timeGen(); 144 | } 145 | return timestamp; 146 | } 147 | 148 | /** 149 | * 返回以毫秒为单位的当前时间 150 | * 151 | * @return 当前时间(毫秒) 152 | */ 153 | protected long timeGen() { 154 | return System.currentTimeMillis(); 155 | } 156 | 157 | //==============================Test============================================= 158 | 159 | /** 160 | * 测试 161 | */ 162 | public static void main(String[] args) { 163 | SnowflakeIdUtils idWorker = new SnowflakeIdUtils(3, 1); 164 | System.out.println(idWorker.nextId()); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/VerifyCodeCheck.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | import com.ujuji.navigation.exception.MyException; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.annotation.Resource; 10 | 11 | @Component 12 | @Slf4j 13 | public class VerifyCodeCheck { 14 | @Resource 15 | RedisUtils redisUtils; 16 | 17 | /** 18 | * 检查验证码 19 | * 20 | * @param verifyCode 用户输入的验证码 21 | * @param code 验证码的key 22 | * @throws MyException 验证失败异常 23 | */ 24 | public void checkVerifyCode(String verifyCode, String code) throws MyException { 25 | if (StringUtils.isBlank(verifyCode) || StringUtils.isBlank(code)) { 26 | throw new MyException(ResultCode.PLEASE_VERIFY_CODE); 27 | } 28 | 29 | final String originCode = (String) redisUtils.get(Constants.Common.KEY_VERIFY_CODE + code); 30 | log.info("originCode ==>> {} ", originCode); 31 | 32 | if (originCode == null) { 33 | throw new MyException(ResultCode.VERIFY_CODE_EXPIRED); 34 | } 35 | if (!originCode.toLowerCase().equals(verifyCode.toLowerCase())) { 36 | throw new MyException(ResultCode.VERIFY_CODE_ERROR); 37 | } 38 | // 走到这一步说明验证码已经验证成功了,所以这一步 就是清除redis中的数据,同一个验证码不能一直用 39 | redisUtils.del(Constants.Common.KEY_VERIFY_CODE + code); 40 | } 41 | 42 | /** 43 | * 检测修改密码的code是否准确 44 | * 45 | * @param email 电子邮件 46 | * @param code 用户输入的验证码 47 | * @return 是否准确 48 | */ 49 | public boolean checkPasswordCode(String email, String code) { 50 | Object o = redisUtils.get(Constants.Mail.KEY_FORGET_CODE_PREFIX + email); 51 | log.info("o ==>> {}", o); 52 | if (o != null) { 53 | String originCode = (String) o; 54 | log.info("checkPasswordCode ==>> code =>> {}", code); 55 | log.info("checkPasswordCode ==>> originCode =>> {}", originCode); 56 | boolean equals = originCode.equals(code); 57 | if (equals) { 58 | redisUtils.del(Constants.Mail.KEY_FORGET_CODE_PREFIX + email);//删除 59 | return true; 60 | } 61 | } 62 | return false; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/ujuji/navigation/util/VerifyCodeUtils.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.util; 2 | 3 | import com.ujuji.navigation.model.dto.VerifyCodeDto; 4 | import com.wf.captcha.ArithmeticCaptcha; 5 | import com.wf.captcha.SpecCaptcha; 6 | import org.apache.commons.lang3.RandomUtils; 7 | 8 | public class VerifyCodeUtils { 9 | 10 | public static VerifyCodeDto getRandomCode() { 11 | int num = RandomUtils.nextInt(1, 100); 12 | int r = num % 2; 13 | VerifyCodeDto verifyCodeDto = new VerifyCodeDto(); 14 | 15 | switch (r) { 16 | // case 2: 17 | // // 中文类型 18 | // ChineseCaptcha chineseCaptcha = new ChineseCaptcha(120, 40, 3); 19 | // verifyCodeDto.setCode(chineseCaptcha.text()); 20 | // verifyCodeDto.setImage(chineseCaptcha.toBase64()); 21 | // break; 22 | case 1: 23 | //png 24 | SpecCaptcha captcha = new SpecCaptcha(120, 40, 4); 25 | verifyCodeDto.setCode(captcha.text()); 26 | verifyCodeDto.setImage(captcha.toBase64()); 27 | break; 28 | case 0://算术 29 | ArithmeticCaptcha arithmeticCaptcha = new ArithmeticCaptcha(120, 40, 2); 30 | verifyCodeDto.setCode(arithmeticCaptcha.text()); 31 | verifyCodeDto.setImage(arithmeticCaptcha.toBase64()); 32 | break; 33 | } 34 | return verifyCodeDto; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 4037 3 | 4 | #mybatis 5 | mybatis-plus: 6 | # mapper-locations: classpath*:mapper/*.xml 7 | configuration: 8 | map-underscore-to-camel-case: true 9 | 10 | spring: 11 | profiles: 12 | active: dev 13 | 14 | mail: 15 | host: smtp.domain.com 16 | password: 123456@test 17 | username: ujuji@domain.com 18 | port: 25 19 | 20 | --- 21 | 22 | #开发环境 23 | 24 | spring: 25 | profiles: dev 26 | datasource: 27 | driver-class-name: com.mysql.cj.jdbc.Driver 28 | username: root 29 | password: root 30 | url: jdbc:mysql://localhost:3306/java_navigation?useSSL=false&serverTimezone=UTC 31 | artemis: 32 | port: 4029 33 | 34 | redis: 35 | host: 127.0.0.1 36 | password: 37 | port: 6379 38 | lettuce: 39 | pool: 40 | max-active: 8 #最大连接数 41 | max-wait: -1 # 表示未限制 42 | max-idle: 8 # 接池中的最大空闲连接 43 | min-idle: 0 # 最小空闲链接 44 | timeout: 5000 # 超时时间 45 | cache: 46 | redis: 47 | time-to-live: 1m 48 | 49 | 50 | mybatis-plus: 51 | configuration: 52 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 53 | jwt: 54 | secret: 21312142131232 55 | expiration: 86400000 56 | header: Authorization 57 | prefix: "Bearer " 58 | 59 | cors: 60 | origins: 61 | - http://localhost:8080 62 | headers: 63 | - authentication 64 | - Cache-Control 65 | - X-User-Agent 66 | - Content-Type 67 | - Authorization -------------------------------------------------------------------------------- /src/main/resources/http/Admin.http: -------------------------------------------------------------------------------- 1 | GET {{api}}/admin/userInfo/1 2 | Authorization: {{token}} 3 | -------------------------------------------------------------------------------- /src/main/resources/http/adminBox.http: -------------------------------------------------------------------------------- 1 | ### 查询盒子 分页 2 | GET {{api}}/admin/box?size=10&page=1 3 | Authorization: Bearer {{token}} 4 | 5 | ### 删除用户 6 | DELETE {{api}}/admin/box/15 7 | Authorization: Bearer {{token}} 8 | 9 | ### 修改盒子 10 | PUT {{api}}/admin/box 11 | Content-Type: application/json 12 | Authorization: Bearer {{token}} 13 | 14 | { 15 | "id": 14, 16 | "title": "无道hh" 17 | } 18 | 19 | ### 搜索 20 | POST {{api}}/admin/box/search 21 | Content-Type: application/json 22 | Authorization: {{token}} 23 | 24 | { 25 | "key": "测试6", 26 | "pageSize": 10, 27 | "pageNo": 1 28 | } -------------------------------------------------------------------------------- /src/main/resources/http/adminCardCode.http: -------------------------------------------------------------------------------- 1 | ### 查询所有卡密分类 2 | 3 | GET {{api}}/admin/cardCode/types 4 | Authorization: {{token}} 5 | 6 | ### 插入 7 | POST {{api}}/admin/cardCode 8 | Content-Type: application/json 9 | Authorization: {{token}} 10 | 11 | { 12 | "num": 10, 13 | "type": "rename" 14 | } 15 | 16 | 17 | ### 搜索 18 | POST {{api}}/admin/cardCode/search 19 | Authorization: {{token}} 20 | Content-Type: application/json 21 | 22 | { 23 | "key": "ytLY", 24 | "pageSize": 20, 25 | "pageNo": 1 26 | } 27 | 28 | ### 分页查询 29 | POST {{api}}/admin/cardCode/find 30 | Authorization: {{token}} 31 | Content-Type: application/json 32 | 33 | { 34 | "pageSize": 20, 35 | "pageNo": 1 36 | } 37 | 38 | ### 删除 39 | DELETE {{api}}/admin/cardCode/1 40 | Authorization: {{token}} 41 | -------------------------------------------------------------------------------- /src/main/resources/http/adminLink.http: -------------------------------------------------------------------------------- 1 | ### 查询列表 分页 2 | GET {{api}}/admin/link?size=10&page=1 3 | Authorization: Bearer {{token}} 4 | 5 | ### 删除列表 6 | DELETE {{api}}/admin/link/21 7 | Authorization: Bearer {{token}} 8 | 9 | ### 修改列表 10 | PUT {{api}}/admin/link 11 | Content-Type: application/json 12 | Authorization: Bearer {{token}} 13 | 14 | { 15 | "id": 21, 16 | "title": "无道hh" 17 | } 18 | 19 | 20 | ### 搜索 21 | POST {{api}}/admin/link/search 22 | Content-Type: application/json 23 | Authorization: {{token}} 24 | 25 | { 26 | "key": "测试啊", 27 | "pageSize": 10, 28 | "pageNo": 1 29 | } -------------------------------------------------------------------------------- /src/main/resources/http/adminMsg.http: -------------------------------------------------------------------------------- 1 | ### 查询列表 分页 2 | GET {{api}}/admin/msg?size=10&page=1 3 | Authorization: Bearer {{token}} 4 | 5 | 6 | 7 | 8 | ### 删除列表 9 | DELETE {{api}}/admin/msg/3 10 | Authorization: Bearer {{token}} 11 | 12 | ### 修改列表 13 | PUT {{api}}/admin/msg 14 | Content-Type: application/json 15 | Authorization: Bearer {{token}} 16 | 17 | { 18 | "id": 3, 19 | "content": "和借款方发的健康" 20 | } 21 | 22 | 23 | #### 搜索 24 | #POST {{api}}/admin/link/search 25 | #Content-Type: application/json 26 | #Authorization: {{token}} 27 | # 28 | #{ 29 | # "key": "测试啊", 30 | # "pageSize": 10, 31 | # "pageNo": 1 32 | #} -------------------------------------------------------------------------------- /src/main/resources/http/adminSetting.http: -------------------------------------------------------------------------------- 1 | ### 插入 2 | POST {{api}}/admin/globalSetting 3 | Authorization: {{token}} 4 | Content-Type: application/json 5 | 6 | { 7 | "name": "defaultShow", 8 | "value": "misiai" 9 | } 10 | 11 | ### 修改 12 | PUT {{api}}/admin/globalSetting 13 | Authorization: {{token}} 14 | Content-Type: application/json 15 | 16 | { 17 | "id": 1, 18 | "name": "defaultShow", 19 | "value": "及法角度看方法" 20 | } 21 | 22 | ### 查询所有 23 | GET {{api}}/admin/globalSetting 24 | Authorization: {{token}} 25 | 26 | ### 删除 27 | 28 | DELETE {{api}}/admin/globalSetting/1 29 | Authorization: {{token}} -------------------------------------------------------------------------------- /src/main/resources/http/adminUser.http: -------------------------------------------------------------------------------- 1 | ### 查询用户 分页 2 | GET {{api}}/admin/user?size=10&page=1 3 | Authorization: Bearer {{token}} 4 | 5 | ### 删除用户 6 | DELETE {{api}}/admin/user/8 7 | Authorization: Bearer {{token}} 8 | 9 | ### 修改用户 10 | PUT {{api}}/admin/user 11 | Content-Type: application/json 12 | Authorization: Bearer {{token}} 13 | 14 | { 15 | "id": 1, 16 | "username": "无道hh" 17 | } 18 | 19 | ### 搜索 20 | POST {{api}}/admin/user/search 21 | Content-Type: application/json 22 | Authorization: {{token}} 23 | 24 | { 25 | "key": "231", 26 | "pageSize": 10, 27 | "pageNo": 1 28 | } -------------------------------------------------------------------------------- /src/main/resources/http/box.http: -------------------------------------------------------------------------------- 1 | ### 插入数据 2 | POST {{api}}/user/box 3 | Content-Type: application/json 4 | Authorization: {{token}} 5 | 6 | { 7 | "userId": 1, 8 | "title": "默认分类222_222", 9 | "boxOrder": 3, 10 | "titleIcon": "http://xxx.com", 11 | "pwd": "1234" 12 | } 13 | 14 | ### 修改 15 | 16 | PUT {{api}}/user/box 17 | Content-Type: application/json 18 | Authorization: {{token}} 19 | 20 | { 21 | "id": 27, 22 | "title": "秀爱附近21321312阿萨德看发12313", 23 | "boxOrder": 5, 24 | "pwd": "5678" 25 | } 26 | 27 | ### 删除 28 | 29 | DELETE {{api}}/user/box/3 30 | Authorization: {{token}} 31 | 32 | ### 查询所属用户的所有盒子 33 | GET {{api}}/public/allBoxes/1 34 | 35 | ### 根据用户ID查询所有 36 | GET {{api}}/user/box/user/1 37 | Authorization: {{token}} 38 | 39 | ### 导入盒子 40 | POST {{api}}/user/box/import 41 | Authorization: {{token}} 42 | Content-Type: application/json 43 | 44 | { 45 | "boxTitle": "导入的盒子123", 46 | "links": [ 47 | { 48 | "title": "书签标题", 49 | "link": "https://1kjf.comaf" 50 | }, 51 | { 52 | "title": "书签标题12", 53 | "link": "://1kjf.co12maf" 54 | } 55 | ] 56 | } -------------------------------------------------------------------------------- /src/main/resources/http/code.http: -------------------------------------------------------------------------------- 1 | GET {{api}}/public/verifyCode -------------------------------------------------------------------------------- /src/main/resources/http/http-client.private.env.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "api": "http://localhost:4037", 4 | "verifyCode": "", 5 | "token": "" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/resources/http/leaveMsg.http: -------------------------------------------------------------------------------- 1 | ### 后台用户查询 2 | GET {{api}}/user/leaveMsg?pageNo=1&pageSize=20 3 | Authorization: {{token}} 4 | 5 | ### 增加留言 6 | POST {{api}}/public/msg 7 | Content-Type: application/json 8 | 9 | { 10 | "content": "留言内容", 11 | "nickname": "无道", 12 | "userId": 1 13 | } 14 | 15 | ### 查询某个用户所有留言(非置顶) 16 | GET {{api}}/public/msg/1?pageNo=1&pageSize=20 17 | 18 | ### 查询某个用户所有置顶留言 19 | GET {{api}}/public/msg/fixed/1 20 | 21 | ### 查询未读留言个数 22 | GET {{api}}/user/leaveMsg/getNonReadCount 23 | Authorization: {{token}} 24 | 25 | 26 | 27 | ###=============需要权限=========== 28 | 29 | 30 | ### 搜索留言 31 | GET {{api}}/user/leaveMsg/search?kw=无道231&pageNo=1&pageSize=20 32 | Authorization: {{token}} 33 | 34 | ### 设置置顶 35 | GET {{api}}/user/leaveMsg/setFixed/3 36 | Authorization: {{token}} 37 | 38 | ### 设置已读 39 | GET {{api}}/user/leaveMsg/setRead/3 40 | Authorization: {{token}} 41 | 42 | ### 回复 43 | 44 | PUT {{api}}/user/leaveMsg/reply 45 | Content-Type: application/json 46 | Authorization: {{token}} 47 | 48 | { 49 | "id": 2, 50 | "reply": "这是回复内容" 51 | } 52 | 53 | ### 删除 54 | DELETE {{api}}/user/leaveMsg/2 55 | Authorization: {{token}} 56 | -------------------------------------------------------------------------------- /src/main/resources/http/link.http: -------------------------------------------------------------------------------- 1 | ### 插入数据 2 | POST {{api}}/user/link 3 | Content-Type: application/json 4 | Authorization: {{token}} 5 | 6 | { 7 | "boxId": 2, 8 | "title": "这是一条链接3333", 9 | "link": "http://xxx.com", 10 | "description": "这是一条描述哟减肥的靠发动机", 11 | "titleIcon": "https://xxxs.com" 12 | } 13 | 14 | ### 修改 15 | 16 | PUT {{api}}/user/link 17 | Content-Type: application/json 18 | Authorization: {{token}} 19 | 20 | { 21 | "id": 1, 22 | "boxId": 3, 23 | "title": "这是一条链接222", 24 | "link": "http://xx2222x.com", 25 | "description": "12312312", 26 | "titleIcon": "https://xxxs.com" 27 | } 28 | 29 | ### 删除 30 | 31 | DELETE {{api}}/user/link/3 32 | Authorization: {{token}} 33 | 34 | ### 查询所属用户的所有盒子,及其下面的所有链接 35 | GET {{api}}/public/allBoxes/1 36 | 37 | ### 根据盒子ID查询所有 38 | GET {{api}}/user/link/box/18 39 | Authorization: {{token}} -------------------------------------------------------------------------------- /src/main/resources/http/notice.http: -------------------------------------------------------------------------------- 1 | ### 查询 2 | GET {{api}}/user/notice/ 3 | Authorization: {{token}} 4 | 5 | ### 新建 6 | POST {{api}}/user/notice 7 | Authorization: {{token}} 8 | Content-Type: application/json 9 | 10 | { 11 | "userId": 1, 12 | "content": "这是内容哟放大镜发动机发大水发大水" 13 | } 14 | 15 | ### 修改 16 | PUT {{api}}/user/notice 17 | Authorization: {{token}} 18 | Content-Type: application/json 19 | 20 | { 21 | "userId": 1, 22 | "id": 1, 23 | "content": "修改后的内容", 24 | "longNotice": "这是长的公告,呵呵" 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/main/resources/http/public.http: -------------------------------------------------------------------------------- 1 | GET {{api}}/public/system/info 2 | 3 | 4 | ### 查询所有 5 | GET {{api}}/public/nav/info/misiai 6 | 7 | 8 | ### 查询某个站点盒子信息 9 | GET {{api}}/public/boxes/1 10 | 11 | ### 查询信息 12 | GET {{api}}/public/config/info/misiai 13 | 14 | ### 查询盒子列表(有密码) 15 | GET {{api}}/public/nav/pwd/18/12312 16 | 17 | ### 搜索链接 18 | GET {{api}}/public/search 19 | Content-Type: application/json 20 | 21 | { 22 | "keyword": "B" 23 | } 24 | 25 | ### 查询天气 26 | GET {{api}}/public/weather?city=什邡 27 | 28 | 29 | ### 插入数据(AccessToken) 30 | POST {{api}}/public/token/LKwkrnUzBxCaHPtxjSKnSILJuKuwXr 31 | Content-Type: application/json 32 | 33 | { 34 | "boxId": 1, 35 | "title": "这是一条链接3333", 36 | "link": "http://xxx.com", 37 | "description": "这是一条描述哟减肥的靠发动机", 38 | "titleIcon": "https://xxxs.com" 39 | } 40 | 41 | ### 通过token后去boxes 42 | GET {{api}}/public/allBoxes/token/LKwkrnUzBxCaHPtxjSKnSILJuKuwXr -------------------------------------------------------------------------------- /src/main/resources/http/searchSite.http: -------------------------------------------------------------------------------- 1 | ### 查询 2 | GET {{api}}/user/searchSite/ 3 | Authorization: {{token}} 4 | 5 | ### 新建 6 | POST {{api}}/user/searchSite 7 | Authorization: {{token}} 8 | Content-Type: application/json 9 | 10 | { 11 | "userId": 1, 12 | "name": "百度搜索", 13 | "searchUrl": "https://www.baidu.com/s?ie=UTF-8&wd=[kw]", 14 | "notice": "百度一下,你就知道" 15 | } 16 | 17 | ### 修改 18 | PUT {{api}}/user/searchSite 19 | Authorization: {{token}} 20 | Content-Type: application/json 21 | 22 | { 23 | "userId": 1, 24 | "id": 1, 25 | "name": "百度搜索2", 26 | "searchUrl": "https://www.baidu.com/s?ie=UTF-8&wd=[kw]", 27 | "notice": "百度一下2,你就知道" 28 | } 29 | 30 | ### 删除 31 | DELETE {{api}}/user/searchSite/1 32 | Authorization: {{token}} -------------------------------------------------------------------------------- /src/main/resources/http/siteConfig.http: -------------------------------------------------------------------------------- 1 | PUT {{api}}/user/siteConfig 2 | Authorization: {{token}} 3 | Content-Type: application/json 4 | 5 | { 6 | "siteName": "无道的导222航", 7 | "siteDesc": "这是无道的导213航2222", 8 | "suffix": "122fd" 9 | } 10 | 11 | ### 查询某用户的配置信息 12 | GET {{api}}/public//siteConfig/2 13 | 14 | ### 后缀是否可用 15 | GET {{api}}/user/siteConfig/suffix/available/misiai 16 | Authorization: {{token}} 17 | -------------------------------------------------------------------------------- /src/main/resources/http/test.http: -------------------------------------------------------------------------------- 1 | GET http://localhost:4037/admin/user?username=无 2 | 3 | <> 2020-05-15T080418.200.json 4 | <> 2020-05-15T074607.500.json 5 | <> 2020-05-15T074602.200.json 6 | -------------------------------------------------------------------------------- /src/main/resources/http/user.http: -------------------------------------------------------------------------------- 1 | ### 获取验证码 2 | 3 | GET {{api}}/public/verifyCode 4 | 5 | ### 登录 6 | POST {{api}}/auth/login 7 | Content-Type: application/json 8 | Acces-Token: dc892ac8-9b69-42f0-a4a1-a82c037c7816 9 | 10 | { 11 | "username": "无道", 12 | "password": "123456", 13 | "email": "", 14 | "verifyCode": "1", 15 | "code": "MhcGX5vpsg" 16 | } 17 | > {%client.global.set("token",response.body.data.token) %} 18 | 19 | ### 注册 20 | POST {{api}}/auth/register 21 | Content-Type: application/json 22 | 23 | { 24 | "username": "无21212", 25 | "password": "123f21a6", 26 | "verifyCode": "7Se8", 27 | "code": "723869104687165440", 28 | "email": "12fas11@ujuji.com" 29 | } 30 | 31 | ### 修改密码 32 | POST {{api}}/user/updatePassword1 33 | Authorization: {{token}} 34 | Content-Type: application/x-www-form-urlencoded 35 | 36 | oldPass=123456&newPass=1234567 37 | 38 | ### 查询用户信息 39 | GET {{api}}/user/info 40 | Authorization: {{token}} 41 | 42 | ### 查询用户信息 43 | GET {{api}}/auth/info 44 | Authorization: {{token}} 45 | 46 | 47 | ### 查询所有信息 48 | GET {{api}}/ 49 | 50 | ### 查询所有备份 51 | GET {{api}}/user/backup 52 | Authorization: {{token}} 53 | 54 | ### 发送修改密码的邮箱验证 55 | POST {{api}}/auth/sendUpdateMail 56 | Content-Type: application/json 57 | 58 | { 59 | "username": "无道", 60 | "email": "991418182@qq.com", 61 | "verifyCode": "42", 62 | "code": "wdlW1JWJ70" 63 | } 64 | 65 | ### 通过邮箱验证码,请求修改密码 66 | POST {{api}}/auth/updatePassWithCode 67 | Content-Type: application/json 68 | 69 | { 70 | "email": "991418182@qq.com", 71 | "code": "GgcRegVyUl", 72 | "newPass": "12345678" 73 | } 74 | 75 | ### 生成token 76 | POST {{api}}/auth/token 77 | Authorization: {{token}} 78 | 79 | -------------------------------------------------------------------------------- /src/test/java/com/ujuji/navigation/NavigationApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | import javax.annotation.Resource; 9 | 10 | @SpringBootTest 11 | class NavigationApplicationTests { 12 | 13 | public static void main(String[] args) { 14 | //$2a$10$xTOc1xrGt13w5pSF2wbOQO9kO4sVKfq6xfmTr4/lAaOSp5dOEMyee 15 | System.out.println(new BCryptPasswordEncoder().encode("123456")); 16 | } 17 | 18 | @Resource 19 | PasswordEncoder passwordEncoder; 20 | @Test 21 | void contextLoads() { 22 | System.out.println(passwordEncoder.encode("123456")); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/ujuji/navigation/service/UserServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service; 2 | 3 | import com.ujuji.navigation.model.entity.UserEntity; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | import javax.annotation.Resource; 9 | 10 | @SpringBootTest 11 | class UserServiceImplTest { 12 | @Resource 13 | UserService userService; 14 | @Resource 15 | PasswordEncoder passwordEncoder; 16 | 17 | @Test 18 | void findByUsername() { 19 | UserEntity user = userService.findByUsername("无道"); 20 | System.out.println("user = " + user); 21 | } 22 | 23 | @Test 24 | void findById() { 25 | UserEntity user = userService.findById(1); 26 | System.out.println("user = " + user); 27 | } 28 | 29 | @Test 30 | void register() { 31 | // UserEntity userEntity = new UserEntity("无道", passwordEncoder.encode("12345"), "99141818@qq.com", 1, 32 | // "ROLE_ADMIN"); 33 | // Boolean register = userService.register(userEntity); 34 | // System.out.println("register = " + register); 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/java/com/ujuji/navigation/service/impl/EmailServiceImplTest.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.service.impl; 2 | 3 | import com.ujuji.navigation.service.EmailService; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | 7 | import javax.annotation.Resource; 8 | 9 | @SpringBootTest 10 | class EmailServiceImplTest { 11 | @Resource 12 | EmailService emailService; 13 | 14 | @Test 15 | void sendForgotPassEmail() { 16 | // emailService.sendForgotPassEmail("991418182@qq.com", "你好,这是重置邮件"); 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/com/ujuji/navigation/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.ujuji.navigation.test; 2 | 3 | import com.ujuji.navigation.core.Constants; 4 | 5 | public class Test { 6 | public static void main(String[] args) { 7 | System.out.println(Constants.CardCodeType.valueOf("RENAME") == Constants.CardCodeType.RENAME); 8 | // System.out.println(System.currentTimeMillis()); 9 | } 10 | } 11 | --------------------------------------------------------------------------------