├── src ├── main │ ├── resources │ │ ├── static │ │ │ ├── js │ │ │ │ ├── client.js │ │ │ │ └── console.js │ │ │ ├── images │ │ │ │ ├── logo.jpg │ │ │ │ ├── avatar.jpg │ │ │ │ ├── favicon.ico │ │ │ │ ├── mistake.jpg │ │ │ │ ├── demo │ │ │ │ │ └── demo.jpg │ │ │ │ └── question.jpg │ │ │ ├── bootstrap │ │ │ │ └── font │ │ │ │ │ ├── .DS_Store │ │ │ │ │ └── fonts │ │ │ │ │ ├── .DS_Store │ │ │ │ │ ├── bootstrap-icons.woff │ │ │ │ │ └── bootstrap-icons.woff2 │ │ │ ├── font-awesome │ │ │ │ └── fonts │ │ │ │ │ ├── FontAwesome.otf │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ ├── laydate │ │ │ │ └── theme │ │ │ │ │ └── default │ │ │ │ │ └── font │ │ │ │ │ ├── iconfont.eot │ │ │ │ │ ├── iconfont.ttf │ │ │ │ │ └── iconfont.woff │ │ │ ├── css │ │ │ │ ├── common.css │ │ │ │ └── client.css │ │ │ └── error │ │ │ │ ├── 404.html │ │ │ │ └── 500.html │ │ ├── teststatic │ │ │ └── yinhun.jpg │ │ ├── mapper │ │ │ ├── AdminMapper.xml │ │ │ ├── NoticeMapper.xml │ │ │ ├── OrderMapper.xml │ │ │ ├── CategoryMapper.xml │ │ │ ├── ProductMapper.xml │ │ │ ├── ScheduleJobMapper.xml │ │ │ ├── SiteConfigMapper.xml │ │ │ ├── AdminPermissionMapper.xml │ │ │ ├── UserMapper.xml │ │ │ ├── PermissionMapper.xml │ │ │ ├── SqlMapper.xml │ │ │ └── FeedbackMapper.xml │ │ ├── config │ │ │ ├── myconfig.properties │ │ │ └── dbinit.json │ │ ├── templates │ │ │ ├── console │ │ │ │ ├── msg.html │ │ │ │ ├── admin-permission.html │ │ │ │ └── tpl │ │ │ │ │ └── tpl-module.html │ │ │ └── client │ │ │ │ ├── notice-index.html │ │ │ │ ├── 500.html │ │ │ │ ├── notice-list.html │ │ │ │ ├── feedback-index.html │ │ │ │ ├── notice-detail.html │ │ │ │ ├── feedback-list.html │ │ │ │ ├── login.html │ │ │ │ └── user-center.html │ │ └── quartz.properties │ └── java │ │ └── com │ │ └── jingqueyimu │ │ ├── mapper │ │ ├── sql │ │ │ └── DynamicSql.java │ │ ├── OrderMapper.java │ │ ├── DbInitMapper.java │ │ ├── ProductMapper.java │ │ ├── CategoryMapper.java │ │ ├── SiteConfigMapper.java │ │ ├── ScheduleJobMapper.java │ │ ├── AdminPermissionMapper.java │ │ ├── SqlMapper.java │ │ ├── UserMapper.java │ │ ├── FeedbackMapper.java │ │ ├── AdminMapper.java │ │ ├── PermissionMapper.java │ │ ├── NoticeMapper.java │ │ └── SqlMapper2.java │ │ ├── handler │ │ ├── excel │ │ │ ├── IExcelExportHandler.java │ │ │ └── IExcelImportHandler.java │ │ ├── login │ │ │ ├── PasswordLoginHandler.java │ │ │ └── LoginHandler.java │ │ └── register │ │ │ ├── RegisterHandler.java │ │ │ ├── MobileRegisterHandler.java │ │ │ └── EmailRegisterHandler.java │ │ ├── constant │ │ ├── BizConstant.java │ │ ├── RunEnv.java │ │ ├── SysConstant.java │ │ ├── CacheConstant.java │ │ └── StatusCode.java │ │ ├── annotation │ │ ├── MyAnnotation.java │ │ ├── Perm.java │ │ └── Lock.java │ │ ├── service │ │ ├── OrderService.java │ │ ├── ProductService.java │ │ ├── CategoryService.java │ │ ├── NoticeService.java │ │ ├── component │ │ │ ├── RabbitService.java │ │ │ ├── CaptchaService.java │ │ │ ├── SmsService.java │ │ │ └── RedisService.java │ │ ├── PermissionService.java │ │ ├── DbInitService.java │ │ └── FeedbackService.java │ │ ├── controller │ │ ├── ProductController.java │ │ ├── CategoryController.java │ │ ├── BaseController.java │ │ ├── console │ │ │ ├── ConsoleCategoryController.java │ │ │ ├── ConsoleOrderController.java │ │ │ ├── ConsoleProductController.java │ │ │ ├── ConsolePermissionController.java │ │ │ ├── ConsoleFeedbackController.java │ │ │ └── ConsoleAdminPermissionController.java │ │ ├── api │ │ │ ├── ApiFeedbackController.java │ │ │ └── ApiUserController.java │ │ ├── SmsController.java │ │ ├── EmailController.java │ │ ├── SiteConfigController.java │ │ ├── NoticeController.java │ │ └── UserController.java │ │ ├── schedule │ │ ├── TestScheduleJob.java │ │ └── TestQuartzJob.java │ │ ├── mq │ │ ├── RabbitDirectReceiver.java │ │ ├── RabbitTopicReceiver.java │ │ ├── RabbitFanoutReceiver.java │ │ ├── RabbitDirectConfig.java │ │ ├── RabbitFanoutConfig.java │ │ └── RabbitTopicConfig.java │ │ ├── exception │ │ ├── AppException.java │ │ └── GlobalExceptionResolver.java │ │ ├── model │ │ ├── BaseModel.java │ │ ├── dict │ │ │ ├── PayType.java │ │ │ ├── ProductStatus.java │ │ │ ├── FeedbackStatus.java │ │ │ ├── LoginType.java │ │ │ ├── FeedbackType.java │ │ │ ├── ScheduleJobStatus.java │ │ │ ├── RegisterType.java │ │ │ ├── SiteConfigContentType.java │ │ │ ├── OrderStatus.java │ │ │ ├── ScheduleJobExecuteStatus.java │ │ │ └── PermissionGroup.java │ │ ├── bean │ │ │ ├── ResultData.java │ │ │ └── CurrAdmin.java │ │ ├── DbInit.java │ │ ├── vo │ │ │ ├── PermissionWithAccessVO.java │ │ │ └── FeedbackVO.java │ │ ├── Category.java │ │ ├── AdminPermission.java │ │ ├── Permission.java │ │ └── Notice.java │ │ ├── factory │ │ ├── YamlPropertySourceFactory.java │ │ └── LockFactory.java │ │ ├── filter │ │ └── LogFilter.java │ │ ├── config │ │ ├── InterceptorConfig.java │ │ ├── FilterConfig.java │ │ └── MyConfig.java │ │ ├── util │ │ ├── Dom4JUtil.java │ │ ├── IpUtil.java │ │ ├── DbInitUtil.java │ │ └── BizUtil.java │ │ ├── MyApplication.java │ │ └── aspect │ │ └── LockAspect.java └── test │ ├── resources │ └── config │ │ ├── test.properties │ │ ├── test2.yml │ │ ├── test.sql │ │ ├── test-dbinit.json │ │ ├── test.json │ │ └── test-dbinit2.json │ └── java │ └── com │ └── jingqueyimu │ ├── HutoolTest.java │ ├── SimpleTest.java │ ├── ConfigTest.java │ ├── BaseTest.java │ ├── config │ ├── TestConfig.java │ └── TestYmlConfig.java │ ├── BizTest.java │ ├── ResourceTest.java │ ├── RabbitTest.java │ ├── MailTest.java │ ├── util │ └── DbInitTestUtil.java │ └── JacobTest.java ├── .gitignore ├── Dockerfile └── chewing_docker_run.sh /src/main/resources/static/js/client.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/config/test.properties: -------------------------------------------------------------------------------- 1 | test.value=配置测试 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #target 2 | #.settings 3 | /target/ 4 | /.settings/ 5 | .classpath 6 | .project 7 | -------------------------------------------------------------------------------- /src/main/resources/static/images/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/logo.jpg -------------------------------------------------------------------------------- /src/main/resources/teststatic/yinhun.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/teststatic/yinhun.jpg -------------------------------------------------------------------------------- /src/main/resources/static/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/avatar.jpg -------------------------------------------------------------------------------- /src/main/resources/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/static/images/mistake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/mistake.jpg -------------------------------------------------------------------------------- /src/main/resources/static/images/demo/demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/demo/demo.jpg -------------------------------------------------------------------------------- /src/main/resources/static/images/question.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/images/question.jpg -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/font/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/bootstrap/font/.DS_Store -------------------------------------------------------------------------------- /src/test/resources/config/test2.yml: -------------------------------------------------------------------------------- 1 | test: 2 | value: yaml配置测试 3 | person: 4 | name: 张三 5 | age: 22 6 | dog: 7 | name: 大黄 8 | age: 2 9 | -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/font/fonts/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/bootstrap/font/fonts/.DS_Store -------------------------------------------------------------------------------- /src/main/resources/static/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /src/main/resources/static/laydate/theme/default/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/laydate/theme/default/font/iconfont.eot -------------------------------------------------------------------------------- /src/main/resources/static/laydate/theme/default/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/laydate/theme/default/font/iconfont.ttf -------------------------------------------------------------------------------- /src/main/resources/static/laydate/theme/default/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/laydate/theme/default/font/iconfont.woff -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 基础镜像 2 | FROM java:8 3 | # 添加文件到容器中 4 | ADD chewing.jar /package/chewing.jar 5 | # 暴露端口 6 | EXPOSE 9000 7 | # 执行命令(运行jar包) 8 | ENTRYPOINT ["java","-jar","/package/chewing.jar"] 9 | -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/font/fonts/bootstrap-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/bootstrap/font/fonts/bootstrap-icons.woff -------------------------------------------------------------------------------- /src/main/resources/static/bootstrap/font/fonts/bootstrap-icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/bootstrap/font/fonts/bootstrap-icons.woff2 -------------------------------------------------------------------------------- /src/main/resources/static/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/main/resources/static/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/main/resources/static/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/main/resources/static/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingqueyimu/chewing/HEAD/src/main/resources/static/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/test/resources/config/test.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO t_site_config(id, code, name, content, description, public_flag, gmt_create) VALUES(1, 'site_record_no', '网站备案号', '备案号', '网站备案号', true, NOW()); -------------------------------------------------------------------------------- /src/main/resources/mapper/AdminMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/NoticeMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/CategoryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/ProductMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/ScheduleJobMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/mapper/SiteConfigMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/mapper/AdminPermissionMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/sql/DynamicSql.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper.sql; 2 | 3 | /** 4 | * 动态SQL类 5 | * 6 | * @author zhuangyilian 7 | */ 8 | public class DynamicSql { 9 | 10 | public static String sql(String sql) { 11 | return sql; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.Order; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 订单数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface OrderMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/DbInitMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.DbInit; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 数据库初始化数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface DbInitMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/ProductMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.Product; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 产品数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface ProductMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/CategoryMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.Category; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 类目数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface CategoryMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/HutoolTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import cn.hutool.Hutool; 4 | 5 | /** 6 | * Hutool工具类测试 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public class HutoolTest extends BaseTest { 11 | 12 | public static void main(String[] args) { 13 | Hutool.printAllUtils(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/SiteConfigMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.SiteConfig; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 网站配置数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface SiteConfigMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/ScheduleJobMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.ScheduleJob; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 调度任务数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface ScheduleJobMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/AdminPermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.jingqueyimu.model.AdminPermission; 4 | 5 | import tk.mybatis.mapper.common.Mapper; 6 | 7 | /** 8 | * 管理员权限数据映射 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public interface AdminPermissionMapper extends Mapper { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/config/test-dbinit.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "initKey": "site_config_20210110", 4 | "sqls": [ 5 | "INSERT INTO t_site_config(id, code, name, content, description, public_flag) VALUES(NULL, 'site_record_no', '网站备案号', '备案号', '网站备案号', true);" 6 | ] 7 | } 8 | ] -------------------------------------------------------------------------------- /src/main/resources/config/myconfig.properties: -------------------------------------------------------------------------------- 1 | # --系统配置-- 2 | # 运行环境(开发:dev;测试:test;生产:prod) 3 | myconfig.runEnv=dev 4 | # 网站地址 5 | myconfig.siteUrl=www.jingqueyimu.com 6 | # 网站名称 7 | myconfig.siteName=惊却一目 8 | # 文件存放路径 9 | myconfig.fileStoragePath=D:/dev-test/file 10 | 11 | # --超级管理员配置-- 12 | # 超级管理员账户名 13 | myconfig.superAdminName=admin 14 | # 超级管理员密码 15 | myconfig.superAdminPwd=123456 16 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/excel/IExcelExportHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.excel; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Excel导出处理器接口 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public interface IExcelExportHandler { 11 | 12 | /** 13 | * 导出处理 14 | * 15 | * @param data 16 | * @return 17 | */ 18 | List handle(T data); 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/config/test.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tableName": "t_site_config", 4 | "initKey": "site_config_1", 5 | "colVals": [ 6 | { 7 | "code": "site_record_no", 8 | "name": "网站备案号", 9 | "content": "备案号" 10 | } 11 | ] 12 | } 13 | ] -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/excel/IExcelImportHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.excel; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | /** 6 | * Excel导入处理器接口 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public interface IExcelImportHandler { 11 | 12 | /** 13 | * 导入处理 14 | * 15 | * @param data 16 | * @return 17 | */ 18 | void handle(JSONObject data); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/SqlMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | /** 7 | * 原生SQL执行接口(配置文件方式) 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public interface SqlMapper { 12 | 13 | int insert(String sql); 14 | 15 | int delete(String sql); 16 | 17 | int update(String sql); 18 | 19 | List> select(String sql); 20 | 21 | int count(String sql); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/constant/BizConstant.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.constant; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * 业务常量类 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public class BizConstant { 11 | 12 | /** 13 | * 超级管理员ID 14 | */ 15 | public static final long SUPER_ADMIN_ID = 1L; 16 | 17 | /** 18 | * 默认头像 19 | */ 20 | public static final String DEFAULT_AVATAR = File.separator + "images" + File.separator + "avatar.jpg"; 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/constant/RunEnv.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.constant; 2 | 3 | /** 4 | * 运行环境 5 | * 6 | * @author zhuangyilian 7 | */ 8 | public class RunEnv { 9 | 10 | /** 11 | * 开发(不调用第三方等) 12 | */ 13 | public static final String DEV = "dev"; 14 | 15 | /** 16 | * 测试(使用测试账号调用第三方等) 17 | */ 18 | public static final String TEST = "test"; 19 | 20 | /** 21 | * 生产 22 | */ 23 | public static final String PROD = "prod"; 24 | } 25 | -------------------------------------------------------------------------------- /src/test/resources/config/test-dbinit2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "tableName": "t_site_config", 4 | "initKey": "site_config_20210110", 5 | "colKeys": "['code']", 6 | "maps": [ 7 | { 8 | "cols": "(id, code, name, content, description, public_flag)", 9 | "vals": "(NULL, 'site_record_no', '网站备案号', '备案号', '网站备案号', true)" 10 | } 11 | ] 12 | } 13 | ] -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/annotation/MyAnnotation.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Target({ElementType.TYPE, ElementType.METHOD}) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | public @interface MyAnnotation { 13 | 14 | String name() default ""; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.jingqueyimu.model.User; 5 | 6 | import tk.mybatis.mapper.common.Mapper; 7 | 8 | /** 9 | * 用户数据映射 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public interface UserMapper extends Mapper{ 14 | 15 | /** 16 | * 根据账号和密码查询用户 17 | * 18 | * @param params 19 | * @return 20 | */ 21 | User getByAccountAndPassword(JSONObject params); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.jingqueyimu.mapper.OrderMapper; 7 | import com.jingqueyimu.model.Order; 8 | 9 | /** 10 | * 订单服务 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Service 15 | public class OrderService extends BaseService { 16 | 17 | @Autowired 18 | private OrderMapper orderMapper; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SELECT * 7 | FROM t_user 8 | WHERE (username = #{account} OR mobile = #{account} OR email = #{account}) AND password = #{password} 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/ProductService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.jingqueyimu.mapper.ProductMapper; 7 | import com.jingqueyimu.model.Product; 8 | 9 | /** 10 | * 产品服务 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Service 15 | public class ProductService extends BaseService { 16 | 17 | @Autowired 18 | private ProductMapper productMapper; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/CategoryService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.jingqueyimu.mapper.CategoryMapper; 7 | import com.jingqueyimu.model.Category; 8 | 9 | /** 10 | * 类目服务 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Service 15 | public class CategoryService extends BaseService { 16 | 17 | @Autowired 18 | private CategoryMapper categoryMapper; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/static/css/common.css: -------------------------------------------------------------------------------- 1 | .my-bg-err-500 { 2 | background: url(/images/mistake.jpg); 3 | background-size:100% 100%; 4 | } 5 | 6 | .my-bg-err-404 { 7 | background: url(/images/question.jpg); 8 | background-size:100% 100%; 9 | } 10 | 11 | .my-err-text { 12 | font-size: 3rem; 13 | font-weight: bold; 14 | } 15 | 16 | /***************** 覆盖bootstrap的样式 *****************/ 17 | 18 | .custom-file-input:lang(zh) ~ .custom-file-label::after { 19 | content: "浏览"; 20 | } 21 | 22 | .custom-file-label::after { 23 | content: "浏览"; 24 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/FeedbackMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import java.util.List; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.jingqueyimu.model.Feedback; 7 | import com.jingqueyimu.model.vo.FeedbackVO; 8 | 9 | import tk.mybatis.mapper.common.Mapper; 10 | 11 | /** 12 | * 意见反馈数据映射 13 | * 14 | * @author zhuangyilian 15 | */ 16 | public interface FeedbackMapper extends Mapper { 17 | 18 | /** 19 | * 查询意见反馈列表 20 | * 21 | * @param params 22 | * @return 23 | */ 24 | List listFeedback(JSONObject params); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/ProductController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.jingqueyimu.service.ProductService; 8 | 9 | /** 10 | * 产品控制器 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @RestController 15 | @RequestMapping("/product") 16 | public class ProductController extends BaseController { 17 | 18 | @Autowired 19 | private ProductService productService; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/AdminMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.ibatis.annotations.Select; 6 | 7 | import com.jingqueyimu.model.Admin; 8 | 9 | import tk.mybatis.mapper.common.Mapper; 10 | 11 | /** 12 | * 管理员数据映射 13 | * 14 | * @author zhuangyilian 15 | */ 16 | public interface AdminMapper extends Mapper { 17 | 18 | /** 19 | * 查询接收邮件的管理员 20 | * 21 | * @return 22 | */ 23 | @Select("SELECT * FROM t_admin WHERE is_lock = 0 AND email IS NOT NULL AND email <> ''") 24 | List listReceiveEmailAdmin(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/schedule/TestScheduleJob.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.schedule; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.scheduling.annotation.Scheduled; 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.jingqueyimu.util.DateUtil; 9 | 10 | /** 11 | * 调度任务测试 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Component 16 | public class TestScheduleJob { 17 | 18 | @Scheduled(cron="0 */5 * * * ?") 19 | public void printTime() { 20 | System.out.println("TestScheduleJob: " + DateUtil.format(new Date(), DateUtil.FORMAT_DATE_TIME)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/CategoryController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.jingqueyimu.service.CategoryService; 8 | 9 | /** 10 | * 类目控制器 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @RestController 15 | @RequestMapping("/category") 16 | public class CategoryController extends BaseController { 17 | 18 | @Autowired 19 | private CategoryService categoryService; 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/SimpleTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * 简单测试 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public class SimpleTest extends BaseTest { 13 | 14 | @Before 15 | public void testBefore() { 16 | System.out.println("junit before..."); 17 | } 18 | 19 | @After 20 | public void testAfter() { 21 | System.out.println("junit after..."); 22 | } 23 | 24 | @Test 25 | public void test() { 26 | System.out.println("junit test..."); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/PermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import java.util.List; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.jingqueyimu.model.Permission; 7 | import com.jingqueyimu.model.vo.PermissionWithAccessVO; 8 | 9 | import tk.mybatis.mapper.common.Mapper; 10 | 11 | /** 12 | * 权限数据映射 13 | * 14 | * @author zhuangyilian 15 | */ 16 | public interface PermissionMapper extends Mapper { 17 | 18 | /** 19 | * 查询带访问状态的权限 20 | * 21 | * @param params 22 | * @return 23 | */ 24 | List listWithAccess(JSONObject params); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitDirectReceiver.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * 直接模式消息接收者 10 | * 11 | * @author zhuangyilian 12 | */ 13 | @Component 14 | public class RabbitDirectReceiver { 15 | 16 | private Logger log = LoggerFactory.getLogger(this.getClass()); 17 | 18 | // 监听指定队列 19 | @RabbitListener(queues = RabbitDirectConfig.DIRECT_QUEUE) 20 | public void process(String data) { 21 | log.debug("DirectReceiver: {}", data); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/mapper/PermissionMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SELECT p.*, ap.admin_id, (CASE WHEN ap.id IS NULL THEN FALSE ELSE TRUE END) accessFlag 7 | FROM t_permission p 8 | LEFT JOIN (SELECT * FROM t_admin_permission WHERE admin_id = #{adminId}) ap ON p.id = ap.permission_id 9 | WHERE p.group_code = #{groupCode} 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/static/js/console.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 分页搜索 3 | * 4 | * @param url 5 | * @param pageInfo 6 | * @param formSelector Form选择器 7 | * @param numKeys value为数值类型的key 8 | * @param boolKeys value为布尔类型的key 9 | */ 10 | function pageSearch(url, pageInfo, formSelector, numKeys, boolKeys) { 11 | if (pageInfo == undefined) { 12 | return; 13 | } 14 | var pageNum = pageInfo.pageNum; 15 | var pageSize = pageInfo.pageSize; 16 | var pages = pageInfo.pages; 17 | pageNum = pageNum < 1 ? 1 : pageNum; 18 | pageNum = pageNum > pages ? pages : pageNum; 19 | var params = formToJsonString($(formSelector), numKeys, boolKeys); 20 | location.href = url + "?pageNum=" + pageNum + "&pageSize=" + pageSize + "¶ms=" + encodeURI(params); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/annotation/Perm.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 权限 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Target({ElementType.TYPE, ElementType.METHOD}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Perm { 18 | 19 | /** 20 | * 分组(字典: PermissionGroup) 21 | */ 22 | String group() default ""; 23 | 24 | /** 25 | * 名称 26 | */ 27 | String name() default ""; 28 | 29 | /** 30 | * 描述 31 | */ 32 | String description() default ""; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/NoticeMapper.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import org.apache.ibatis.annotations.Select; 4 | 5 | import com.jingqueyimu.model.Notice; 6 | 7 | import tk.mybatis.mapper.common.Mapper; 8 | 9 | /** 10 | * 公告数据映射 11 | * 12 | * @author zhuangyilian 13 | */ 14 | public interface NoticeMapper extends Mapper { 15 | 16 | /** 17 | * 上一篇公告 18 | * 19 | * @param id 20 | * @return 21 | */ 22 | @Select("SELECT * FROM t_notice WHERE id < #{id} ORDER BY id DESC LIMIT 1") 23 | Notice prevNotice(long id); 24 | 25 | /** 26 | * 下一篇公告 27 | * 28 | * @param id 29 | * @return 30 | */ 31 | @Select("SELECT * FROM t_notice WHERE id > #{id} LIMIT 1") 32 | Notice nextNotice(long id); 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/ConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import com.jingqueyimu.config.TestConfig; 7 | import com.jingqueyimu.config.TestYmlConfig; 8 | 9 | /** 10 | * 配置测试 11 | * 12 | * @author zhuangyilian 13 | */ 14 | public class ConfigTest extends BaseTest { 15 | 16 | @Autowired 17 | private TestConfig testConfig; 18 | @Autowired 19 | private TestYmlConfig testYamlConfig; 20 | 21 | @Test 22 | public void test() { 23 | System.out.println("test config: " + testConfig.getValue()); 24 | } 25 | 26 | @Test 27 | public void test2() { 28 | System.out.println("test yaml config: " + testYamlConfig.toString()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/exception/AppException.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.exception; 2 | 3 | import com.jingqueyimu.constant.StatusCode; 4 | 5 | /** 6 | * 应用异常类 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public class AppException extends RuntimeException { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | private int code = StatusCode.ERR_SYS; 15 | 16 | public AppException() {} 17 | 18 | public AppException(String msg) { 19 | super(msg); 20 | } 21 | 22 | public AppException(int code, String msg) { 23 | super(msg); 24 | this.code = code; 25 | } 26 | 27 | public int getCode() { 28 | return code; 29 | } 30 | 31 | public void setCode(int code) { 32 | this.code = code; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/resources/mapper/SqlMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${value} 7 | 8 | 9 | ${value} 10 | 11 | 12 | ${value} 13 | 14 | 15 | ${value} 16 | 17 | 18 | ${value} 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Lazy; 7 | 8 | import com.jingqueyimu.config.MyConfig; 9 | import com.jingqueyimu.context.AdminContext; 10 | import com.jingqueyimu.context.UserContext; 11 | 12 | /** 13 | * 抽象基础控制器 14 | * 15 | * @author zhuangyilian 16 | */ 17 | public abstract class BaseController { 18 | 19 | public final Logger log = LoggerFactory.getLogger(this.getClass()); 20 | 21 | @Lazy 22 | @Autowired 23 | public MyConfig config; 24 | @Lazy 25 | @Autowired 26 | public UserContext userContext; 27 | @Lazy 28 | @Autowired 29 | public AdminContext adminContext; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/annotation/Lock.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.annotation; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 分布式锁 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Target(ElementType.METHOD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Documented 17 | public @interface Lock { 18 | 19 | /** 20 | * 锁的key 21 | */ 22 | String[] keys() default {}; 23 | 24 | /** 25 | * 尝试加锁等待时间 26 | */ 27 | long waitTime() default 0; 28 | 29 | /** 30 | * 加锁后自动释放时间 31 | */ 32 | long releaseTime() default 0; 33 | 34 | /** 35 | * 尝试加锁失败后提示信息 36 | */ 37 | String msg() default "您这手速有点快啊,服务器都承受不了!"; 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 6 | import org.springframework.test.context.web.WebAppConfiguration; 7 | 8 | import com.jingqueyimu.MyApplication; 9 | 10 | /** 11 | * Junit基础测试类 12 | * 其他测试类只需继承该基础测试类即可,不用在每个测试类上加注解 13 | * 注意src/test/java中不要注入src/main/java中的类,否则运行时会找不到类 14 | * 15 | * @author zhuangyilian 16 | */ 17 | // 指定测试运行器为SpringJUnit4ClassRunner,从而自动创建Spring运行环境 18 | @RunWith(SpringJUnit4ClassRunner.class) 19 | // 指定SpringBoot工程的Application启动类(会测试开始前启动SpringBoot项目) 20 | @SpringBootTest(classes=MyApplication.class) 21 | // 对于Web项目,Junit需要模拟ServletContext,因此需要在测试类加上@WebAppConfiguration(如果不测试Web相关的可以不加) 22 | @WebAppConfiguration 23 | public class BaseTest { 24 | 25 | } -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/config/TestConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.PropertySource; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 自定义配置 9 | * 将配置文件属性值,映射到组件中 10 | * 11 | * @author zhuangyilian 12 | */ 13 | // 只有容器中的组件,才能使用@ConfigurationProperties提供的功能 14 | @Component 15 | // 属性前缀 16 | @ConfigurationProperties(prefix="test") 17 | // 指定配置文件(默认读取主配置文件),会从src/test/resources寻找 18 | @PropertySource(value="classpath:config/test.properties", ignoreResourceNotFound=true, encoding="UTF-8") 19 | public class TestConfig { 20 | 21 | private String value; 22 | 23 | public String getValue() { 24 | return value; 25 | } 26 | 27 | public void setValue(String value) { 28 | this.value = value; 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/resources/templates/console/msg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | [[${msg}]] 17 | 返回上一页 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/schedule/TestQuartzJob.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.schedule; 2 | 3 | import java.util.Date; 4 | 5 | import org.quartz.JobExecutionContext; 6 | import org.springframework.stereotype.Component; 7 | 8 | import com.jingqueyimu.util.DateUtil; 9 | 10 | /** 11 | * Quartz任务测试 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Component 16 | public class TestQuartzJob extends BaseJob { 17 | 18 | @Override 19 | protected void doExecute(JobExecutionContext context) { 20 | System.out.println("TestQuartzJob: " + DateUtil.format(new Date(), DateUtil.FORMAT_DATE_TIME)); 21 | } 22 | 23 | @Override 24 | public String name() { 25 | return "Quartz任务测试"; 26 | } 27 | 28 | @Override 29 | public String group() { 30 | return "test"; 31 | } 32 | 33 | @Override 34 | public String cron() { 35 | return "0 */5 * * * ?"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/notice-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 网站动态 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/resources/mapper/FeedbackMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SELECT 7 | f.id, f.user_id, f.content, f.reply, f.type, f.status, f.gmt_create, 8 | u.username 9 | FROM t_feedback f 10 | LEFT JOIN t_user u ON f.user_id = u.id 11 | WHERE 1 = 1 12 | 13 | AND f.type = #{type} 14 | 15 | 16 | AND f.status = #{status} 17 | 18 | 19 | AND u.username LIKE '%${username_like}%' 20 | 21 | ORDER BY id DESC 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitTopicReceiver.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * 主题模式消息接收者 10 | * 11 | * @author zhuangyilian 12 | */ 13 | @Component 14 | public class RabbitTopicReceiver { 15 | 16 | private Logger log = LoggerFactory.getLogger(this.getClass()); 17 | 18 | @RabbitListener(queues = RabbitTopicConfig.TOPIC_QUEUE_1) 19 | public void process1(String data) { 20 | log.debug("TopicReceiver1: {}", data); 21 | } 22 | 23 | @RabbitListener(queues = RabbitTopicConfig.TOPIC_QUEUE_2) 24 | public void process2(String data) { 25 | log.debug("TopicReceiver2: {}", data); 26 | } 27 | 28 | @RabbitListener(queues = RabbitTopicConfig.TOPIC_QUEUE_ALL) 29 | public void processAll(String data) { 30 | log.debug("TopicReceiverAll: {}", data); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitFanoutReceiver.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * 广播模式消息接收者 10 | * 11 | * @author zhuangyilian 12 | */ 13 | @Component 14 | public class RabbitFanoutReceiver { 15 | 16 | private Logger log = LoggerFactory.getLogger(this.getClass()); 17 | 18 | @RabbitListener(queues = RabbitFanoutConfig.FANOUT_QUEUE_1) 19 | public void process1(String data) { 20 | log.debug("FanoutReceiver1: {}", data); 21 | } 22 | 23 | @RabbitListener(queues = RabbitFanoutConfig.FANOUT_QUEUE_2) 24 | public void process2(String data) { 25 | log.debug("FanoutReceiver2: {}", data); 26 | } 27 | 28 | @RabbitListener(queues = RabbitFanoutConfig.FANOUT_QUEUE_3) 29 | public void process3(String data) { 30 | log.debug("FanoutReceiver3: {}", data); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/BizTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.junit.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.model.User; 11 | import com.jingqueyimu.service.UserService; 12 | 13 | /** 14 | * 业务测试 15 | * 16 | * @author zhuangyilian 17 | */ 18 | public class BizTest extends BaseTest { 19 | 20 | @Autowired 21 | private UserService userService; 22 | 23 | @Test 24 | public void test() { 25 | JSONObject params = new JSONObject(); 26 | params.put("username_like", "test"); 27 | List user = userService.list(params); 28 | System.out.println(user); 29 | } 30 | 31 | @Test 32 | public void test2() { 33 | JSONObject params = new JSONObject(); 34 | params.put("username_in", Arrays.asList("test")); 35 | List user = userService.list(params); 36 | System.out.println(user); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mapper/SqlMapper2.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mapper; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.apache.ibatis.annotations.DeleteProvider; 7 | import org.apache.ibatis.annotations.InsertProvider; 8 | import org.apache.ibatis.annotations.SelectProvider; 9 | import org.apache.ibatis.annotations.UpdateProvider; 10 | 11 | import com.jingqueyimu.mapper.sql.DynamicSql; 12 | 13 | /** 14 | * 原生SQL执行接口(注解方式) 15 | * 16 | * @author zhuangyilian 17 | */ 18 | public interface SqlMapper2 { 19 | 20 | @InsertProvider(type = DynamicSql.class, method = "sql") 21 | int insert(String sql); 22 | 23 | @DeleteProvider(type = DynamicSql.class, method = "sql") 24 | int delete(String sql); 25 | 26 | @UpdateProvider(type = DynamicSql.class, method = "sql") 27 | int update(String sql); 28 | 29 | @SelectProvider(type = DynamicSql.class, method = "sql") 30 | List> select(String sql); 31 | 32 | @SelectProvider(type = DynamicSql.class, method = "sql") 33 | int count(String sql); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.alibaba.fastjson.serializer.SerializeConfig; 8 | import com.alibaba.fastjson.serializer.SerializerFeature; 9 | import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer; 10 | 11 | /** 12 | * 基类模型 13 | * 14 | * @author zhuangyilian 15 | */ 16 | //@MappedSuperclass 17 | public abstract class BaseModel implements Serializable { 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | @Override 22 | public String toString() { 23 | return this.getClass().getName() + "=" + toJsonString(); 24 | } 25 | 26 | public String toJsonString() { 27 | SerializeConfig serializeConfig = new SerializeConfig(); 28 | serializeConfig.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); 29 | return JSONObject.toJSONString(this, serializeConfig, SerializerFeature.SortField, SerializerFeature.WriteMapNullValue); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/constant/SysConstant.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.constant; 2 | 3 | /** 4 | * 系统通用常量类 5 | * 6 | * @author zhuangyilian 7 | */ 8 | public class SysConstant { 9 | 10 | /** 11 | * 字母表 12 | */ 13 | public static final String[] LETTER_LIST = { 14 | "A", "B", "C", "D", "E", "F", "G", 15 | "H", "I", "J", "K", "L", "M", "N", 16 | "O", "P", "Q", "R", "S", "T", 17 | "U", "V", "W", "X", "Y", "Z"}; 18 | 19 | /** 20 | * 邮箱验证码有效期(10分钟) 21 | */ 22 | public static final int EMAIL_CODE_VALID_PERIOD = 60 * 10; 23 | 24 | /** 25 | * 发送邮箱验证码间隔时间(1分钟) 26 | */ 27 | public static final int SEND_EMAIL_CODE_INTERVAL = 60; 28 | 29 | /** 30 | * 短信验证码有效期(10分钟) 31 | */ 32 | public static final int SMS_CODE_VALID_PERIOD = 60 * 10; 33 | 34 | /** 35 | * 发送短信验证码间隔时间(1分钟) 36 | */ 37 | public static final int SEND_SMS_CODE_INTERVAL = 60; 38 | 39 | /** 40 | * 图形验证码有效期(30分钟) 41 | */ 42 | public static final int CAPTCHA_CODE_VALID_PERIOD = 60 * 30; 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | emmm~~~ 10 | 好像发生了什么错误?! 11 | 容我给开发提个Bug~ 12 | 返回上一页 13 | 返回首页 14 | 15 | 16 | [[${msg}]] 17 | 返回上一页 18 | 返回首页 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/static/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 404 Not Found 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | emmm~~~ 19 | 页面好像不见了! 20 | 容我问问开发~ 21 | 返回上一页 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/constant/CacheConstant.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.constant; 2 | 3 | /** 4 | * 缓存常量类 5 | * 6 | * @author zhuangyilian 7 | */ 8 | public class CacheConstant { 9 | 10 | /** 11 | * 管理员权限 12 | */ 13 | public static final String ADMIN_PERMISSION = "admin_permission_"; 14 | 15 | /** 16 | * 短信验证码 17 | */ 18 | public static final String SMS_CODE = "sms_code_"; 19 | 20 | /** 21 | * 邮箱验证码 22 | */ 23 | public static final String EMAIL_CODE = "email_code_"; 24 | 25 | /** 26 | * 上次发送短信验证码时间 27 | */ 28 | public static final String LAST_SMS_CODE_TIME = "last_sms_code_time_"; 29 | 30 | /** 31 | * 上次发送邮箱验证码时间 32 | */ 33 | public static final String LAST_EMAIL_CODE_TIME = "last_email_code_time_"; 34 | 35 | /** 36 | * 图形验证码 37 | */ 38 | public static final String CAPTCHA_CODE = "captcha_code_"; 39 | 40 | /** 41 | * 公有网站配置 42 | */ 43 | public static final String PUB_SITE_CONFIG = "pub_site_config"; 44 | 45 | /** 46 | * 私有网站配置 47 | */ 48 | public static final String PRI_SITE_CONFIG = "pri_site_config"; 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/static/error/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 500 Internal Server Error 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | emmm~~~ 19 | 好像发生了什么错误?! 20 | 容我给开发提个Bug~ 21 | 返回上一页 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/ResourceTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.junit.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import com.alibaba.fastjson.JSONArray; 10 | import com.jingqueyimu.util.ResourceUtil; 11 | 12 | /** 13 | * 资源测试 14 | * 15 | * @author zhuangyilian 16 | */ 17 | public class ResourceTest extends BaseTest { 18 | 19 | @Autowired 20 | private ResourceUtil resourceUtil; 21 | 22 | @Test 23 | public void test() { 24 | try { 25 | Map map = resourceUtil.loadMapConfigs("classpath:config/test.properties"); 26 | System.out.println("--------loadMapConfigs--------:" + map); 27 | JSONArray jsonArr = resourceUtil.loadJsonArrConfigs("classpath:config/test.json"); 28 | System.out.println("--------loadJsonArrConfigs--------:" + jsonArr); 29 | List sqls = resourceUtil.loadSqlConfig("classpath:config/test.sql"); 30 | System.out.println("--------loadSqlConfig--------:" + sqls); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsoleCategoryController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.controller.BaseController; 11 | import com.jingqueyimu.model.bean.ResultData; 12 | import com.jingqueyimu.service.CategoryService; 13 | 14 | /** 15 | * 类目控制器 16 | * 17 | * @author zhuangyilian 18 | */ 19 | @RestController 20 | @RequestMapping("/console/category") 21 | public class ConsoleCategoryController extends BaseController { 22 | 23 | @Autowired 24 | private CategoryService categoryService; 25 | 26 | /** 27 | * 查询主类目 28 | * 29 | * @param params 30 | * @return 31 | */ 32 | @PostMapping("/list_main") 33 | public ResultData listMain(@RequestBody JSONObject params) { 34 | // TODO 35 | return ResultData.succ(null); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/notice-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 阅读([[${item.readCount}]]) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 暂无动态 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/login/PasswordLoginHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.login; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.jingqueyimu.constant.StatusCode; 7 | import com.jingqueyimu.exception.AppException; 8 | import com.jingqueyimu.model.User; 9 | import com.jingqueyimu.model.dict.LoginType; 10 | import com.jingqueyimu.util.SysUtil; 11 | 12 | /** 13 | * 密码登录处理器 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Component 18 | public class PasswordLoginHandler extends LoginHandler { 19 | 20 | @Override 21 | protected int getType() { 22 | return LoginType.PASSWORD.getCode(); 23 | } 24 | 25 | @Override 26 | public User getLoginUser(JSONObject params) { 27 | SysUtil.checkParam(params, "account", "请输入账号"); 28 | SysUtil.checkParam(params, "password", "请输入密码"); 29 | String account = params.getString("account"); 30 | String password = params.getString("password"); 31 | User user = userService.getByAccountAndPassword(account, password); 32 | if (user == null) { 33 | throw new AppException(StatusCode.ERR_AUTH_ACCT_PWD, "账号密码错误"); 34 | } 35 | return user; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/api/ApiFeedbackController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.api; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.controller.BaseController; 11 | import com.jingqueyimu.model.bean.ResultData; 12 | import com.jingqueyimu.service.FeedbackService; 13 | 14 | /** 15 | * 意见反馈控制器 16 | * 17 | * @author zhuangyilian 18 | */ 19 | @RestController 20 | @RequestMapping("/api/feedback") 21 | public class ApiFeedbackController extends BaseController { 22 | 23 | @Autowired 24 | private FeedbackService feedbackService; 25 | 26 | /** 27 | * 提交反馈 28 | * 29 | * @param params 30 | * @return 31 | */ 32 | @PostMapping(value="/submit") 33 | public ResultData submit(@RequestBody JSONObject params) { 34 | params.put("userId", userContext.getCurrUser().getId()); 35 | feedbackService.submit(params); 36 | return ResultData.succ(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/NoticeService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.jingqueyimu.mapper.NoticeMapper; 7 | import com.jingqueyimu.model.Notice; 8 | 9 | /** 10 | * 公告服务 11 | * 12 | * @author zhuangyilian 13 | */ 14 | @Service 15 | public class NoticeService extends BaseService { 16 | 17 | @Autowired 18 | private NoticeMapper noticeMapper; 19 | 20 | /** 21 | * 浏览公告详情 22 | * 23 | * @param id 24 | * @return 25 | */ 26 | public Notice viewDetail(long id) { 27 | Notice notice = getById(id); 28 | if (notice == null) { 29 | return null; 30 | } 31 | notice.setReadCount(notice.getReadCount() + 1); 32 | return update(notice); 33 | } 34 | 35 | /** 36 | * 上一篇公告 37 | * 38 | * @param id 39 | * @return 40 | */ 41 | public Notice prevNotice(long id) { 42 | return noticeMapper.prevNotice(id); 43 | } 44 | 45 | /** 46 | * 下一篇公告 47 | * 48 | * @param id 49 | * @return 50 | */ 51 | public Notice nextNotice(long id) { 52 | return noticeMapper.nextNotice(id); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/factory/YamlPropertySourceFactory.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.factory; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.Properties; 7 | 8 | import org.springframework.boot.env.YamlPropertySourceLoader; 9 | import org.springframework.core.env.PropertiesPropertySource; 10 | import org.springframework.core.env.PropertySource; 11 | import org.springframework.core.io.support.EncodedResource; 12 | import org.springframework.core.io.support.PropertySourceFactory; 13 | 14 | /** 15 | * YAML属性源工厂类 16 | * 17 | * @author zhuangyilian 18 | */ 19 | public class YamlPropertySourceFactory implements PropertySourceFactory { 20 | 21 | @Override 22 | public PropertySource> createPropertySource(String name, EncodedResource resource) throws IOException { 23 | String resourceName = Optional.ofNullable(name).orElse(resource.getResource().getFilename()); 24 | if (resourceName.endsWith(".yml") || resourceName.endsWith(".yaml")) { 25 | List> yamlSources = new YamlPropertySourceLoader().load(resourceName, resource.getResource()); 26 | return yamlSources.get(0); 27 | } else { 28 | return new PropertiesPropertySource(resourceName, new Properties()); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/factory/LockFactory.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.factory; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.jingqueyimu.service.component.RedisService; 7 | 8 | /** 9 | * 分布式锁工厂 10 | * 11 | * @author zhuangyilian 12 | */ 13 | @Component 14 | public class LockFactory { 15 | 16 | @Autowired 17 | private RedisService redisService; 18 | 19 | /** 20 | * 尝试加锁 21 | * 22 | * @param key 23 | * @param waitSeconds 24 | * @param releaseSecodes 25 | * @return 26 | */ 27 | public boolean tryLock(String key, long waitSeconds, long releaseSecodes) { 28 | // 默认自动释放锁的时间: 60s 29 | if (releaseSecodes <= 0) { 30 | releaseSecodes = 60; 31 | } 32 | long startTime = System.currentTimeMillis(); 33 | while (true) { 34 | // value可以是任意值 35 | if (redisService.setnx(key, key, releaseSecodes)) { 36 | return true; 37 | } 38 | // 超过等待时间,则加锁失败 39 | if (System.currentTimeMillis() - startTime > waitSeconds * 1000) { 40 | return false; 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * 释放锁 47 | * 48 | * @param key 49 | */ 50 | public void releaseLock(String key) { 51 | redisService.delete(key); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/resources/quartz.properties: -------------------------------------------------------------------------------- 1 | # Default Properties file for use by StdSchedulerFactory 2 | # to create a Quartz Scheduler Instance, if a different 3 | # properties file is not explicitly specified. 4 | 5 | # =========================================================================== 6 | # Configure Main Scheduler Properties 调度器属性 7 | # =========================================================================== 8 | org.quartz.scheduler.instanceName: DefaultQuartzScheduler 9 | org.quartz.scheduler.rmi.export: false 10 | org.quartz.scheduler.rmi.proxy: false 11 | org.quartz.scheduler.wrapJobExecutionInUserTransaction: false 12 | 13 | # =========================================================================== 14 | # Configure ThreadPool 线程池属性 15 | # =========================================================================== 16 | # 线程池的实现类 17 | org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool 18 | # 线程数 19 | org.quartz.threadPool.threadCount: 50 20 | org.quartz.threadPool.threadPriority: 5 21 | org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true 22 | 23 | # =========================================================================== 24 | # Configure JobStore 作业存储配置 25 | # =========================================================================== 26 | # 存储时间,默认值60秒 27 | org.quartz.jobStore.misfireThreshold: 60000 28 | # 保存Job和Trigger信息到内存中的类 29 | org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore 30 | -------------------------------------------------------------------------------- /src/main/resources/config/dbinit.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "initKey": "site_config_20210110", 4 | "remark": "网站备案号", 5 | "sqls": [ 6 | "INSERT INTO t_site_config (id, code, name, content, content_type, description, public_flag, gmt_create) VALUES(NULL, 'site_record_no', '网站备案号', '备案号', '1', '网站备案号', true, NOW());" 7 | ] 8 | }, 9 | { 10 | "initKey": "site_config_20210228", 11 | "remark": "网站信息(logo,icon,关键词,描述)", 12 | "sqls": [ 13 | "INSERT INTO t_site_config (id, code, name, content, content_type, description, public_flag, gmt_create) VALUES(NULL, 'site_logo', '网站LOGO', '/images/logo.jpg', '2', '网站LOGO', true, NOW());", 14 | "INSERT INTO t_site_config (id, code, name, content, content_type, description, public_flag, gmt_create) VALUES(NULL, 'site_icon', '网站ICON', '/images/favicon.ico', '2', '网站ICON', true, NOW());", 15 | "INSERT INTO t_site_config (id, code, name, content, content_type, description, public_flag, gmt_create) VALUES(NULL, 'site_meta_keywords', '网站关键词', 'Chewing,Java,脚手架', '1', '针对搜索引擎的关键词,SEO优化', true, NOW());", 16 | "INSERT INTO t_site_config (id, code, name, content, content_type, description, public_flag, gmt_create) VALUES(NULL, 'site_meta_description', '网站描述', 'Chewing——Java 项目快速开发脚手架!', '1', '网站描述,SEO优化', true, NOW());" 17 | ] 18 | } 19 | ] -------------------------------------------------------------------------------- /chewing_docker_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------------------------- 4 | # docker启动项目脚本 5 | # -------------------------------------------------------------------------------------- 6 | 7 | # ------------------------------------------------------------------------------------- 8 | # 克隆到windows再上传到linux,或者在windows下编辑shell脚本后上传到linux时, 9 | # 由于linux与windows的换行符不同,可能会导致续行符(\)失效,从而导致shell脚本执行报错。 10 | # 此时,可以在linux下使用dos2unix命令(没有的话需要先安装)对文件进行转换。 11 | # ------------------------------------------------------------------------------------- 12 | 13 | # 应用名 14 | PROJECT=chewing 15 | # 应用版本 16 | VERSION=v1.0.0 17 | # 应用jar包路径 18 | JAR_PATH=/home/wwwroot/chewing 19 | # 应用上传文件路径 20 | FILE_PATH=/data/chewing/file 21 | 22 | cd $JAR_PATH 23 | # 构建镜像 24 | docker build -t ${PROJECT}:${VERSION} . 25 | # 停止容器 26 | docker stop ${PROJECT} 2>/dev/null 27 | # 删除容器 28 | docker rm ${PROJECT} 2>/dev/null 29 | # 启动容器 30 | docker run -d -p 9000:9000 -v ${FILE_PATH}:${FILE_PATH} -v ${JAR_PATH}:/package \ 31 | -e spring.datasource.url="jdbc:mysql://localhost:3306/chewing?useAffectedRows=true&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8" \ 32 | -e spring.datasource.username="root" \ 33 | -e spring.datasource.password="123456" \ 34 | -e spring.redis.host="127.0.0.1" \ 35 | -e myconfig.fileStoragePath=${FILE_PATH} \ 36 | --name ${PROJECT} ${PROJECT}:${VERSION} 37 | 38 | # 删除悬挂镜像 39 | docker rmi $(docker images -f "dangling=true" -q) 2>/dev/null 40 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/RabbitTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.jingqueyimu.mq.RabbitDirectConfig; 8 | import com.jingqueyimu.mq.RabbitFanoutConfig; 9 | import com.jingqueyimu.mq.RabbitTopicConfig; 10 | import com.jingqueyimu.service.component.RabbitService; 11 | 12 | /** 13 | * RabbitMQ测试 14 | * 15 | * @author zhuangyilian 16 | */ 17 | public class RabbitTest extends BaseTest { 18 | 19 | @Autowired 20 | private RabbitService rabbitService; 21 | 22 | @Test 23 | public void testSendDirect() { 24 | rabbitService.sendDirect(RabbitDirectConfig.DIRECT_QUEUE, "test direct..."); 25 | } 26 | 27 | @Test 28 | public void testSendDirectObj() { 29 | JSONObject data = new JSONObject(); 30 | data.put("content", "test direct obj..."); 31 | // 发送对象 32 | rabbitService.sendDirect(RabbitDirectConfig.DIRECT_QUEUE, data); 33 | } 34 | 35 | @Test 36 | public void testSendTopic() { 37 | rabbitService.sendTopic(RabbitTopicConfig.TOPIC_EXCHANGE, "topic.1", "test topic 1..."); 38 | // rabbitService.sendTopic(RabbitTopicConfig.TOPIC_EXCHANGE, "topic.2", "test topic 2..."); 39 | } 40 | 41 | @Test 42 | public void testSendFanout() { 43 | rabbitService.sendFanout(RabbitFanoutConfig.FANOUT_EXCHANGE, "test fanout..."); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/SmsController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.constant.StatusCode; 11 | import com.jingqueyimu.exception.AppException; 12 | import com.jingqueyimu.model.bean.ResultData; 13 | import com.jingqueyimu.service.component.SmsService; 14 | import com.jingqueyimu.util.SysUtil; 15 | 16 | /** 17 | * 短信控制器 18 | * 19 | * @author zhuangyilian 20 | */ 21 | @RestController 22 | @RequestMapping("/sms") 23 | public class SmsController extends BaseController { 24 | 25 | @Autowired 26 | private SmsService smsService; 27 | 28 | /** 29 | * 发送短信验证码 30 | * 31 | * @param params 32 | * @return 33 | */ 34 | @PostMapping(value="/send_sms_code") 35 | public ResultData sendSmsCode(@RequestBody JSONObject params) { 36 | SysUtil.checkParam(params, "mobile", "请输入手机号"); 37 | String mobile = params.getString("mobile"); 38 | if (!SysUtil.checkMobile(mobile)) { 39 | throw new AppException(StatusCode.ERR_PARAM, "手机号格式不正确"); 40 | } 41 | smsService.sendSmsCode(mobile); 42 | return ResultData.succ(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsoleOrderController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageInfo; 11 | import com.jingqueyimu.annotation.Perm; 12 | import com.jingqueyimu.controller.BaseController; 13 | import com.jingqueyimu.model.Order; 14 | import com.jingqueyimu.model.bean.ResultData; 15 | import com.jingqueyimu.service.OrderService; 16 | 17 | /** 18 | * 订单控制器 19 | * 20 | * @author zhuangyilian 21 | */ 22 | @RestController 23 | @RequestMapping("/console/order") 24 | public class ConsoleOrderController extends BaseController { 25 | 26 | @Autowired 27 | private OrderService orderService; 28 | 29 | /** 30 | * 分页查询订单 31 | * 32 | * @param params 33 | * @return 34 | */ 35 | @Perm(group="order", name="分页查询订单", description="订单管理-订单列表-分页查询订单") 36 | @PostMapping("/page") 37 | public ResultData page(@RequestBody JSONObject params) { 38 | int pageNum = params.getIntValue("pageNum"); 39 | int pageSize = params.getIntValue("pageSize"); 40 | PageInfo page = orderService.page(pageNum, pageSize, params); 41 | return ResultData.succ(page); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitDirectConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.DirectExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 直接模式队列配置 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Configuration 16 | public class RabbitDirectConfig { 17 | 18 | /** 19 | * 队列名称 20 | */ 21 | public static final String DIRECT_QUEUE = "direct.queue"; 22 | 23 | /** 24 | * 交换机名称(amq.direct: 默认的直接模式交换机,指定其他名称将创建新的交换机) 25 | */ 26 | public static final String DIRECT_EXCHANGE = "amq.direct"; 27 | 28 | /******************************* 创建队列 *******************************/ 29 | 30 | @Bean 31 | public Queue directQueue() { 32 | return new Queue(DIRECT_QUEUE, true, false, false); 33 | } 34 | 35 | /******************************* 创建交换机 *******************************/ 36 | 37 | @Bean 38 | public DirectExchange directExchange() { 39 | return new DirectExchange(DIRECT_EXCHANGE); 40 | } 41 | 42 | /******************************* 绑定队列到交换机 *******************************/ 43 | 44 | @Bean 45 | public Binding directBinding(DirectExchange directExchange, Queue directQueue) { 46 | return BindingBuilder.bind(directQueue).to(directExchange).with(DIRECT_QUEUE); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/EmailController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.constant.StatusCode; 11 | import com.jingqueyimu.exception.AppException; 12 | import com.jingqueyimu.model.bean.ResultData; 13 | import com.jingqueyimu.service.component.MailService; 14 | import com.jingqueyimu.util.SysUtil; 15 | 16 | /** 17 | * 邮箱控制器 18 | * 19 | * @author zhuangyilian 20 | */ 21 | @RestController 22 | @RequestMapping("/email") 23 | public class EmailController extends BaseController { 24 | 25 | @Autowired 26 | private MailService mailService; 27 | 28 | /** 29 | * 发送邮箱验证码 30 | * 31 | * @param params 32 | * @return 33 | */ 34 | @PostMapping(value="/send_email_code") 35 | public ResultData sendEmailCode(@RequestBody JSONObject params) { 36 | SysUtil.checkParam(params, "email", "请输入邮箱"); 37 | String email = params.getString("email"); 38 | if (email.length() > 32 || !SysUtil.checkEmail(email)) { 39 | throw new AppException(StatusCode.ERR_PARAM, "邮箱格式不正确"); 40 | } 41 | // 发送邮箱验证码 42 | mailService.sendEmailCode(email); 43 | return ResultData.succ(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsoleProductController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageInfo; 11 | import com.jingqueyimu.annotation.Perm; 12 | import com.jingqueyimu.controller.BaseController; 13 | import com.jingqueyimu.model.Product; 14 | import com.jingqueyimu.model.bean.ResultData; 15 | import com.jingqueyimu.service.ProductService; 16 | 17 | /** 18 | * 产品控制器 19 | * 20 | * @author zhuangyilian 21 | */ 22 | @RestController 23 | @RequestMapping("/console/product") 24 | public class ConsoleProductController extends BaseController { 25 | 26 | @Autowired 27 | private ProductService productService; 28 | 29 | /** 30 | * 分页查询产品 31 | * 32 | * @param params 33 | * @return 34 | */ 35 | @Perm(group="product", name="分页查询产品", description="产品管理-产品列表-分页查询产品") 36 | @PostMapping("/page") 37 | public ResultData page(@RequestBody JSONObject params) { 38 | int pageNum = params.getIntValue("pageNum"); 39 | int pageSize = params.getIntValue("pageSize"); 40 | PageInfo page = productService.page(pageNum, pageSize, params); 41 | return ResultData.succ(page); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/MailTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.junit.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | 6 | import com.jingqueyimu.service.component.MailService; 7 | 8 | /** 9 | * 邮件测试 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public class MailTest extends BaseTest { 14 | 15 | private static final String TO_MAIL = "1010092116@qq.com"; 16 | 17 | @Autowired 18 | private MailService mailService; 19 | 20 | @Test 21 | public void testSimpleMail() { 22 | mailService.sendSimpleMail(TO_MAIL, "test simple mail", "This is a simple mail"); 23 | } 24 | 25 | @Test 26 | public void testHtmlMail() { 27 | String content = "\n" + 28 | "\n" + 29 | " This is a html email\n" + 30 | "\n" + 31 | ""; 32 | mailService.sendHtmlMail(TO_MAIL, "test html mail", content); 33 | } 34 | 35 | @Test 36 | public void testAttachmentsMail() { 37 | String filePath = "D:\\test.txt"; 38 | mailService.sendAttachmentsMail(TO_MAIL, "test attachments mail", "注意查收附件...", filePath); 39 | } 40 | 41 | @Test 42 | public void testInlineResourceMail() { 43 | String cid = "pic_test_001"; 44 | String content="这是有图片的邮件:"; 45 | String imgPath = "D:\\pic_test.jpg"; 46 | mailService.sendInlineResourceMail(TO_MAIL, "test inline resource mail", content, imgPath, cid); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsolePermissionController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageInfo; 11 | import com.jingqueyimu.annotation.Perm; 12 | import com.jingqueyimu.controller.BaseController; 13 | import com.jingqueyimu.model.Permission; 14 | import com.jingqueyimu.model.bean.ResultData; 15 | import com.jingqueyimu.service.PermissionService; 16 | 17 | /** 18 | * 权限控制器 19 | * 20 | * @author zhuangyilian 21 | */ 22 | @RestController 23 | @RequestMapping("/console/permission") 24 | public class ConsolePermissionController extends BaseController { 25 | 26 | @Autowired 27 | private PermissionService permissionService; 28 | 29 | /** 30 | * 分页查询权限 31 | * 32 | * @param params 33 | * @return 34 | */ 35 | @Perm(group="admin", name="分页查询权限", description="管理员管理-管理员列表-分页查询权限") 36 | @PostMapping("/page") 37 | public ResultData page(@RequestBody JSONObject params) { 38 | int pageNum = params.getIntValue("pageNum"); 39 | int pageSize = params.getIntValue("pageSize"); 40 | PageInfo page = permissionService.page(pageNum, pageSize, params); 41 | return ResultData.succ(page); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/filter/LogFilter.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.Filter; 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.FilterConfig; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.stereotype.Component; 17 | 18 | /** 19 | * 日志过滤器 20 | * 21 | * @author zhuangyilian 22 | */ 23 | @Component 24 | public class LogFilter implements Filter { 25 | 26 | private Logger log = LoggerFactory.getLogger(this.getClass()); 27 | 28 | @Override 29 | public void init(FilterConfig filterConfig) throws ServletException { 30 | // 初始化Filter时调用 31 | } 32 | 33 | @Override 34 | public void destroy() { 35 | // 销毁Filter时调用 36 | } 37 | 38 | /** 39 | * 过滤处理 40 | */ 41 | @Override 42 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 43 | throws IOException, ServletException { 44 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 45 | HttpServletResponse httpServletResponse = (HttpServletResponse) response; 46 | 47 | // TODO 打印更多的日志信息 48 | log.info("请求地址: {}", httpServletRequest.getRequestURL().toString()); 49 | 50 | chain.doFilter(request,response); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/login/LoginHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.login; 2 | 3 | import java.util.Date; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import javax.annotation.PostConstruct; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | 11 | import com.alibaba.fastjson.JSONObject; 12 | import com.jingqueyimu.constant.StatusCode; 13 | import com.jingqueyimu.exception.AppException; 14 | import com.jingqueyimu.model.User; 15 | import com.jingqueyimu.service.UserService; 16 | import com.jingqueyimu.service.component.RedisService; 17 | 18 | /** 19 | * 登录处理器抽象类 20 | * 21 | * @author zhuangyilian 22 | */ 23 | public abstract class LoginHandler { 24 | 25 | private static final Map HANDLERS = new HashMap<>(); 26 | 27 | @Autowired 28 | protected UserService userService; 29 | @Autowired 30 | protected RedisService redisService; 31 | 32 | protected abstract int getType(); 33 | 34 | protected abstract User getLoginUser(JSONObject params); 35 | 36 | @PostConstruct 37 | protected void init() { 38 | HANDLERS.put(getType(), this); 39 | } 40 | 41 | public User handle(JSONObject params) { 42 | User user = getLoginUser(params); 43 | if (user == null) { 44 | throw new AppException(StatusCode.ERR_AUTH, "登录失败"); 45 | } 46 | user.setLastLoginTime(new Date()); 47 | return userService.update(user); 48 | } 49 | 50 | public static LoginHandler getHandler(int type) { 51 | return HANDLERS.get(type); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/config/InterceptorConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistration; 6 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 7 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | import com.jingqueyimu.interceptor.GlobalInterceptor; 11 | 12 | /** 13 | * 拦截器配置 14 | * 最好实现WebMvcConfigurer,而不要继承WebMvcConfigurationSupport 15 | * 继承WebMvcConfigurationSupport,会导致springboot自动配置失效(会导致访问不到默认的静态资源路径) 16 | * 17 | * @author zhuangyilian 18 | */ 19 | @Configuration 20 | public class InterceptorConfig implements WebMvcConfigurer { 21 | 22 | @Autowired 23 | private GlobalInterceptor globalInterceptor; 24 | 25 | /** 26 | * 注册拦截器 27 | */ 28 | @Override 29 | public void addInterceptors(InterceptorRegistry registry) { 30 | // 可以添加多个拦截器 31 | InterceptorRegistration ig = registry.addInterceptor(globalInterceptor); 32 | // 排除拦截路径 33 | // ig.excludePathPatterns("/file/**"); 34 | // 添加拦截路径 35 | ig.addPathPatterns("/**"); 36 | } 37 | 38 | /** 39 | * 添加静态资源路径 40 | */ 41 | @Override 42 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 43 | registry.addResourceHandler("/teststatic/**").addResourceLocations("classpath:/teststatic/"); 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/SiteConfigController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestBody; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import com.alibaba.fastjson.JSONObject; 9 | import com.jingqueyimu.model.SiteConfig; 10 | import com.jingqueyimu.model.bean.ResultData; 11 | import com.jingqueyimu.service.SiteConfigService; 12 | 13 | /** 14 | * 网站配置控制器 15 | * 16 | * @author zhuangyilian 17 | */ 18 | @RestController 19 | @RequestMapping("/site_config") 20 | public class SiteConfigController extends BaseController { 21 | 22 | @Autowired 23 | private SiteConfigService siteConfigService; 24 | 25 | /** 26 | * 获取配置 27 | * 28 | * @param params 29 | * @return 30 | */ 31 | @RequestMapping("/get") 32 | public ResultData get(@RequestBody JSONObject params) { 33 | params.put("publicFlag", true); 34 | SiteConfig siteConfig = siteConfigService.get(params); 35 | return ResultData.succ(siteConfig); 36 | } 37 | 38 | /** 39 | * 获取配置内容 40 | * 41 | * @param params 42 | * @return 43 | */ 44 | @RequestMapping("/get_content") 45 | public ResultData getContent(@RequestBody JSONObject params) { 46 | params.put("publicFlag", true); 47 | SiteConfig siteConfig = siteConfigService.get(params); 48 | return ResultData.succ(siteConfig == null ? null : siteConfig.getContent()); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/PayType.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 付款方式 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum PayType { 12 | 13 | OFFLINE(1, "线下付款"), 14 | 15 | WECHAT(2, "微信付款"), 16 | 17 | ALIPAY(3, "支付宝付款"); 18 | 19 | private int code; 20 | 21 | private String value; 22 | 23 | PayType(int code, String value) { 24 | this.code = code; 25 | this.value = value; 26 | } 27 | 28 | public int getCode() { 29 | return code; 30 | } 31 | 32 | public void setCode(int code) { 33 | this.code = code; 34 | } 35 | 36 | public String getValue() { 37 | return value; 38 | } 39 | 40 | public void setValue(String value) { 41 | this.value = value; 42 | } 43 | 44 | /** 45 | * 获取枚举 46 | * 47 | * @param code 48 | * @return 49 | */ 50 | public static PayType getEnum(int code) { 51 | PayType[] enums = PayType.values(); 52 | for (PayType e : enums) { 53 | if (e.code == code) { 54 | return e; 55 | } 56 | } 57 | return null; 58 | } 59 | 60 | /** 61 | * 获取枚举信息 62 | * 63 | * @return 64 | */ 65 | public static Map getEnumInfo() { 66 | Map map = new HashMap(); 67 | PayType[] enums = PayType.values(); 68 | for (PayType e : enums) { 69 | map.put(e.getCode(), e.getValue()); 70 | } 71 | return map; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/ProductStatus.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 产品状态 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum ProductStatus { 12 | 13 | UP(0, "上架"), 14 | 15 | DOWN(1, "下架"); 16 | 17 | private int code; 18 | 19 | private String value; 20 | 21 | ProductStatus(Integer code, String value) { 22 | this.code = code; 23 | this.value = value; 24 | } 25 | 26 | public Integer getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(int code) { 31 | this.code = code; 32 | } 33 | 34 | public String getValue() { 35 | return value; 36 | } 37 | 38 | public void setValue(String value) { 39 | this.value = value; 40 | } 41 | 42 | /** 43 | * 获取枚举 44 | * 45 | * @param code 46 | * @return 47 | */ 48 | public static ProductStatus getEnum(int code) { 49 | ProductStatus[] enums = ProductStatus.values(); 50 | for (ProductStatus e : enums) { 51 | if (e.code == code) { 52 | return e; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * 获取枚举信息 60 | * 61 | * @return 62 | */ 63 | public static Map getEnumInfo() { 64 | Map map = new HashMap(); 65 | ProductStatus[] enums = ProductStatus.values(); 66 | for (ProductStatus e : enums) { 67 | map.put(e.getCode(), e.getValue()); 68 | } 69 | return map; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/FeedbackStatus.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 反馈类型 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum FeedbackStatus { 12 | 13 | WAIT(0, "待处理"), 14 | 15 | DONE(1, "已处理"); 16 | 17 | private int code; 18 | 19 | private String value; 20 | 21 | FeedbackStatus(int code, String value) { 22 | this.code = code; 23 | this.value = value; 24 | } 25 | 26 | public int getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(int code) { 31 | this.code = code; 32 | } 33 | 34 | public String getValue() { 35 | return value; 36 | } 37 | 38 | public void setValue(String value) { 39 | this.value = value; 40 | } 41 | 42 | /** 43 | * 获取枚举 44 | * 45 | * @param code 46 | * @return 47 | */ 48 | public static FeedbackStatus getEnum(int code) { 49 | FeedbackStatus[] enums = FeedbackStatus.values(); 50 | for (FeedbackStatus e : enums) { 51 | if (e.code == code) { 52 | return e; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * 获取枚举信息 60 | * 61 | * @return 62 | */ 63 | public static Map getEnumInfo() { 64 | Map map = new HashMap(); 65 | FeedbackStatus[] enums = FeedbackStatus.values(); 66 | for (FeedbackStatus e : enums) { 67 | map.put(e.getCode(), e.getValue()); 68 | } 69 | return map; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/util/Dom4JUtil.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.util; 2 | 3 | import java.util.Iterator; 4 | 5 | import org.dom4j.Document; 6 | import org.dom4j.DocumentException; 7 | import org.dom4j.DocumentHelper; 8 | import org.dom4j.Element; 9 | 10 | import com.alibaba.fastjson.JSONObject; 11 | 12 | /** 13 | * Dom4J工具类 14 | * 15 | * @author zhuangyilian 16 | */ 17 | public class Dom4JUtil { 18 | 19 | /** 20 | * 解析XML为JSON格式 21 | * 22 | * @param xml 23 | * @return 24 | */ 25 | public static JSONObject xmlToJson(String xml) { 26 | JSONObject json = new JSONObject(); 27 | try { 28 | Document document = DocumentHelper.parseText(xml); 29 | // 根节点 30 | Element rootElement = document.getRootElement(); 31 | Iterator iterator = rootElement.elementIterator(); 32 | while (iterator.hasNext()) { 33 | Element childElement = (Element) iterator.next(); 34 | parseElement(childElement, json); 35 | } 36 | } catch (DocumentException e) { 37 | e.printStackTrace(); 38 | } 39 | return json; 40 | } 41 | 42 | /** 43 | * 解析XML元素 44 | * 45 | * @param element 46 | * @param json 47 | */ 48 | private static void parseElement(Element element, JSONObject json) { 49 | json.put(element.getName(), element.getData()); 50 | Iterator iterator = element.elementIterator(); 51 | while (iterator.hasNext()) { 52 | Element childElement = (Element) iterator.next(); 53 | parseElement(childElement, json); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/LoginType.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 登录方式 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum LoginType { 12 | 13 | PASSWORD(1, "密码"), 14 | 15 | SMS(2, "短信"), 16 | 17 | EMAIL(3, "邮箱"), 18 | 19 | OAUTH(4, "授权"); 20 | 21 | private int code; 22 | 23 | private String value; 24 | 25 | LoginType(int code, String value) { 26 | this.code = code; 27 | this.value = value; 28 | } 29 | 30 | public int getCode() { 31 | return code; 32 | } 33 | 34 | public void setCode(int code) { 35 | this.code = code; 36 | } 37 | 38 | public String getValue() { 39 | return value; 40 | } 41 | 42 | public void setValue(String value) { 43 | this.value = value; 44 | } 45 | 46 | /** 47 | * 获取枚举 48 | * 49 | * @param code 50 | * @return 51 | */ 52 | public static LoginType getEnum(int code) { 53 | LoginType[] enums = LoginType.values(); 54 | for (LoginType e : enums) { 55 | if (e.code == code) { 56 | return e; 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | /** 63 | * 获取枚举信息 64 | * 65 | * @return 66 | */ 67 | public static Map getEnumInfo() { 68 | Map map = new HashMap(); 69 | LoginType[] enums = LoginType.values(); 70 | for (LoginType e : enums) { 71 | map.put(e.getCode(), e.getValue()); 72 | } 73 | return map; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/FeedbackType.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 反馈类型 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum FeedbackType { 12 | 13 | PROBLEM(1, "问题反馈"), 14 | 15 | SUGGESTION(2, "功能建议"), 16 | 17 | OTHER(99, "其他"); 18 | 19 | private int code; 20 | 21 | private String value; 22 | 23 | FeedbackType(int code, String value) { 24 | this.code = code; 25 | this.value = value; 26 | } 27 | 28 | public int getCode() { 29 | return code; 30 | } 31 | 32 | public void setCode(int code) { 33 | this.code = code; 34 | } 35 | 36 | public String getValue() { 37 | return value; 38 | } 39 | 40 | public void setValue(String value) { 41 | this.value = value; 42 | } 43 | 44 | /** 45 | * 获取枚举 46 | * 47 | * @param code 48 | * @return 49 | */ 50 | public static FeedbackType getEnum(int code) { 51 | FeedbackType[] enums = FeedbackType.values(); 52 | for (FeedbackType e : enums) { 53 | if (e.code == code) { 54 | return e; 55 | } 56 | } 57 | return null; 58 | } 59 | 60 | /** 61 | * 获取枚举信息 62 | * 63 | * @return 64 | */ 65 | public static Map getEnumInfo() { 66 | Map map = new HashMap(); 67 | FeedbackType[] enums = FeedbackType.values(); 68 | for (FeedbackType e : enums) { 69 | map.put(e.getCode(), e.getValue()); 70 | } 71 | return map; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.builder.SpringApplicationBuilder; 8 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; 9 | import org.springframework.cache.annotation.EnableCaching; 10 | import org.springframework.scheduling.annotation.EnableAsync; 11 | import org.springframework.scheduling.annotation.EnableScheduling; 12 | 13 | import tk.mybatis.spring.annotation.MapperScan; 14 | 15 | /** 16 | * 项目启动类 17 | * 使用外部tomcat时,必须继承SpringBootServletInitializer,并实现configure 18 | * 19 | * @author zhuangyilian 20 | */ 21 | @SpringBootApplication 22 | // 使用通用mapper时,要导入tk.mybatis.spring.annotation.MapperScan 23 | @MapperScan("com.jingqueyimu.mapper") 24 | // 开启缓存 25 | @EnableCaching 26 | // 开启定时任务 27 | @EnableScheduling 28 | // 开启异步调用 29 | @EnableAsync 30 | public class MyApplication extends SpringBootServletInitializer { 31 | 32 | public static final Logger log = LoggerFactory.getLogger(MyApplication.class); 33 | 34 | public static void main(String[] args) { 35 | long begin = System.currentTimeMillis(); 36 | SpringApplication.run(MyApplication.class, args); 37 | long end = System.currentTimeMillis(); 38 | log.info("The service has been fully started, taking {} seconds.", (end - begin) / 1000D); 39 | } 40 | 41 | @Override 42 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 43 | return builder.sources(MyApplication.class); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/ScheduleJobStatus.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 调度任务状态 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum ScheduleJobStatus { 12 | 13 | OPEN(0, "开启"), 14 | 15 | CLOSE(1, "关闭"); 16 | 17 | private int code; 18 | 19 | private String value; 20 | 21 | ScheduleJobStatus(Integer code, String value) { 22 | this.code = code; 23 | this.value = value; 24 | } 25 | 26 | public Integer getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(int code) { 31 | this.code = code; 32 | } 33 | 34 | public String getValue() { 35 | return value; 36 | } 37 | 38 | public void setValue(String value) { 39 | this.value = value; 40 | } 41 | 42 | /** 43 | * 获取枚举 44 | * 45 | * @param code 46 | * @return 47 | */ 48 | public static ScheduleJobStatus getEnum(int code) { 49 | ScheduleJobStatus[] enums = ScheduleJobStatus.values(); 50 | for (ScheduleJobStatus e : enums) { 51 | if (e.code == code) { 52 | return e; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * 获取枚举信息 60 | * 61 | * @return 62 | */ 63 | public static Map getEnumInfo() { 64 | Map map = new HashMap(); 65 | ScheduleJobStatus[] enums = ScheduleJobStatus.values(); 66 | for (ScheduleJobStatus e : enums) { 67 | map.put(e.getCode(), e.getValue()); 68 | } 69 | return map; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/constant/StatusCode.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.constant; 2 | 3 | /** 4 | * 状态码 5 | * 大于0: 成功 6 | * 等于0: 失败-未知错误 7 | * 小于0: 失败 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public class StatusCode { 12 | 13 | /*********************************** 成功状态码 ***********************************/ 14 | 15 | /** 16 | * 成功 17 | */ 18 | public static final int OK = 1; 19 | /** 20 | * 成功-重复执行 21 | */ 22 | public static final int OK_REPEAT = 2; 23 | 24 | /*********************************** 失败状态码 ***********************************/ 25 | 26 | /** 27 | * 未知错误 28 | */ 29 | public static final int ERR_UNKNOWN = 0; 30 | 31 | /** 32 | * 系统错误 33 | */ 34 | public static final int ERR_SYS = -1000; 35 | /** 36 | * 系统错误-锁 37 | */ 38 | public static final int ERR_SYS_LOCK = -1001; 39 | 40 | /** 41 | * 权限错误 42 | */ 43 | public static final int ERR_AUTH = -2000; 44 | /** 45 | * 权限错误-未登录 46 | */ 47 | public static final int ERR_AUTH_NO_LOGIN = -2001; 48 | /** 49 | * 权限错误-账号密码错误 50 | */ 51 | public static final int ERR_AUTH_ACCT_PWD = -2002; 52 | 53 | /** 54 | * 参数错误 55 | */ 56 | public static final int ERR_PARAM = -3000; 57 | 58 | /** 59 | * 参数错误-参数为空 60 | */ 61 | public static final int ERR_PARAM_EMPTY = -3001; 62 | 63 | /** 64 | * 业务错误 65 | */ 66 | public static final int ERR_BIZ = -4000; 67 | /** 68 | * 业务错误-重复执行 69 | */ 70 | public static final int ERR_BIZ_REPEAT = -4001; 71 | 72 | /** 73 | * 第三方错误 74 | */ 75 | public static final int ERR_THIRD = -5000; 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/RegisterType.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 注册方式 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum RegisterType { 12 | 13 | MOBILE(1, "手机号"), 14 | 15 | EMAIL(2, "邮箱"), 16 | 17 | QQ(3, "QQ"), 18 | 19 | WX(4, "微信"); 20 | 21 | private int code; 22 | 23 | private String value; 24 | 25 | RegisterType(int code, String value) { 26 | this.code = code; 27 | this.value = value; 28 | } 29 | 30 | public int getCode() { 31 | return code; 32 | } 33 | 34 | public void setCode(int code) { 35 | this.code = code; 36 | } 37 | 38 | public String getValue() { 39 | return value; 40 | } 41 | 42 | public void setValue(String value) { 43 | this.value = value; 44 | } 45 | 46 | /** 47 | * 获取枚举 48 | * 49 | * @param code 50 | * @return 51 | */ 52 | public static RegisterType getEnum(int code) { 53 | RegisterType[] enums = RegisterType.values(); 54 | for (RegisterType e : enums) { 55 | if (e.code == code) { 56 | return e; 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | /** 63 | * 获取枚举信息 64 | * 65 | * @return 66 | */ 67 | public static Map getEnumInfo() { 68 | Map map = new HashMap(); 69 | RegisterType[] enums = RegisterType.values(); 70 | for (RegisterType e : enums) { 71 | map.put(e.getCode(), e.getValue()); 72 | } 73 | return map; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/component/RabbitService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service.component; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.amqp.core.AmqpTemplate; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * RabbitMQ消息队列服务 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Service 16 | @ConditionalOnBean(AmqpTemplate.class) 17 | public class RabbitService { 18 | 19 | private final Logger log = LoggerFactory.getLogger(this.getClass()); 20 | 21 | @Autowired 22 | private AmqpTemplate rabbitTemplate; 23 | 24 | /** 25 | * 直接发送 26 | * 27 | * @param route 28 | * @param msg 29 | */ 30 | public void sendDirect(String route, Object msg) { 31 | log.debug("DirectSender: {}", msg); 32 | // 默认交换机模式为direct,并且路由键为direct队列名 33 | rabbitTemplate.convertAndSend(route, msg); 34 | } 35 | 36 | /** 37 | * 通配符模式发送 38 | * 39 | * @param exchange 40 | * @param route 41 | * @param msg 42 | */ 43 | public void sendTopic(String exchange, String route, Object msg) { 44 | log.debug("TopicSender: {}", msg); 45 | rabbitTemplate.convertAndSend(exchange, route, msg); 46 | } 47 | 48 | /** 49 | * 广播模式发送 50 | * 51 | * @param exchange 52 | * @param msg 53 | */ 54 | public void sendFanout(String exchange, Object msg) { 55 | log.debug("FanoutSender: {}", msg); 56 | // 指定广播模式时,无论设置什么样的路由键都会被忽略 57 | rabbitTemplate.convertAndSend(exchange, "", msg); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/SiteConfigContentType.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 网站配置内容类型 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum SiteConfigContentType { 12 | 13 | TEXT(1, "文本"), 14 | 15 | IMAGE(2, "图片"); 16 | 17 | private int code; 18 | 19 | private String value; 20 | 21 | SiteConfigContentType(int code, String value) { 22 | this.code = code; 23 | this.value = value; 24 | } 25 | 26 | public int getCode() { 27 | return code; 28 | } 29 | 30 | public void setCode(int code) { 31 | this.code = code; 32 | } 33 | 34 | public String getValue() { 35 | return value; 36 | } 37 | 38 | public void setValue(String value) { 39 | this.value = value; 40 | } 41 | 42 | /** 43 | * 获取枚举 44 | * 45 | * @param code 46 | * @return 47 | */ 48 | public static SiteConfigContentType getEnum(int code) { 49 | SiteConfigContentType[] enums = SiteConfigContentType.values(); 50 | for (SiteConfigContentType e : enums) { 51 | if (e.code == code) { 52 | return e; 53 | } 54 | } 55 | return null; 56 | } 57 | 58 | /** 59 | * 获取枚举信息 60 | * 61 | * @return 62 | */ 63 | public static Map getEnumInfo() { 64 | Map map = new HashMap(); 65 | SiteConfigContentType[] enums = SiteConfigContentType.values(); 66 | for (SiteConfigContentType e : enums) { 67 | map.put(e.getCode(), e.getValue()); 68 | } 69 | return map; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/OrderStatus.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 订单状态 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum OrderStatus { 12 | 13 | WAIT(0, "待付款"), 14 | 15 | DOING(1, "付款中"), 16 | 17 | SUCC(2, "付款成功"), 18 | 19 | FAIL(3, "付款失败"), 20 | 21 | CANCEL(4, "放弃付款"); 22 | 23 | private int code; 24 | 25 | private String value; 26 | 27 | OrderStatus(Integer code, String value) { 28 | this.code = code; 29 | this.value = value; 30 | } 31 | 32 | public Integer getCode() { 33 | return code; 34 | } 35 | 36 | public void setCode(int code) { 37 | this.code = code; 38 | } 39 | 40 | public String getValue() { 41 | return value; 42 | } 43 | 44 | public void setValue(String value) { 45 | this.value = value; 46 | } 47 | 48 | /** 49 | * 获取枚举 50 | * 51 | * @param code 52 | * @return 53 | */ 54 | public static OrderStatus getEnum(int code) { 55 | OrderStatus[] enums = OrderStatus.values(); 56 | for (OrderStatus e : enums) { 57 | if (e.code == code) { 58 | return e; 59 | } 60 | } 61 | return null; 62 | } 63 | 64 | /** 65 | * 获取枚举信息 66 | * 67 | * @return 68 | */ 69 | public static Map getEnumInfo() { 70 | Map map = new HashMap(); 71 | OrderStatus[] enums = OrderStatus.values(); 72 | for (OrderStatus e : enums) { 73 | map.put(e.getCode(), e.getValue()); 74 | } 75 | return map; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/ScheduleJobExecuteStatus.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 调度任务执行状态 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum ScheduleJobExecuteStatus { 12 | 13 | NO_EXECUTE(0, "未执行"), 14 | 15 | IN_EXECUTE(1, "执行中"), 16 | 17 | WAIT_EXECUTE(2, "待下次执行"); 18 | 19 | private int code; 20 | 21 | private String value; 22 | 23 | ScheduleJobExecuteStatus(Integer code, String value) { 24 | this.code = code; 25 | this.value = value; 26 | } 27 | 28 | public Integer getCode() { 29 | return code; 30 | } 31 | 32 | public void setCode(int code) { 33 | this.code = code; 34 | } 35 | 36 | public String getValue() { 37 | return value; 38 | } 39 | 40 | public void setValue(String value) { 41 | this.value = value; 42 | } 43 | 44 | /** 45 | * 获取枚举 46 | * 47 | * @param code 48 | * @return 49 | */ 50 | public static ScheduleJobExecuteStatus getEnum(int code) { 51 | ScheduleJobExecuteStatus[] enums = ScheduleJobExecuteStatus.values(); 52 | for (ScheduleJobExecuteStatus e : enums) { 53 | if (e.code == code) { 54 | return e; 55 | } 56 | } 57 | return null; 58 | } 59 | 60 | /** 61 | * 获取枚举信息 62 | * 63 | * @return 64 | */ 65 | public static Map getEnumInfo() { 66 | Map map = new HashMap(); 67 | ScheduleJobExecuteStatus[] enums = ScheduleJobExecuteStatus.values(); 68 | for (ScheduleJobExecuteStatus e : enums) { 69 | map.put(e.getCode(), e.getValue()); 70 | } 71 | return map; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/util/IpUtil.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.util; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.springframework.web.context.request.RequestContextHolder; 10 | import org.springframework.web.context.request.ServletRequestAttributes; 11 | 12 | import cn.hutool.core.net.Ipv4Util; 13 | 14 | /** 15 | * IP工具类 16 | * 17 | * @author zhuangyilian 18 | */ 19 | public class IpUtil extends Ipv4Util{ 20 | 21 | /** 22 | * 获取服务IP 23 | * 24 | * @param defaultIp 25 | * @return 26 | */ 27 | public static String getServerIp(String defaultIp) { 28 | try { 29 | return InetAddress.getLocalHost().getHostAddress(); 30 | } catch (UnknownHostException e) { 31 | e.printStackTrace(); 32 | } 33 | return defaultIp; 34 | } 35 | 36 | /** 37 | * 获取请求IP 38 | * 39 | * @return 40 | */ 41 | public static String getRemoteIp() { 42 | HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 43 | String ip = request.getHeader("X-Real-IP"); 44 | if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) { 45 | return ip; 46 | } 47 | ip = request.getHeader("X-Forwarded-For"); 48 | if (StringUtils.isNotBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) { 49 | // 多次代理后会有多个ip值,第一个ip才是真实ip 50 | int index = ip.indexOf(","); 51 | if (index != -1) { 52 | return ip.substring(0, index); 53 | } else { 54 | return ip; 55 | } 56 | } 57 | return request.getRemoteAddr(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/feedback-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 意见反馈 10 | 11 | --反馈类型-- 12 | 13 | 14 | 15 | 16 | 提交 17 | 18 | 19 | 20 | 21 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/config/FilterConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import com.jingqueyimu.filter.AuthFilter; 9 | import com.jingqueyimu.filter.LogFilter; 10 | 11 | /** 12 | * 过滤器配置 13 | * 14 | * @author zhuangyilian 15 | */ 16 | // 相当于xml的beans 17 | @Configuration 18 | public class FilterConfig { 19 | 20 | @Autowired 21 | private LogFilter logFilter; 22 | @Autowired 23 | private AuthFilter authFilter; 24 | 25 | /** 26 | * 注册日志过滤器 27 | * 28 | * @return 29 | */ 30 | @Bean 31 | public FilterRegistrationBean registerLogFilter() { 32 | FilterRegistrationBean registration = new FilterRegistrationBean(); 33 | // 设置过滤器 34 | registration.setFilter(logFilter); 35 | // 过滤路径 36 | registration.addUrlPatterns("/*"); 37 | // 过滤器名 38 | registration.setName("logFilter"); 39 | // 过滤器执行顺序 40 | registration.setOrder(1); 41 | return registration; 42 | } 43 | 44 | /** 45 | * 注册权限过滤器 46 | * 47 | * @return 48 | */ 49 | @Bean 50 | public FilterRegistrationBean registerAuthFilter() { 51 | FilterRegistrationBean registration = new FilterRegistrationBean(); 52 | // 设置过滤器 53 | registration.setFilter(authFilter); 54 | // 过滤路径 55 | registration.addUrlPatterns("/*"); 56 | // 过滤器名 57 | registration.setName("authFilter"); 58 | // 过滤器执行顺序 59 | registration.setOrder(2); 60 | return registration; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/NoticeController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageInfo; 11 | import com.jingqueyimu.constant.StatusCode; 12 | import com.jingqueyimu.exception.AppException; 13 | import com.jingqueyimu.model.Notice; 14 | import com.jingqueyimu.model.bean.ResultData; 15 | import com.jingqueyimu.service.NoticeService; 16 | 17 | /** 18 | * 公告控制器 19 | * 20 | * @author zhuangyilian 21 | */ 22 | @RestController 23 | @RequestMapping("/notice") 24 | public class NoticeController extends BaseController { 25 | 26 | @Autowired 27 | private NoticeService noticeService; 28 | 29 | /** 30 | * 分页查询公告 31 | * 32 | * @param params 33 | * @return 34 | */ 35 | @PostMapping("/page") 36 | public ResultData page(@RequestBody JSONObject params) { 37 | int pageNum = params.getIntValue("pageNum"); 38 | int pageSize = params.getIntValue("pageSize"); 39 | PageInfo page = noticeService.page(pageNum, pageSize, params); 40 | return ResultData.succ(page); 41 | } 42 | 43 | /** 44 | * 获取公告 45 | * 46 | * @param params 47 | * @return 48 | */ 49 | @RequestMapping("/get") 50 | public ResultData get(@RequestBody JSONObject params) { 51 | if (params.isEmpty()) { 52 | throw new AppException(StatusCode.ERR_PARAM, "查询参数不能为空"); 53 | } 54 | Notice notice = noticeService.get(params); 55 | return ResultData.succ(notice); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/dict/PermissionGroup.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.dict; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 权限分组 8 | * 9 | * @author zhuangyilian 10 | */ 11 | public enum PermissionGroup { 12 | 13 | HOME("home", "首页"), 14 | 15 | USER("user", "用户管理"), 16 | 17 | ADMIN("admin", "管理员管理"), 18 | 19 | PRODUCT("product", "产品管理"), 20 | 21 | ORDER("order", "订单管理"), 22 | 23 | FEEDBACK("feedback", "反馈管理"), 24 | 25 | SYSTEM("system", "系统管理"), 26 | 27 | OTHER("other", "其他"); 28 | 29 | private String code; 30 | 31 | private String value; 32 | 33 | PermissionGroup(String code, String value) { 34 | this.code = code; 35 | this.value = value; 36 | } 37 | 38 | public String getCode() { 39 | return code; 40 | } 41 | 42 | public void setCode(String code) { 43 | this.code = code; 44 | } 45 | 46 | public String getValue() { 47 | return value; 48 | } 49 | 50 | public void setValue(String value) { 51 | this.value = value; 52 | } 53 | 54 | /** 55 | * 获取枚举 56 | * 57 | * @param code 58 | * @return 59 | */ 60 | public static PermissionGroup getEnum(String code) { 61 | PermissionGroup[] enums = PermissionGroup.values(); 62 | for (PermissionGroup e : enums) { 63 | if (e.code == code) { 64 | return e; 65 | } 66 | } 67 | return null; 68 | } 69 | 70 | /** 71 | * 获取枚举信息 72 | * 73 | * @return 74 | */ 75 | public static Map getEnumInfo() { 76 | Map map = new HashMap(); 77 | PermissionGroup[] enums = PermissionGroup.values(); 78 | for (PermissionGroup e : enums) { 79 | map.put(e.getCode(), e.getValue()); 80 | } 81 | return map; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/component/CaptchaService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service.component; 2 | 3 | import java.awt.Image; 4 | 5 | import org.apache.commons.lang3.RandomStringUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.jingqueyimu.constant.CacheConstant; 10 | import com.jingqueyimu.constant.StatusCode; 11 | import com.jingqueyimu.constant.SysConstant; 12 | import com.jingqueyimu.exception.AppException; 13 | 14 | import cn.hutool.captcha.CaptchaUtil; 15 | import cn.hutool.captcha.LineCaptcha; 16 | 17 | /** 18 | * 图形验证码服务 19 | * 20 | * @author zhuangyilian 21 | */ 22 | @Service 23 | public class CaptchaService { 24 | 25 | @Autowired 26 | private RedisService redisService; 27 | 28 | /** 29 | * 生成图形验证码 30 | * 31 | * @param token 32 | * @return 33 | */ 34 | public Image createCaptcha(String token) { 35 | // 字母数字验证码 36 | String code = RandomStringUtils.randomAlphanumeric(4); 37 | LineCaptcha captcha = CaptchaUtil.createLineCaptcha(120, 50, 4, 100); 38 | Image image = captcha.createImage(code); 39 | // 缓存验证码 40 | redisService.set(CacheConstant.CAPTCHA_CODE + token, code, SysConstant.CAPTCHA_CODE_VALID_PERIOD); 41 | return image; 42 | } 43 | 44 | /** 45 | * 校验图形验证码 46 | * 47 | * @param token 48 | * @param captchaCode 49 | */ 50 | public void checkCaptchaCode(String token, String captchaCode) { 51 | Object captchaCodeObj = redisService.get(CacheConstant.CAPTCHA_CODE + token); 52 | if (captchaCodeObj == null) { 53 | throw new AppException(StatusCode.ERR_BIZ, "图形验证码失效,请点击刷新"); 54 | } 55 | if (!captchaCodeObj.toString().equalsIgnoreCase(captchaCode)) { 56 | throw new AppException(StatusCode.ERR_BIZ, "图形验证码错误"); 57 | } 58 | redisService.delete(CacheConstant.CAPTCHA_CODE + token); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/notice-detail.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 返回网站动态 27 | 28 | 29 | 30 | 31 | 32 | 阅读([[${detail?.readCount}]]) 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 上一篇: 42 | 43 | 44 | 下一篇: 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/bean/ResultData.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.bean; 2 | 3 | import java.util.Date; 4 | 5 | import com.jingqueyimu.constant.StatusCode; 6 | import com.jingqueyimu.model.BaseModel; 7 | 8 | /** 9 | * 结果数据 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public class ResultData extends BaseModel { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | private int code; 18 | 19 | private String msg; 20 | 21 | private Object data; 22 | 23 | private Date time = new Date(); 24 | 25 | public int getCode() { 26 | return code; 27 | } 28 | 29 | public void setCode(int code) { 30 | this.code = code; 31 | } 32 | 33 | public String getMsg() { 34 | return msg; 35 | } 36 | 37 | public void setMsg(String msg) { 38 | this.msg = msg; 39 | } 40 | 41 | public Date getTime() { 42 | return time; 43 | } 44 | 45 | public void setTime(Date time) { 46 | this.time = time; 47 | } 48 | 49 | public Object getData() { 50 | return data; 51 | } 52 | 53 | public void setData(Object data) { 54 | this.data = data; 55 | } 56 | 57 | public ResultData() {} 58 | 59 | public ResultData(int code, String msg, Object data) { 60 | this.code = code; 61 | this.msg = msg; 62 | this.data = data; 63 | } 64 | 65 | public static ResultData succ() { 66 | return new ResultData(StatusCode.OK, "成功", null); 67 | } 68 | 69 | public static ResultData succ(Object data) { 70 | return new ResultData(StatusCode.OK, "成功", data); 71 | } 72 | 73 | public static ResultData fail() { 74 | return new ResultData(StatusCode.ERR_SYS, "系统错误", null); 75 | } 76 | 77 | public static ResultData fail(String msg) { 78 | return new ResultData(StatusCode.ERR_SYS, msg, null); 79 | } 80 | 81 | public static ResultData fail(int code, String msg) { 82 | return new ResultData(code, msg, null); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/util/DbInitUtil.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import com.alibaba.fastjson.JSONArray; 6 | import com.alibaba.fastjson.JSONObject; 7 | 8 | /** 9 | * 数据库初始化工具类 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public class DbInitUtil { 14 | 15 | /** 16 | * 校验数据库初始化数据 17 | * 18 | * @param dbInitData 19 | */ 20 | public static void checkDbInitData(JSONObject dbInitData) { 21 | String initKey = dbInitData.getString("initKey"); 22 | if (StringUtils.isBlank(initKey)) { 23 | throw new RuntimeException("initKey不能为空"); 24 | } 25 | JSONArray sqls = JSONObject.parseArray(dbInitData.getString("sqls")); 26 | if (sqls == null || sqls.isEmpty()) { 27 | throw new RuntimeException("sqls不能为空"); 28 | } 29 | } 30 | 31 | /** 32 | * 获取DML语句中的表名(只支持单表) 33 | * 34 | * @param sql 35 | * @return 36 | */ 37 | public static String getTableNameForDML(String sql) { 38 | // SELECT * FROM 表名/(表名) WHERE 39 | // UPDATE 表名/(表名) SET 40 | // DELETE FROM 表名 WHERE 41 | // INSERT [INTO] 表名 [()] VALUES/VALUE 42 | sql = sql.replace("(", " ").replace(")", " ").trim().toLowerCase(); 43 | String tableName = null; 44 | if (sql.startsWith("select") || sql.startsWith("delete")) { 45 | tableName = sql.split("from")[1].trim(); 46 | tableName = tableName.split(" ")[0].trim(); 47 | return tableName; 48 | } 49 | if (sql.startsWith("update")) { 50 | tableName = sql.replace("update", "").trim().split(" ")[0].trim(); 51 | return tableName; 52 | } 53 | if (sql.startsWith("insert")) { 54 | sql = sql.replace("values", "value"); 55 | tableName = sql.replace("insert", "").replace("into", "").trim(); 56 | tableName = tableName.split(" ")[0].trim(); 57 | return tableName; 58 | } 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/util/DbInitTestUtil.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | import com.alibaba.fastjson.JSONArray; 6 | import com.alibaba.fastjson.JSONObject; 7 | 8 | /** 9 | * 数据库初始化工具类 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public class DbInitTestUtil { 14 | 15 | /** 16 | * 校验数据库初始化数据 17 | * 18 | * @param dbInitData 19 | */ 20 | public static void checkDbInitData(JSONObject dbInitData) { 21 | String initKey = dbInitData.getString("initKey"); 22 | if (StringUtils.isBlank(initKey)) { 23 | throw new RuntimeException("initKey不能为空"); 24 | } 25 | JSONArray sqls = JSONObject.parseArray(dbInitData.getString("sqls")); 26 | if (sqls == null || sqls.isEmpty()) { 27 | throw new RuntimeException("sqls不能为空"); 28 | } 29 | } 30 | 31 | /** 32 | * 获取DML语句中的表名(只支持单表) 33 | * 34 | * @param sql 35 | * @return 36 | */ 37 | public static String getTableNameForDML(String sql) { 38 | // SELECT * FROM 表名/(表名) WHERE 39 | // UPDATE 表名/(表名) SET 40 | // DELETE FROM 表名 WHERE 41 | // INSERT [INTO] 表名 [()] VALUES/VALUE 42 | sql = sql.replace("(", " ").replace(")", " ").trim().toLowerCase(); 43 | String tableName = null; 44 | if (sql.startsWith("select") || sql.startsWith("delete")) { 45 | tableName = sql.split("from")[1].trim(); 46 | tableName = tableName.split(" ")[0].trim(); 47 | return tableName; 48 | } 49 | if (sql.startsWith("update")) { 50 | tableName = sql.replace("update", "").trim().split(" ")[0].trim(); 51 | return tableName; 52 | } 53 | if (sql.startsWith("insert")) { 54 | sql = sql.replace("values", "value"); 55 | tableName = sql.replace("insert", "").replace("into", "").trim(); 56 | tableName = tableName.split(" ")[0].trim(); 57 | return tableName; 58 | } 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/register/RegisterHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.register; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.annotation.PostConstruct; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | 10 | import com.alibaba.fastjson.JSONObject; 11 | import com.jingqueyimu.model.User; 12 | import com.jingqueyimu.service.UserService; 13 | import com.jingqueyimu.service.component.CaptchaService; 14 | import com.jingqueyimu.service.component.MailService; 15 | import com.jingqueyimu.service.component.RedisService; 16 | import com.jingqueyimu.service.component.SmsService; 17 | 18 | /** 19 | * 注册处理器抽象类 20 | * 21 | * @author zhuangyilian 22 | */ 23 | public abstract class RegisterHandler { 24 | 25 | private static final Map HANDLERS = new HashMap<>(); 26 | 27 | @Autowired 28 | protected RedisService redisService; 29 | @Autowired 30 | protected UserService userService; 31 | @Autowired 32 | protected MailService mailService; 33 | @Autowired 34 | protected SmsService smsService; 35 | @Autowired 36 | protected CaptchaService captchaService; 37 | 38 | protected abstract int getType(); 39 | 40 | protected abstract void checkParams(JSONObject params); 41 | 42 | @PostConstruct 43 | protected void init() { 44 | HANDLERS.put(getType(), this); 45 | } 46 | 47 | public User handle(JSONObject params) { 48 | // 校验参数 49 | checkParams(params); 50 | String username = params.getString("username"); 51 | String mobile = params.getString("mobile"); 52 | String email = params.getString("email"); 53 | String password = params.getString("password"); 54 | int registerType = params.getInteger("registerType"); 55 | // 创建注册用户 56 | return userService.createRegisterUser(username, password, mobile, email, registerType); 57 | } 58 | 59 | public static RegisterHandler getHandler(int type) { 60 | return HANDLERS.get(type); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/DbInit.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Index; 11 | import javax.persistence.Table; 12 | 13 | /** 14 | * 数据库初始化实体类 15 | * 16 | * @author zhuangyilian 17 | */ 18 | @Entity() 19 | @Table(name="t_db_init", indexes={ 20 | @Index(name="uk_init_key", columnList="init_key", unique=true)}) 21 | public class DbInit extends BaseModel { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | @Id 26 | @GeneratedValue(strategy=GenerationType.IDENTITY) 27 | private Long id; 28 | 29 | /** 30 | * 初始化标识 31 | */ 32 | @Column(name="init_key", length=32) 33 | private String initKey; 34 | 35 | 36 | /** 37 | * 初始化内容 38 | */ 39 | @Column(name="content", columnDefinition="text") 40 | private String content; 41 | 42 | /** 43 | * 创建时间 44 | */ 45 | @Column(name="gmt_create", nullable=false) 46 | private Date gmtCreate; 47 | 48 | /** 49 | * 修改时间 50 | */ 51 | @Column(name="gmt_modify") 52 | private Date gmtModify; 53 | 54 | public Long getId() { 55 | return id; 56 | } 57 | 58 | public void setId(Long id) { 59 | this.id = id; 60 | } 61 | 62 | public String getInitKey() { 63 | return initKey; 64 | } 65 | 66 | public void setInitKey(String initKey) { 67 | this.initKey = initKey; 68 | } 69 | 70 | public String getContent() { 71 | return content; 72 | } 73 | 74 | public void setContent(String content) { 75 | this.content = content; 76 | } 77 | 78 | public Date getGmtCreate() { 79 | return gmtCreate; 80 | } 81 | 82 | public void setGmtCreate(Date gmtCreate) { 83 | this.gmtCreate = gmtCreate; 84 | } 85 | 86 | public Date getGmtModify() { 87 | return gmtModify; 88 | } 89 | 90 | public void setGmtModify(Date gmtModify) { 91 | this.gmtModify = gmtModify; 92 | } 93 | } -------------------------------------------------------------------------------- /src/main/resources/templates/client/feedback-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | [[${f.content}]] 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 暂无回复 15 | 16 | 17 | 回复:[[${f.reply}]] 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 您还没有反馈过哟! 30 | 31 | 32 | 33 | 44 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/vo/PermissionWithAccessVO.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.vo; 2 | 3 | import com.jingqueyimu.model.BaseModel; 4 | 5 | /** 6 | * 权限VO 7 | * 8 | * @author zhuangyilian 9 | */ 10 | public class PermissionWithAccessVO extends BaseModel { 11 | 12 | private static final long serialVersionUID = 1L; 13 | 14 | private Long id; 15 | 16 | /** 17 | * 权限路径 18 | */ 19 | private String path; 20 | 21 | /** 22 | * 权限分组 23 | */ 24 | private String groupCode; 25 | 26 | /** 27 | * 权限名称 28 | */ 29 | private String name; 30 | 31 | /** 32 | * 描述 33 | */ 34 | private String description; 35 | 36 | /** 37 | * 管理员ID 38 | */ 39 | private Long adminId; 40 | 41 | /** 42 | * 访问状态 43 | */ 44 | private Boolean accessFlag; 45 | 46 | public Long getId() { 47 | return id; 48 | } 49 | 50 | public void setId(Long id) { 51 | this.id = id; 52 | } 53 | 54 | public String getPath() { 55 | return path; 56 | } 57 | 58 | public void setPath(String path) { 59 | this.path = path; 60 | } 61 | 62 | public String getGroupCode() { 63 | return groupCode; 64 | } 65 | 66 | public void setGroupCode(String groupCode) { 67 | this.groupCode = groupCode; 68 | } 69 | 70 | public String getName() { 71 | return name; 72 | } 73 | 74 | public void setName(String name) { 75 | this.name = name; 76 | } 77 | 78 | public String getDescription() { 79 | return description; 80 | } 81 | 82 | public void setDescription(String description) { 83 | this.description = description; 84 | } 85 | 86 | public Long getAdminId() { 87 | return adminId; 88 | } 89 | 90 | public void setAdminId(Long adminId) { 91 | this.adminId = adminId; 92 | } 93 | 94 | public Boolean getAccessFlag() { 95 | return accessFlag; 96 | } 97 | 98 | public void setAccessFlag(Boolean accessFlag) { 99 | this.accessFlag = accessFlag; 100 | } 101 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/config/MyConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.PropertySource; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * 自定义配置 9 | * 10 | * @author zhuangyilian 11 | */ 12 | @Component 13 | @ConfigurationProperties(prefix="myconfig") 14 | @PropertySource(value={"classpath:config/myconfig.properties"}, encoding="UTF-8") 15 | public class MyConfig { 16 | 17 | /** 18 | * 运行环境 19 | */ 20 | private String runEnv; 21 | 22 | /** 23 | * 网站地址 24 | */ 25 | private String siteUrl; 26 | 27 | /** 28 | * 网站名称 29 | */ 30 | private String siteName; 31 | 32 | /** 33 | * 文件存放路径 34 | */ 35 | private String fileStoragePath; 36 | 37 | /** 38 | * 超级管理员账户名 39 | */ 40 | private String superAdminName; 41 | 42 | /** 43 | * 超级管理员密码 44 | */ 45 | private String superAdminPwd; 46 | 47 | public String getRunEnv() { 48 | return runEnv; 49 | } 50 | 51 | public void setRunEnv(String runEnv) { 52 | this.runEnv = runEnv; 53 | } 54 | 55 | public String getSiteUrl() { 56 | return siteUrl; 57 | } 58 | 59 | public void setSiteUrl(String siteUrl) { 60 | this.siteUrl = siteUrl; 61 | } 62 | 63 | public String getSiteName() { 64 | return siteName; 65 | } 66 | 67 | public void setSiteName(String siteName) { 68 | this.siteName = siteName; 69 | } 70 | 71 | public String getFileStoragePath() { 72 | return fileStoragePath; 73 | } 74 | 75 | public void setFileStoragePath(String fileStoragePath) { 76 | this.fileStoragePath = fileStoragePath; 77 | } 78 | 79 | public String getSuperAdminName() { 80 | return superAdminName; 81 | } 82 | 83 | public void setSuperAdminName(String superAdminName) { 84 | this.superAdminName = superAdminName; 85 | } 86 | 87 | public String getSuperAdminPwd() { 88 | return superAdminPwd; 89 | } 90 | 91 | public void setSuperAdminPwd(String superAdminPwd) { 92 | this.superAdminPwd = superAdminPwd; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.constant.StatusCode; 11 | import com.jingqueyimu.exception.AppException; 12 | import com.jingqueyimu.model.User; 13 | import com.jingqueyimu.model.bean.ResultData; 14 | import com.jingqueyimu.service.UserService; 15 | 16 | /** 17 | * 用户控制器 18 | * 19 | * @author zhuangyilian 20 | */ 21 | @RestController 22 | @RequestMapping("/user") 23 | public class UserController extends BaseController { 24 | 25 | @Autowired 26 | private UserService userService; 27 | 28 | /** 29 | * 注册 30 | * 31 | * @param params 32 | * @return 33 | */ 34 | @PostMapping(value="/register") 35 | public ResultData register(@RequestBody JSONObject params) { 36 | User user = userService.register(params); 37 | if (user == null) { 38 | throw new AppException(StatusCode.ERR_BIZ, "注册失败"); 39 | } 40 | // 保存当前登录用户 41 | userContext.saveCurrUser(user, false); 42 | return ResultData.succ(); 43 | } 44 | 45 | /** 46 | * 登录 47 | * 48 | * @param params 49 | * @return 50 | */ 51 | @PostMapping(value="/login") 52 | public ResultData login(@RequestBody JSONObject params) { 53 | // 记住账号密码 54 | boolean rememberMe = params.getBooleanValue("rememberMe"); 55 | User user = userService.login(params); 56 | if (user == null) { 57 | throw new AppException(StatusCode.ERR_AUTH, "登录失败"); 58 | } 59 | // 保存当前登录用户 60 | userContext.saveCurrUser(user, rememberMe); 61 | return ResultData.succ(); 62 | } 63 | 64 | /** 65 | * 登出 66 | * 67 | * @return 68 | */ 69 | @RequestMapping("/logout") 70 | public ResultData logout() { 71 | userContext.clearCurrUser(); 72 | return ResultData.succ(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitFanoutConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.FanoutExchange; 6 | import org.springframework.amqp.core.Queue; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 广播模式队列配置 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Configuration 16 | public class RabbitFanoutConfig { 17 | 18 | public static final String FANOUT_QUEUE_1 = "fanout.queue.1"; 19 | public static final String FANOUT_QUEUE_2 = "fanout.queue.2"; 20 | public static final String FANOUT_QUEUE_3 = "fanout.queue.3"; 21 | 22 | /** 23 | * amq.fanout: 默认的广播模式交换机,指定其他名称将创建新的交换机 24 | */ 25 | public static final String FANOUT_EXCHANGE = "amq.fanout"; 26 | 27 | /******************************* 创建队列 *******************************/ 28 | 29 | @Bean 30 | public Queue fanoutQueue1() { 31 | return new Queue(FANOUT_QUEUE_1, true, false, false); 32 | } 33 | 34 | @Bean 35 | public Queue fanoutQueue2() { 36 | return new Queue(FANOUT_QUEUE_2, true, false, false); 37 | } 38 | 39 | @Bean 40 | public Queue fanoutQueue3() { 41 | return new Queue(FANOUT_QUEUE_3, true, false, false); 42 | } 43 | 44 | /******************************* 创建交换机 *******************************/ 45 | 46 | @Bean 47 | public FanoutExchange fanoutExchange() { 48 | return new FanoutExchange(FANOUT_EXCHANGE); 49 | } 50 | 51 | /******************************* 绑定队列到交换机 *******************************/ 52 | 53 | @Bean 54 | public Binding fanoutBinding1(FanoutExchange fanoutExchange, Queue fanoutQueue1) { 55 | return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange); 56 | } 57 | 58 | @Bean 59 | public Binding fanoutBinding2(FanoutExchange fanoutExchange, Queue fanoutQueue2) { 60 | return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange); 61 | } 62 | 63 | @Bean 64 | public Binding fanoutBinding3(FanoutExchange fanoutExchange, Queue fanoutQueue3) { 65 | return BindingBuilder.bind(fanoutQueue3).to(fanoutExchange); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsoleFeedbackController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageInfo; 11 | import com.jingqueyimu.annotation.Perm; 12 | import com.jingqueyimu.controller.BaseController; 13 | import com.jingqueyimu.model.Feedback; 14 | import com.jingqueyimu.model.bean.ResultData; 15 | import com.jingqueyimu.model.vo.FeedbackVO; 16 | import com.jingqueyimu.service.FeedbackService; 17 | import com.jingqueyimu.util.SysUtil; 18 | 19 | /** 20 | * 意见反馈控制器 21 | * 22 | * @author zhuangyilian 23 | */ 24 | @RestController 25 | @RequestMapping("/console/feedback") 26 | public class ConsoleFeedbackController extends BaseController { 27 | 28 | @Autowired 29 | private FeedbackService feedbackService; 30 | 31 | /** 32 | * 分页查询意见反馈 33 | * 34 | * @param params 35 | * @return 36 | */ 37 | @Perm(group="feedback", name="分页查询意见反馈", description="反馈管理-意见反馈列表-分页查询意见反馈") 38 | @PostMapping("/page") 39 | public ResultData page(@RequestBody JSONObject params) { 40 | int pageNum = params.getIntValue("pageNum"); 41 | int pageSize = params.getIntValue("pageSize"); 42 | PageInfo page = feedbackService.pageFeedback(pageNum, pageSize, params); 43 | return ResultData.succ(page); 44 | } 45 | 46 | /** 47 | * 回复意见反馈 48 | * 49 | * @param params 50 | * @return 51 | */ 52 | @Perm(group="feedback", name="回复意见反馈", description="反馈管理-意见反馈列表-回复意见反馈") 53 | @PostMapping("/reply") 54 | public ResultData reply(@RequestBody JSONObject params) { 55 | SysUtil.checkParam(params, "id", "意见反馈ID不能为空"); 56 | SysUtil.checkParam(params, "reply", "回复内容不能为空"); 57 | long id = params.getLongValue("id"); 58 | String reply = params.getString("reply"); 59 | Feedback feedback = feedbackService.reply(id, reply); 60 | return ResultData.succ(feedback); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/resources/templates/client/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 密码登录 11 | 12 | 13 | 14 | 记住我 15 | 16 | 17 | 登录 18 | 19 | 20 | 21 | 22 | 23 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/mq/RabbitTopicConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.mq; 2 | 3 | import org.springframework.amqp.core.Binding; 4 | import org.springframework.amqp.core.BindingBuilder; 5 | import org.springframework.amqp.core.Queue; 6 | import org.springframework.amqp.core.TopicExchange; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 主题模式队列配置 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Configuration 16 | public class RabbitTopicConfig { 17 | 18 | public static final String TOPIC_QUEUE_1 = "topic.queue.1"; 19 | public static final String TOPIC_QUEUE_2 = "topic.queue.2"; 20 | public static final String TOPIC_QUEUE_ALL = "topic.queue.all"; 21 | 22 | /** 23 | * amq.topic: 默认的广播模式交换机,指定其他名称将创建新的交换机 24 | */ 25 | public static final String TOPIC_EXCHANGE = "amq.topic"; 26 | 27 | /******************************* 创建队列 *******************************/ 28 | 29 | @Bean 30 | public Queue topicQueue1() { 31 | return new Queue(TOPIC_QUEUE_1, true, false, false); 32 | } 33 | 34 | @Bean 35 | public Queue topicQueue2() { 36 | return new Queue(TOPIC_QUEUE_2, true, false, false); 37 | } 38 | 39 | @Bean 40 | public Queue topicQueueAll() { 41 | return new Queue(TOPIC_QUEUE_ALL, true, false, false); 42 | } 43 | 44 | /******************************* 创建交换机 *******************************/ 45 | 46 | @Bean 47 | public TopicExchange topicExchange() { 48 | return new TopicExchange(TOPIC_EXCHANGE); 49 | } 50 | 51 | /******************************* 绑定队列到交换机 *******************************/ 52 | 53 | @Bean 54 | public Binding topicBinding1(TopicExchange topicExchange, Queue topicQueue1) { 55 | // 以指定 路由键 绑定队列 到交换机上 56 | return BindingBuilder.bind(topicQueue1).to(topicExchange).with("topic.1"); 57 | } 58 | 59 | @Bean 60 | public Binding topicBinding2(TopicExchange topicExchange, Queue topicQueue2) { 61 | return BindingBuilder.bind(topicQueue2).to(topicExchange).with("topic.2"); 62 | } 63 | 64 | @Bean 65 | public Binding topicBindingAll(TopicExchange topicExchange, Queue topicQueueAll) { 66 | // 发送到topic.下的消息,topicQueueAll都会接收到 67 | return BindingBuilder.bind(topicQueueAll).to(topicExchange).with("topic.#"); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/register/MobileRegisterHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.register; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.jingqueyimu.constant.StatusCode; 7 | import com.jingqueyimu.exception.AppException; 8 | import com.jingqueyimu.model.User; 9 | import com.jingqueyimu.model.dict.RegisterType; 10 | import com.jingqueyimu.util.SysUtil; 11 | 12 | /** 13 | * 手机注册处理器 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Component 18 | public class MobileRegisterHandler extends RegisterHandler { 19 | 20 | @Override 21 | protected int getType() { 22 | return RegisterType.MOBILE.getCode(); 23 | } 24 | 25 | @Override 26 | protected void checkParams(JSONObject params) { 27 | SysUtil.checkParam(params, "username", "请输入用户名"); 28 | SysUtil.checkParam(params, "mobile", "请输入手机号"); 29 | SysUtil.checkParam(params, "smsCode", "请输入短信验证码"); 30 | SysUtil.checkParam(params, "password", "请输入密码"); 31 | SysUtil.checkParam(params, "rePassword", "请输入确认密码"); 32 | 33 | String username = params.getString("username"); 34 | String mobile = params.getString("mobile"); 35 | String smsCode = params.getString("smsCode"); 36 | String password = params.getString("password"); 37 | String rePassword = params.getString("rePassword"); 38 | 39 | if (!SysUtil.checkUsername(username)) { 40 | throw new AppException(StatusCode.ERR_PARAM, "用户名必须为1-16个字符"); 41 | } 42 | if (!SysUtil.checkMobile(mobile)) { 43 | throw new AppException(StatusCode.ERR_PARAM, "手机号格式不正确"); 44 | } 45 | if (!password.equals(rePassword)) { 46 | throw new AppException(StatusCode.ERR_PARAM, "两次输入密码不一致"); 47 | } 48 | if (!SysUtil.checkWeakPassword(password)) { 49 | throw new AppException(StatusCode.ERR_PARAM, "密码长度必须为6-16位"); 50 | } 51 | 52 | User user = userService.getByUsername(username); 53 | if (user != null) { 54 | throw new AppException(StatusCode.ERR_BIZ, "用户名已存在"); 55 | } 56 | user = userService.getByMobile(mobile); 57 | if (user != null) { 58 | throw new AppException(StatusCode.ERR_BIZ, "手机号已存在"); 59 | } 60 | // 校验短信验证码 61 | smsService.checkSmsCode(mobile, smsCode); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/handler/register/EmailRegisterHandler.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.handler.register; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.jingqueyimu.constant.StatusCode; 7 | import com.jingqueyimu.exception.AppException; 8 | import com.jingqueyimu.model.User; 9 | import com.jingqueyimu.model.dict.RegisterType; 10 | import com.jingqueyimu.util.SysUtil; 11 | 12 | /** 13 | * 邮箱注册处理器 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Component 18 | public class EmailRegisterHandler extends RegisterHandler { 19 | 20 | @Override 21 | protected int getType() { 22 | return RegisterType.EMAIL.getCode(); 23 | } 24 | 25 | @Override 26 | protected void checkParams(JSONObject params) { 27 | SysUtil.checkParam(params, "username", "请输入用户名"); 28 | SysUtil.checkParam(params, "email", "请输入邮箱"); 29 | SysUtil.checkParam(params, "emailCode", "请输入邮箱验证码"); 30 | SysUtil.checkParam(params, "password", "请输入密码"); 31 | SysUtil.checkParam(params, "rePassword", "请输入确认密码"); 32 | 33 | String username = params.getString("username"); 34 | String email = params.getString("email"); 35 | String emailCode = params.getString("emailCode"); 36 | String password = params.getString("password"); 37 | String rePassword = params.getString("rePassword"); 38 | 39 | if (!SysUtil.checkUsername(username)) { 40 | throw new AppException(StatusCode.ERR_PARAM, "用户名必须为1-16个字符"); 41 | } 42 | if (email.length() > 32 || !SysUtil.checkEmail(email)) { 43 | throw new AppException(StatusCode.ERR_PARAM, "邮箱格式不正确"); 44 | } 45 | if (!password.equals(rePassword)) { 46 | throw new AppException(StatusCode.ERR_PARAM, "两次输入密码不一致"); 47 | } 48 | if (!SysUtil.checkWeakPassword(password)) { 49 | throw new AppException(StatusCode.ERR_PARAM, "密码长度必须为6-16位"); 50 | } 51 | User user = userService.getByUsername(username); 52 | if (user != null) { 53 | throw new AppException(StatusCode.ERR_BIZ, "用户名已存在"); 54 | } 55 | user = userService.getByEmail(email); 56 | if (user != null) { 57 | throw new AppException(StatusCode.ERR_BIZ, "邮箱已存在"); 58 | } 59 | // 校验邮箱验证码 60 | mailService.checkEmailCode(email, emailCode); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/resources/templates/console/admin-permission.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 权限分组 6 | 权限名称全选 7 | 8 | 9 | 10 | 11 | [[${pg.value}]] 12 | 13 | 14 | 15 | 16 | [[${p.name}]] 17 | 18 | 19 | 20 | 21 | 22 | 23 | 62 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/vo/FeedbackVO.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.vo; 2 | 3 | import java.util.Date; 4 | 5 | import com.jingqueyimu.model.BaseModel; 6 | 7 | /** 8 | * 意见反馈VO 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public class FeedbackVO extends BaseModel { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | private Long id; 17 | 18 | /** 19 | * 用户ID 20 | */ 21 | private Long userId; 22 | 23 | /** 24 | * 用户名 25 | */ 26 | private String username; 27 | 28 | /** 29 | * 内容 30 | */ 31 | private String content; 32 | 33 | /** 34 | * 回复 35 | */ 36 | private String reply; 37 | 38 | /** 39 | * 类型(字典: FeedbackType) 40 | */ 41 | private Integer type; 42 | 43 | /** 44 | * 状态(字典: FeedbackStatus) 45 | */ 46 | private Integer status; 47 | 48 | private Date gmtCreate; 49 | 50 | public Long getId() { 51 | return id; 52 | } 53 | 54 | public void setId(Long id) { 55 | this.id = id; 56 | } 57 | 58 | public Long getUserId() { 59 | return userId; 60 | } 61 | 62 | public void setUserId(Long userId) { 63 | this.userId = userId; 64 | } 65 | 66 | public String getUsername() { 67 | return username; 68 | } 69 | 70 | public void setUsername(String username) { 71 | this.username = username; 72 | } 73 | 74 | public String getContent() { 75 | return content; 76 | } 77 | 78 | public void setContent(String content) { 79 | this.content = content; 80 | } 81 | 82 | public String getReply() { 83 | return reply; 84 | } 85 | 86 | public void setReply(String reply) { 87 | this.reply = reply; 88 | } 89 | 90 | public Integer getType() { 91 | return type; 92 | } 93 | 94 | public void setType(Integer type) { 95 | this.type = type; 96 | } 97 | 98 | public Integer getStatus() { 99 | return status; 100 | } 101 | 102 | public void setStatus(Integer status) { 103 | this.status = status; 104 | } 105 | 106 | public Date getGmtCreate() { 107 | return gmtCreate; 108 | } 109 | 110 | public void setGmtCreate(Date gmtCreate) { 111 | this.gmtCreate = gmtCreate; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/PermissionService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.mapper.PermissionMapper; 11 | import com.jingqueyimu.model.Permission; 12 | import com.jingqueyimu.model.dict.PermissionGroup; 13 | import com.jingqueyimu.model.vo.PermissionWithAccessVO; 14 | 15 | /** 16 | * 权限服务 17 | * 18 | * @author zhuangyilian 19 | */ 20 | @Service 21 | public class PermissionService extends BaseService { 22 | 23 | @Autowired 24 | private PermissionMapper permissionMapper; 25 | 26 | /** 27 | * 根据路径保存或更新权限 28 | * 29 | * @param path 30 | * @param groupCode 31 | * @param name 32 | * @param description 33 | * @return 34 | */ 35 | public Permission saveOrUpdateByPath(String path, String groupCode, String name, String description) { 36 | if (StringUtils.isBlank(groupCode)) { 37 | groupCode = PermissionGroup.OTHER.getCode(); 38 | } 39 | Permission permission = new Permission(); 40 | permission.setPath(path); 41 | Permission resPermission = permissionMapper.selectOne(permission); 42 | if (resPermission == null) { 43 | permission.setGroupCode(groupCode); 44 | permission.setName(name); 45 | permission.setDescription(description); 46 | return save(permission); 47 | } 48 | boolean isUpdate = StringUtils.isNotBlank(groupCode) && !groupCode.equals(resPermission.getGroupCode()) 49 | || StringUtils.isNotBlank(name) && !name.equals(resPermission.getName()) 50 | || StringUtils.isNotBlank(description) && !description.equals(resPermission.getDescription()); 51 | if (!isUpdate) { 52 | return resPermission; 53 | } 54 | resPermission.setGroupCode(groupCode); 55 | resPermission.setName(name); 56 | resPermission.setDescription(description); 57 | return update(resPermission); 58 | } 59 | 60 | /** 61 | * 查询带访问状态的权限 62 | * 63 | * @param params 64 | * @return 65 | */ 66 | public List listWithAccess(JSONObject params) { 67 | return permissionMapper.listWithAccess(params); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/DbInitService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Transactional; 7 | 8 | import com.alibaba.fastjson.JSONArray; 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.mapper.DbInitMapper; 11 | import com.jingqueyimu.mapper.SqlMapper; 12 | import com.jingqueyimu.model.DbInit; 13 | import com.jingqueyimu.util.DbInitUtil; 14 | 15 | /** 16 | * 数据库初始化服务 17 | * 18 | * @author zhuangyilian 19 | */ 20 | @Service 21 | public class DbInitService extends BaseService { 22 | 23 | @Autowired 24 | private DbInitMapper dbInitMapper; 25 | @Autowired 26 | private SqlMapper sqlMapper; 27 | 28 | /** 29 | * 根据初始化标识获取初始化记录 30 | * 31 | * @param initKey 32 | * @return 33 | */ 34 | public DbInit getByInitKey(String initKey) { 35 | DbInit dbInit = new DbInit(); 36 | dbInit.setInitKey(initKey); 37 | return dbInitMapper.selectOne(dbInit); 38 | } 39 | 40 | /** 41 | * 保存初始化记录 42 | * 43 | * @param initKey 44 | * @param content 45 | * @return 46 | */ 47 | public DbInit saveDbInit(String initKey, String content) { 48 | DbInit dbInit = new DbInit(); 49 | dbInit.setInitKey(initKey); 50 | dbInit.setContent(content); 51 | return save(dbInit); 52 | } 53 | 54 | /** 55 | * 执行数据库初始化 56 | * 57 | * @param data 58 | */ 59 | @Transactional(rollbackFor = Exception.class) 60 | public void doDbInit(JSONObject data) { 61 | // 校验数据库初始化数据 62 | DbInitUtil.checkDbInitData(data); 63 | String initKey = data.getString("initKey"); 64 | DbInit dbInit = getByInitKey(initKey); 65 | if (dbInit != null) { 66 | return; 67 | } 68 | // 初始化SQL 69 | JSONArray sqls = JSONObject.parseArray(data.getString("sqls")); 70 | for (Object sqlObj : sqls) { 71 | if (sqlObj == null || StringUtils.isBlank(sqlObj.toString())) { 72 | continue; 73 | } 74 | // 插入数据 75 | sqlMapper.insert(sqlObj.toString()); 76 | } 77 | // 保存初始化记录 78 | saveDbInit(initKey, data.toJSONString()); 79 | log.info("初始化数据成功:{}", initKey); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/component/SmsService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service.component; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.jingqueyimu.config.MyConfig; 7 | import com.jingqueyimu.constant.CacheConstant; 8 | import com.jingqueyimu.constant.RunEnv; 9 | import com.jingqueyimu.constant.StatusCode; 10 | import com.jingqueyimu.constant.SysConstant; 11 | import com.jingqueyimu.exception.AppException; 12 | import com.jingqueyimu.util.BizUtil; 13 | 14 | /** 15 | * 短信验证码服务 16 | * 17 | * @author zhuangyilian 18 | */ 19 | @Service 20 | public class SmsService { 21 | 22 | @Autowired 23 | private RedisService redisService; 24 | @Autowired 25 | private MyConfig config; 26 | 27 | /** 28 | * 发送短信验证码 29 | * 30 | * @param mobile 31 | * @return 32 | */ 33 | public void sendSmsCode(String mobile) { 34 | // 是否已过发送间隔时间 35 | Object smsCodeObj = redisService.get(CacheConstant.LAST_SMS_CODE_TIME + mobile); 36 | if (smsCodeObj != null) { 37 | throw new AppException(StatusCode.OK_REPEAT, "短信验证码已发送"); 38 | } 39 | // 短信验证码 40 | String smsCode = BizUtil.createVerificationCode(); 41 | // 是否开发环境 42 | if (RunEnv.DEV.equals(config.getRunEnv())) { 43 | smsCode = "123456"; 44 | } 45 | String content = BizUtil.buildSmsCodeContent(config.getSiteName(), smsCode); 46 | // TODO 发送短信 47 | 48 | // 缓存短信验证码 49 | redisService.set(CacheConstant.SMS_CODE + mobile, smsCode, SysConstant.SMS_CODE_VALID_PERIOD); 50 | redisService.set(CacheConstant.LAST_SMS_CODE_TIME + mobile, System.currentTimeMillis(), SysConstant.SEND_SMS_CODE_INTERVAL); 51 | } 52 | 53 | /** 54 | * 校验短信验证码 55 | * 56 | * @param mobile 57 | * @param smsCode 58 | */ 59 | public void checkSmsCode(String mobile, String smsCode) { 60 | Object smsCodeObj = redisService.get(CacheConstant.SMS_CODE + mobile); 61 | if (smsCodeObj == null) { 62 | throw new AppException(StatusCode.ERR_BIZ, "短信验证码失效,请重新获取"); 63 | } 64 | if (!smsCodeObj.toString().equals(smsCode)) { 65 | throw new AppException(StatusCode.ERR_BIZ, "短信验证码错误"); 66 | } 67 | redisService.delete(CacheConstant.SMS_CODE + mobile); 68 | redisService.delete(CacheConstant.LAST_SMS_CODE_TIME + mobile); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/Category.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Index; 11 | import javax.persistence.Table; 12 | 13 | /** 14 | * 类目实体类 15 | * 16 | * @author zhuangyilian 17 | */ 18 | @Entity() 19 | @Table(name="t_category", indexes={ 20 | @Index(name="idx_name", columnList="name")}) 21 | public class Category extends BaseModel { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | @Id 26 | @GeneratedValue(strategy=GenerationType.IDENTITY) 27 | private Long id; 28 | 29 | /** 30 | * 类目名 31 | */ 32 | @Column(name="name", length=16, nullable=false) 33 | private String name; 34 | 35 | /** 36 | * 父类目ID 37 | */ 38 | @Column(name="parent_id") 39 | private Long parentId; 40 | 41 | /** 42 | * 备注 43 | */ 44 | @Column(name="remark", length=255) 45 | private String remark; 46 | 47 | /** 48 | * 创建时间 49 | */ 50 | @Column(name="gmt_create", nullable=false) 51 | private Date gmtCreate; 52 | 53 | /** 54 | * 修改时间 55 | */ 56 | @Column(name="gmt_modify") 57 | private Date gmtModify; 58 | 59 | public Long getId() { 60 | return id; 61 | } 62 | 63 | public void setId(Long id) { 64 | this.id = id; 65 | } 66 | 67 | public String getName() { 68 | return name; 69 | } 70 | 71 | public void setName(String name) { 72 | this.name = name; 73 | } 74 | 75 | public Long getParentId() { 76 | return parentId; 77 | } 78 | 79 | public void setParentId(Long parentId) { 80 | this.parentId = parentId; 81 | } 82 | 83 | public String getRemark() { 84 | return remark; 85 | } 86 | 87 | public void setRemark(String remark) { 88 | this.remark = remark; 89 | } 90 | 91 | public Date getGmtCreate() { 92 | return gmtCreate; 93 | } 94 | 95 | public void setGmtCreate(Date gmtCreate) { 96 | this.gmtCreate = gmtCreate; 97 | } 98 | 99 | public Date getGmtModify() { 100 | return gmtModify; 101 | } 102 | 103 | public void setGmtModify(Date gmtModify) { 104 | this.gmtModify = gmtModify; 105 | } 106 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/AdminPermission.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | 12 | /** 13 | * 管理员权限实体类 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Entity() 18 | @Table(name="t_admin_permission") 19 | public class AdminPermission extends BaseModel { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @Id 24 | @GeneratedValue(strategy=GenerationType.IDENTITY) 25 | private Long id; 26 | 27 | /** 28 | * 管理员ID 29 | */ 30 | @Column(name="admin_id") 31 | private Long adminId; 32 | 33 | /** 34 | * 权限ID 35 | */ 36 | @Column(name="permission_id") 37 | private Long permissionId; 38 | 39 | /** 40 | * 权限路径 41 | */ 42 | @Column(name="permission_path", length=1024) 43 | private String permissionPath; 44 | 45 | /** 46 | * 创建时间 47 | */ 48 | @Column(name="gmt_create", nullable=false) 49 | private Date gmtCreate; 50 | 51 | /** 52 | * 修改时间 53 | */ 54 | @Column(name="gmt_modify") 55 | private Date gmtModify; 56 | 57 | public Long getId() { 58 | return id; 59 | } 60 | 61 | public void setId(Long id) { 62 | this.id = id; 63 | } 64 | 65 | public Long getAdminId() { 66 | return adminId; 67 | } 68 | 69 | public void setAdminId(Long adminId) { 70 | this.adminId = adminId; 71 | } 72 | 73 | public Long getPermissionId() { 74 | return permissionId; 75 | } 76 | 77 | public void setPermissionId(Long permissionId) { 78 | this.permissionId = permissionId; 79 | } 80 | 81 | public String getPermissionPath() { 82 | return permissionPath; 83 | } 84 | 85 | public void setPermissionPath(String permissionPath) { 86 | this.permissionPath = permissionPath; 87 | } 88 | 89 | public Date getGmtCreate() { 90 | return gmtCreate; 91 | } 92 | 93 | public void setGmtCreate(Date gmtCreate) { 94 | this.gmtCreate = gmtCreate; 95 | } 96 | 97 | public Date getGmtModify() { 98 | return gmtModify; 99 | } 100 | 101 | public void setGmtModify(Date gmtModify) { 102 | this.gmtModify = gmtModify; 103 | } 104 | } -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/JacobTest.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu; 2 | 3 | import com.jacob.activeX.ActiveXComponent; 4 | import com.jacob.com.Dispatch; 5 | import com.jacob.com.Variant; 6 | 7 | /** 8 | * 文本转语音测试 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public class JacobTest { 13 | 14 | public static void main(String[] args) { 15 | textToSpeech("订单来啦!订单来啦!订单来啦!"); 16 | } 17 | 18 | /** 19 | * 文本转语音并播放 20 | * 21 | * @param text 22 | */ 23 | public static void textToSpeech(String text) { 24 | ActiveXComponent ax = null; 25 | try { 26 | ax = new ActiveXComponent("Sapi.SpVoice"); 27 | 28 | // 运行时输出语音内容 29 | Dispatch spVoice = ax.getObject(); 30 | // 音量 0-100 31 | ax.setProperty("Volume", new Variant(100)); 32 | // 语音朗读速度 -10 到 +10 33 | ax.setProperty("Rate", new Variant(0)); 34 | // 执行朗读 35 | Dispatch.call(spVoice, "Speak", new Variant(text)); 36 | 37 | // 下面是构建文件流并生成语音文件 38 | // ax = new ActiveXComponent("Sapi.SpFileStream"); 39 | // Dispatch spFileStream = ax.getObject(); 40 | // ax = new ActiveXComponent("Sapi.SpAudioFormat"); 41 | // Dispatch spAudioFormat = ax.getObject(); 42 | // 43 | // // 设置音频流格式 44 | // Dispatch.put(spAudioFormat, "Type", new Variant(22)); 45 | // // 设置文件输出流格式 46 | // Dispatch.putRef(spFileStream, "Format", spAudioFormat); 47 | // // 调用输出 文件流打开方法,创建一个.wav文件 48 | // Dispatch.call(spFileStream, "Open", new Variant("./text.wav"), new Variant(3), new Variant(true)); 49 | // // 设置声音对象的音频输出流为输出文件对象 50 | // Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream); 51 | // // 设置音量 0到100 52 | // Dispatch.put(spVoice, "Volume", new Variant(100)); 53 | // // 设置朗读速度 54 | // Dispatch.put(spVoice, "Rate", new Variant(-2)); 55 | // // 开始朗读 56 | // Dispatch.call(spVoice, "Speak", new Variant(text)); 57 | // 58 | // // 关闭输出文件 59 | // Dispatch.call(spFileStream, "Close"); 60 | // Dispatch.putRef(spVoice, "AudioOutputStream", null); 61 | // 62 | // spAudioFormat.safeRelease(); 63 | // spFileStream.safeRelease(); 64 | // spVoice.safeRelease(); 65 | // ax.safeRelease(); 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/bean/CurrAdmin.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model.bean; 2 | 3 | import javax.persistence.Column; 4 | 5 | import com.jingqueyimu.model.BaseModel; 6 | 7 | /** 8 | * 当前登录管理员 9 | * 10 | * @author zhuangyilian 11 | */ 12 | public class CurrAdmin extends BaseModel { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | private Long id; 17 | 18 | /** 19 | * 账户名 20 | */ 21 | private String name; 22 | 23 | /** 24 | * 头像 25 | */ 26 | @Column(name="avatar", length=1024) 27 | private String avatar; 28 | 29 | /** 30 | * 真实姓名 31 | */ 32 | @Column(name="real_name", length=32) 33 | private String realName; 34 | 35 | /** 36 | * 手机号 37 | */ 38 | private String mobile; 39 | 40 | /** 41 | * 邮箱 42 | */ 43 | private String email; 44 | 45 | /** 46 | * 是否锁定 47 | */ 48 | private Boolean lockFlag; 49 | 50 | /** 51 | * 记住我 52 | */ 53 | private Boolean rememberMe; 54 | 55 | public Long getId() { 56 | return id; 57 | } 58 | 59 | public void setId(Long id) { 60 | this.id = id; 61 | } 62 | 63 | public String getName() { 64 | return name; 65 | } 66 | 67 | public void setName(String name) { 68 | this.name = name; 69 | } 70 | 71 | public String getAvatar() { 72 | return avatar; 73 | } 74 | 75 | public void setAvatar(String avatar) { 76 | this.avatar = avatar; 77 | } 78 | 79 | public String getRealName() { 80 | return realName; 81 | } 82 | 83 | public void setRealName(String realName) { 84 | this.realName = realName; 85 | } 86 | 87 | public String getMobile() { 88 | return mobile; 89 | } 90 | 91 | public void setMobile(String mobile) { 92 | this.mobile = mobile; 93 | } 94 | 95 | public String getEmail() { 96 | return email; 97 | } 98 | 99 | public void setEmail(String email) { 100 | this.email = email; 101 | } 102 | 103 | public Boolean getLockFlag() { 104 | return lockFlag; 105 | } 106 | 107 | public void setLockFlag(Boolean lockFlag) { 108 | this.lockFlag = lockFlag; 109 | } 110 | 111 | public Boolean getRememberMe() { 112 | return rememberMe; 113 | } 114 | 115 | public void setRememberMe(Boolean rememberMe) { 116 | this.rememberMe = rememberMe; 117 | } 118 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/util/BizUtil.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.util; 2 | 3 | import java.util.Date; 4 | import java.util.Random; 5 | 6 | import com.jingqueyimu.constant.SysConstant; 7 | 8 | /** 9 | * 业务工具类 10 | * 11 | * @author zhuangyilian 12 | */ 13 | public class BizUtil { 14 | 15 | public static Random random = new Random(); 16 | 17 | /** 18 | * 组装业务编号 19 | * 20 | * @param bizId 21 | * @return 22 | */ 23 | public static String buildBizNo(long bizId) { 24 | String bizIdStr = String.format("%06d", bizId); 25 | String randomStr = String.format("%03d", (int) (Math.random() * 1000)); 26 | // 22位 27 | return System.currentTimeMillis() + bizIdStr + randomStr; 28 | } 29 | 30 | /** 31 | * 组装队列码 32 | * 33 | * @param num 34 | * @return 35 | */ 36 | public static String buildQueueCode(int num) { 37 | Date now = new Date(); 38 | int week = DateUtil.getWeek(now); 39 | String weekCode = SysConstant.LETTER_LIST[week]; 40 | String queueCode = weekCode + String.format("%03d", num); 41 | return queueCode; 42 | } 43 | 44 | /** 45 | * 生成验证码 46 | * 47 | * @return 48 | */ 49 | public static String createVerificationCode() { 50 | int nextInt = random.nextInt(100000); 51 | return String.format("%06d", nextInt); 52 | } 53 | 54 | /** 55 | * 组装邮箱验证码HTML 56 | * 57 | * @param signer 58 | * @param emailCode 59 | * @return 60 | */ 61 | public static String buildEmailCodeHtml(String signer, String emailCode) { 62 | StringBuffer content = new StringBuffer(); 63 | content.append("\r\n"); 64 | content.append("\r\n"); 65 | content.append("【") 66 | .append(signer) 67 | .append("】验证码:") 68 | .append(emailCode) 69 | .append(",有效期10分钟。如非本人操作,那可能是某位小伙伴手抖了吧!\r\n"); 70 | content.append("\r\n"); 71 | content.append("\r\n"); 72 | return content.toString(); 73 | } 74 | 75 | /** 76 | * 组装短信验证码内容 77 | * 78 | * @param signer 79 | * @param smsCode 80 | * @return 81 | */ 82 | public static String buildSmsCodeContent(String signer, String smsCode) { 83 | StringBuffer content = new StringBuffer(); 84 | content.append("【").append(signer).append("】验证码:").append(smsCode) 85 | .append(",有效期10分钟。如非本人操作,那可能是某位小伙伴手抖了吧!"); 86 | return content.toString(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/test/java/com/jingqueyimu/config/TestYmlConfig.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.PropertySource; 5 | import org.springframework.stereotype.Component; 6 | 7 | import com.jingqueyimu.factory.YamlPropertySourceFactory; 8 | 9 | /** 10 | * 自定义配置 11 | * 将配置文件属性值,映射到组件中 12 | * 13 | * @author zhuangyilian 14 | */ 15 | @Component 16 | @ConfigurationProperties(prefix="test") 17 | @PropertySource(value="classpath:config/test2.yml", encoding="UTF-8", factory=YamlPropertySourceFactory.class) 18 | public class TestYmlConfig { 19 | 20 | private String value; 21 | 22 | private Person person; 23 | 24 | private Dog dog; 25 | 26 | public String getValue() { 27 | return value; 28 | } 29 | 30 | public void setValue(String value) { 31 | this.value = value; 32 | } 33 | 34 | public Person getPerson() { 35 | return person; 36 | } 37 | 38 | public void setPerson(Person person) { 39 | this.person = person; 40 | } 41 | 42 | public Dog getDog() { 43 | return dog; 44 | } 45 | 46 | public void setDog(Dog dog) { 47 | this.dog = dog; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return "TestYmlConfig [value=" + value + ", person=" + person + ", dog=" + dog + "]"; 53 | } 54 | } 55 | 56 | class Person { 57 | 58 | private String name; 59 | 60 | private int age; 61 | 62 | public String getName() { 63 | return name; 64 | } 65 | 66 | public void setName(String name) { 67 | this.name = name; 68 | } 69 | 70 | public int getAge() { 71 | return age; 72 | } 73 | 74 | public void setAge(int age) { 75 | this.age = age; 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return "Person [name=" + name + ", age=" + age + "]"; 81 | } 82 | } 83 | 84 | class Dog { 85 | 86 | private String name; 87 | 88 | private int age; 89 | 90 | public String getName() { 91 | return name; 92 | } 93 | 94 | public void setName(String name) { 95 | this.name = name; 96 | } 97 | 98 | public int getAge() { 99 | return age; 100 | } 101 | 102 | public void setAge(int age) { 103 | this.age = age; 104 | } 105 | 106 | @Override 107 | public String toString() { 108 | return "Dog [name=" + name + ", age=" + age + "]"; 109 | } 110 | } -------------------------------------------------------------------------------- /src/main/resources/templates/console/tpl/tpl-module.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 用户列表 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 产品列表 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 订单列表 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 意见反馈列表 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 管理员列表 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 网站配置列表 51 | 52 | 53 | 调度列表 54 | 55 | 56 | 公告列表 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/Permission.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | 12 | /** 13 | * 权限实体类 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Entity() 18 | @Table(name="t_permission") 19 | public class Permission extends BaseModel { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @Id 24 | @GeneratedValue(strategy=GenerationType.IDENTITY) 25 | private Long id; 26 | 27 | /** 28 | * 权限路径 29 | */ 30 | @Column(name="path", length=1024, nullable=false) 31 | private String path; 32 | 33 | /** 34 | * 权限分组 35 | */ 36 | @Column(name="group_code", length=32) 37 | private String groupCode; 38 | 39 | /** 40 | * 权限名称 41 | */ 42 | @Column(name="name", length=32) 43 | private String name; 44 | 45 | /** 46 | * 描述 47 | */ 48 | @Column(name="description", length=128) 49 | private String description; 50 | 51 | /** 52 | * 创建时间 53 | */ 54 | @Column(name="gmt_create", nullable=false) 55 | private Date gmtCreate; 56 | 57 | /** 58 | * 修改时间 59 | */ 60 | @Column(name="gmt_modify") 61 | private Date gmtModify; 62 | 63 | public Long getId() { 64 | return id; 65 | } 66 | 67 | public void setId(Long id) { 68 | this.id = id; 69 | } 70 | 71 | public String getPath() { 72 | return path; 73 | } 74 | 75 | public void setPath(String path) { 76 | this.path = path; 77 | } 78 | 79 | public String getGroupCode() { 80 | return groupCode; 81 | } 82 | 83 | public void setGroupCode(String groupCode) { 84 | this.groupCode = groupCode; 85 | } 86 | 87 | public String getName() { 88 | return name; 89 | } 90 | 91 | public void setName(String name) { 92 | this.name = name; 93 | } 94 | 95 | public String getDescription() { 96 | return description; 97 | } 98 | 99 | public void setDescription(String description) { 100 | this.description = description; 101 | } 102 | 103 | public Date getGmtCreate() { 104 | return gmtCreate; 105 | } 106 | 107 | public void setGmtCreate(Date gmtCreate) { 108 | this.gmtCreate = gmtCreate; 109 | } 110 | 111 | public Date getGmtModify() { 112 | return gmtModify; 113 | } 114 | 115 | public void setGmtModify(Date gmtModify) { 116 | this.gmtModify = gmtModify; 117 | } 118 | } -------------------------------------------------------------------------------- /src/main/resources/templates/client/user-center.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 账号设置 16 | 我的反馈 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/console/ConsoleAdminPermissionController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.console; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.alibaba.fastjson.JSONObject; 12 | import com.jingqueyimu.annotation.Perm; 13 | import com.jingqueyimu.controller.BaseController; 14 | import com.jingqueyimu.model.AdminPermission; 15 | import com.jingqueyimu.model.bean.ResultData; 16 | import com.jingqueyimu.service.AdminPermissionService; 17 | import com.jingqueyimu.util.SysUtil; 18 | 19 | /** 20 | * 管理员权限控制器 21 | * 22 | * @author zhuangyilian 23 | */ 24 | @RestController 25 | @RequestMapping("/console/admin_permission") 26 | public class ConsoleAdminPermissionController extends BaseController { 27 | 28 | @Autowired 29 | private AdminPermissionService adminPermissionService; 30 | 31 | /** 32 | * 查询管理员权限 33 | * 34 | * @param params 35 | * @return 36 | */ 37 | @Perm(group="admin", name="查询管理员权限", description="管理员管理-管理员列表-查询管理员权限") 38 | @PostMapping("/list") 39 | public ResultData list(@RequestBody JSONObject params) { 40 | SysUtil.checkParams(params, "adminId"); 41 | long adminId = params.getLongValue("adminId"); 42 | List list = adminPermissionService.listByAdminId(adminId); 43 | return ResultData.succ(list); 44 | } 45 | 46 | /** 47 | * 查询管理员权限地址 48 | * 49 | * @param params 50 | * @return 51 | */ 52 | @Perm(group="admin", name="查询管理员权限地址", description="管理员管理-管理员列表-查询管理员权限地址") 53 | @PostMapping("/list_path") 54 | public ResultData listPath(@RequestBody JSONObject params) { 55 | SysUtil.checkParams(params, "adminId"); 56 | long adminId = params.getLongValue("adminId"); 57 | List list = adminPermissionService.listPathByAdminId(adminId); 58 | return ResultData.succ(list); 59 | } 60 | 61 | /** 62 | * 更新管理员权限 63 | * 64 | * @param params 65 | * @return 66 | */ 67 | @Perm(group="admin", name="更新管理员权限", description="管理员管理-管理员列表-更新管理员权限") 68 | @PostMapping("/update_admin_permission") 69 | public ResultData updateAdminPermission(@RequestBody JSONObject params) { 70 | SysUtil.checkParams(params, "adminId"); 71 | long adminId = params.getLongValue("adminId"); 72 | List permissions = JSONObject.parseArray(params.getString("permissions"), JSONObject.class); 73 | adminPermissionService.updateAdminPermission(adminId, permissions); 74 | return ResultData.succ(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/component/RedisService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service.component; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import javax.annotation.Resource; 6 | 7 | import org.springframework.data.redis.core.RedisTemplate; 8 | import org.springframework.data.redis.core.ValueOperations; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * Redis缓存服务 13 | * 14 | * @author zhuangyilian 15 | */ 16 | @Service 17 | public class RedisService { 18 | 19 | // 当指定时,不能用@Autowired,不然将注入SpringBoot自动配置的RedisTemplate 20 | @Resource 21 | private RedisTemplate redisTemplate; 22 | 23 | /** 24 | * 设置缓存 25 | * 26 | * @param key 27 | * @param value 28 | */ 29 | public void set(String key, Object value) { 30 | redisTemplate.boundValueOps(key).set(value); 31 | } 32 | 33 | /** 34 | * 设置缓存及过期时间 35 | * 36 | * @param key 37 | * @param value 38 | * @param seconds 39 | */ 40 | public void set(String key, Object value, long seconds) { 41 | ValueOperations ops = redisTemplate.opsForValue(); 42 | // 原子性操作 43 | ops.set(key, value, seconds, TimeUnit.SECONDS); 44 | } 45 | 46 | /** 47 | * 如果key不存在,则设置缓存 48 | * 49 | * @param key 50 | * @param value 51 | */ 52 | public boolean setnx(String key, Object value) { 53 | ValueOperations ops = redisTemplate.opsForValue(); 54 | return ops.setIfAbsent(key, value); 55 | } 56 | 57 | /** 58 | * 如果key不存在,设置缓存及过期时间 59 | * 60 | * @param key 61 | * @param value 62 | * @param seconds 63 | */ 64 | public boolean setnx(String key, Object value, long seconds) { 65 | ValueOperations ops = redisTemplate.opsForValue(); 66 | return ops.setIfAbsent(key, value, seconds, TimeUnit.SECONDS); 67 | } 68 | 69 | /** 70 | * 获取缓存 71 | * 72 | * @param key 73 | * @return 74 | */ 75 | public Object get(String key) { 76 | return redisTemplate.boundValueOps(key).get(); 77 | } 78 | 79 | /** 80 | * 删除缓存 81 | * 82 | * @param key 83 | * @return 84 | */ 85 | public boolean delete(String key) { 86 | return redisTemplate.delete(key); 87 | } 88 | 89 | /** 90 | * 设置缓存过期时间 91 | * 92 | * @param key 93 | * @param seconds 94 | */ 95 | public void expire(String key, long seconds) { 96 | redisTemplate.boundValueOps(key).expire(seconds, TimeUnit.SECONDS); 97 | } 98 | 99 | /** 100 | * 是否存在指定key 101 | * 102 | * @param key 103 | * @return 104 | */ 105 | public boolean hasKey(String key) { 106 | return redisTemplate.hasKey(key); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/service/FeedbackService.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.service; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.github.pagehelper.PageHelper; 11 | import com.github.pagehelper.PageInfo; 12 | import com.jingqueyimu.mapper.FeedbackMapper; 13 | import com.jingqueyimu.model.Feedback; 14 | import com.jingqueyimu.model.dict.FeedbackStatus; 15 | import com.jingqueyimu.model.vo.FeedbackVO; 16 | import com.jingqueyimu.util.SysUtil; 17 | 18 | /** 19 | * 意见反馈服务 20 | * 21 | * @author zhuangyilian 22 | */ 23 | @Service 24 | public class FeedbackService extends BaseService { 25 | 26 | @Autowired 27 | private FeedbackMapper feedbackMapper; 28 | 29 | /** 30 | * 提交反馈 31 | * 32 | * @param params 33 | * @return 34 | */ 35 | public Feedback submit(JSONObject params) { 36 | SysUtil.checkParam(params, "userId", "获取用户ID异常"); 37 | SysUtil.checkParam(params, "type", "请选择反馈类型"); 38 | SysUtil.checkParam(params, "content", "请输入反馈内容"); 39 | long userId = params.getLongValue("userId"); 40 | Integer type = params.getInteger("type"); 41 | String content = params.getString("content"); 42 | 43 | Feedback feedback = new Feedback(); 44 | feedback.setUserId(userId); 45 | feedback.setContent(content); 46 | feedback.setType(type); 47 | feedback.setStatus(FeedbackStatus.WAIT.getCode()); 48 | return save(feedback); 49 | } 50 | 51 | /** 52 | * 分页查询意见反馈 53 | * 54 | * @param pageNum 55 | * @param pageSize 56 | * @param params 57 | * @return 58 | */ 59 | public PageInfo pageFeedback(int pageNum, int pageSize, JSONObject params) { 60 | if (pageNum < 1) { 61 | pageNum = 1; 62 | } 63 | if (pageSize < 1) { 64 | pageSize = 10; 65 | } 66 | PageHelper.startPage(pageNum, pageSize); 67 | List list = feedbackMapper.listFeedback(params); 68 | PageInfo page = new PageInfo(list); 69 | return page; 70 | } 71 | 72 | /** 73 | * 回复意见反馈 74 | * 75 | * @param id 76 | * @param reply 77 | * @return 78 | */ 79 | public Feedback reply(long id, String reply) { 80 | Feedback feedback = getById(id); 81 | if (feedback == null) { 82 | throw new RuntimeException("意见反馈记录不存在"); 83 | } 84 | if (feedback.getStatus() != FeedbackStatus.WAIT.getCode()) { 85 | throw new RuntimeException("意见反馈已处理"); 86 | } 87 | feedback.setReply(reply); 88 | feedback.setStatus(FeedbackStatus.DONE.getCode()); 89 | feedback.setHandleTime(new Date()); 90 | feedback = update(feedback); 91 | // TODO 站内信 92 | return feedback; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/exception/GlobalExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.exception; 2 | 3 | import java.util.Date; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | 8 | import org.apache.commons.lang3.time.DateFormatUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.stereotype.Component; 13 | import org.springframework.web.servlet.HandlerExceptionResolver; 14 | import org.springframework.web.servlet.ModelAndView; 15 | import org.springframework.web.servlet.view.json.MappingJackson2JsonView; 16 | 17 | import com.jingqueyimu.constant.StatusCode; 18 | import com.jingqueyimu.util.SysUtil; 19 | 20 | /** 21 | * 全局异常处理类(实现SpringMVC的HandlerExceptionResolver) 22 | * 只能处理请求过程中抛出的异常,不能处理异常处理本身抛出的异常和视图解析过程中抛出的异常 23 | * 没有进行异常处理时,BasicErrorController会继续处理(BasicErrorController会捕获/error的所有错误,过滤器中的错误会被重定向到/error) 24 | * 25 | * @author zhuangyilian 26 | */ 27 | @Component 28 | public class GlobalExceptionResolver implements HandlerExceptionResolver{ 29 | 30 | private final Logger log = LoggerFactory.getLogger(this.getClass()); 31 | 32 | @Value("${spring.jackson.date-format}") 33 | private String jacksonDateFormat; 34 | 35 | @Override 36 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 37 | log.error("全局异常处理捕获了异常: {}", ex.getMessage(), ex); 38 | // 是否ajax请求 39 | boolean isAjax = SysUtil.isAjaxRequest(request); 40 | // 是否json格式数据 41 | boolean isJson = SysUtil.isJsonData(request); 42 | if (!isAjax && !isJson) { 43 | ModelAndView mv = new ModelAndView(); 44 | // 控台地址 45 | if (request.getServletPath().startsWith("/console/")) { 46 | mv.setViewName("/console/500"); 47 | } else { 48 | mv.setViewName("/client/500"); 49 | } 50 | if (ex instanceof AppException) { 51 | mv.addObject("msg", ex.getMessage()); 52 | } 53 | return mv; 54 | } 55 | if (ex instanceof AppException) { 56 | AppException appEx = (AppException) ex; 57 | return buildJsonModelAndView(appEx.getCode(), appEx.getMessage()); 58 | } 59 | return buildJsonModelAndView(StatusCode.ERR_SYS, ex.getMessage()); 60 | } 61 | 62 | /** 63 | * 组装返回JSON数据的ModelAndView(默认跳转页面) 64 | * 65 | * @param code 66 | * @param msg 67 | * @return 68 | */ 69 | private ModelAndView buildJsonModelAndView(int code, String msg) { 70 | ModelAndView mv = new ModelAndView(); 71 | // 返回JSON数据 72 | MappingJackson2JsonView jsonView = new MappingJackson2JsonView(); 73 | mv.setView(jsonView); 74 | mv.addObject("code", code); 75 | mv.addObject("msg", msg); 76 | mv.addObject("data", null); 77 | mv.addObject("time", DateFormatUtils.format(new Date(), jacksonDateFormat)); 78 | return mv; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/model/Notice.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.GeneratedValue; 8 | import javax.persistence.GenerationType; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | 12 | /** 13 | * 公告实体类 14 | * 15 | * @author zhuangyilian 16 | */ 17 | @Entity() 18 | @Table(name="t_notice") 19 | public class Notice extends BaseModel { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | @Id 24 | @GeneratedValue(strategy=GenerationType.IDENTITY) 25 | private Long id; 26 | 27 | /** 28 | * 标题 29 | */ 30 | @Column(name="title", length=255) 31 | private String title; 32 | 33 | /** 34 | * 内容 35 | */ 36 | @Column(name="content", columnDefinition="longtext") 37 | private String content; 38 | 39 | /** 40 | * 摘要 41 | */ 42 | @Column(name="summary", length=255) 43 | private String summary; 44 | 45 | /** 46 | * 图片 47 | */ 48 | @Column(name="image", columnDefinition="longtext") 49 | private String image; 50 | 51 | /** 52 | * 阅读数 53 | */ 54 | @Column(name="read_count") 55 | private Integer readCount; 56 | 57 | /** 58 | * 创建时间 59 | */ 60 | @Column(name="gmt_create", nullable=false) 61 | private Date gmtCreate; 62 | 63 | /** 64 | * 修改时间 65 | */ 66 | @Column(name="gmt_modify") 67 | private Date gmtModify; 68 | 69 | public Long getId() { 70 | return id; 71 | } 72 | 73 | public void setId(Long id) { 74 | this.id = id; 75 | } 76 | 77 | public String getTitle() { 78 | return title; 79 | } 80 | 81 | public void setTitle(String title) { 82 | this.title = title; 83 | } 84 | 85 | public String getContent() { 86 | return content; 87 | } 88 | 89 | public void setContent(String content) { 90 | this.content = content; 91 | } 92 | 93 | public String getSummary() { 94 | return summary; 95 | } 96 | 97 | public void setSummary(String summary) { 98 | this.summary = summary; 99 | } 100 | 101 | public String getImage() { 102 | return image; 103 | } 104 | 105 | public void setImage(String image) { 106 | this.image = image; 107 | } 108 | 109 | public Integer getReadCount() { 110 | return readCount; 111 | } 112 | 113 | public void setReadCount(Integer readCount) { 114 | this.readCount = readCount; 115 | } 116 | 117 | public Date getGmtCreate() { 118 | return gmtCreate; 119 | } 120 | 121 | public void setGmtCreate(Date gmtCreate) { 122 | this.gmtCreate = gmtCreate; 123 | } 124 | 125 | public Date getGmtModify() { 126 | return gmtModify; 127 | } 128 | 129 | public void setGmtModify(Date gmtModify) { 130 | this.gmtModify = gmtModify; 131 | } 132 | } -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/controller/api/ApiUserController.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.controller.api; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PostMapping; 5 | import org.springframework.web.bind.annotation.RequestBody; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import com.alibaba.fastjson.JSONObject; 10 | import com.jingqueyimu.controller.BaseController; 11 | import com.jingqueyimu.model.User; 12 | import com.jingqueyimu.model.bean.CurrUser; 13 | import com.jingqueyimu.model.bean.ResultData; 14 | import com.jingqueyimu.service.UserService; 15 | 16 | /** 17 | * 用户控制器 18 | * 19 | * @author zhuangyilian 20 | */ 21 | @RestController 22 | @RequestMapping("/api/user") 23 | public class ApiUserController extends BaseController { 24 | 25 | @Autowired 26 | private UserService userService; 27 | 28 | /** 29 | * 获取当前登录用户 30 | * 31 | * @param params 32 | * @return 33 | */ 34 | @PostMapping(value="/get_curr_user") 35 | public ResultData getCurrUser(@RequestBody JSONObject params) { 36 | CurrUser currUser = userContext.getCurrUser(); 37 | return ResultData.succ(currUser); 38 | } 39 | 40 | /** 41 | * 更新用户信息 42 | * 43 | * @param params 44 | * @return 45 | */ 46 | @PostMapping(value="/update_user_info") 47 | public ResultData updateUserInfo(@RequestBody JSONObject params) { 48 | CurrUser currUser = userContext.getCurrUser(); 49 | User user = userService.updateUserInfo(currUser.getId(), params); 50 | currUser = userContext.updateCurrUser(user); 51 | return ResultData.succ(currUser); 52 | } 53 | 54 | /** 55 | * 更新用户密码 56 | * 57 | * @param params 58 | * @return 59 | */ 60 | @PostMapping(value="/update_user_password") 61 | public ResultData updateUserPassword(@RequestBody JSONObject params) { 62 | CurrUser currUser = userContext.getCurrUser(); 63 | userService.updateUserPassword(currUser.getId(), params); 64 | return ResultData.succ(); 65 | } 66 | 67 | /** 68 | * 更新用户邮箱 69 | * 70 | * @param params 71 | * @return 72 | */ 73 | @PostMapping(value="/update_user_email") 74 | public ResultData updateUserEmail(@RequestBody JSONObject params) { 75 | CurrUser currUser = userContext.getCurrUser(); 76 | User user = userService.updateUserEmail(currUser.getId(), params); 77 | currUser = userContext.updateCurrUser(user); 78 | return ResultData.succ(currUser); 79 | } 80 | 81 | /** 82 | * 更新用户手机号 83 | * 84 | * @param params 85 | * @return 86 | */ 87 | @PostMapping(value="/update_user_mobile") 88 | public ResultData updateUserMobile(@RequestBody JSONObject params) { 89 | CurrUser currUser = userContext.getCurrUser(); 90 | User user = userService.updateUserMobile(currUser.getId(), params); 91 | currUser = userContext.updateCurrUser(user); 92 | return ResultData.succ(currUser); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/jingqueyimu/aspect/LockAspect.java: -------------------------------------------------------------------------------- 1 | package com.jingqueyimu.aspect; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.aspectj.lang.ProceedingJoinPoint; 7 | import org.aspectj.lang.annotation.Around; 8 | import org.aspectj.lang.annotation.Aspect; 9 | import org.aspectj.lang.reflect.MethodSignature; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | import com.alibaba.fastjson.JSONObject; 14 | import com.jingqueyimu.annotation.Lock; 15 | import com.jingqueyimu.constant.StatusCode; 16 | import com.jingqueyimu.exception.AppException; 17 | import com.jingqueyimu.factory.LockFactory; 18 | 19 | /** 20 | * 锁切面 21 | * 22 | * @author zhuangyilian 23 | */ 24 | @Aspect 25 | @Component 26 | public class LockAspect { 27 | 28 | @Autowired 29 | private LockFactory lockFactory; 30 | 31 | /** 32 | * 环绕通知 33 | * 34 | * @param point 35 | * @param lock 36 | * @throws Throwable 37 | */ 38 | @Around("@annotation(lock)") 39 | public Object around(ProceedingJoinPoint point, Lock lock) throws Throwable { 40 | // 锁的key 41 | String lockKey = getLockKey(point, lock); 42 | try { 43 | // 尝试加锁 44 | if (!lockFactory.tryLock(lockKey, lock.waitTime(), lock.releaseTime())) { 45 | throw new AppException(StatusCode.ERR_SYS_LOCK, lock.msg()); 46 | } 47 | // 执行连接点处的操作 48 | return point.proceed(); 49 | } finally { 50 | // 释放锁 51 | lockFactory.releaseLock(lockKey); 52 | } 53 | } 54 | 55 | /** 56 | * 获取锁的key 57 | * 58 | * @param point 59 | * @param lock 60 | * @return 61 | */ 62 | private String getLockKey(ProceedingJoinPoint point, Lock lock) { 63 | MethodSignature signature = (MethodSignature) point.getSignature(); 64 | // 锁的key 65 | StringBuffer lockKey = new StringBuffer(signature.getDeclaringTypeName()).append(".").append(signature.getMethod().getName()); 66 | if (lock.keys().length <= 0) { 67 | return lockKey.toString(); 68 | } 69 | // 方法参数名 70 | String[] parameterNames = signature.getParameterNames(); 71 | // 方法参数值 72 | Object[] args = point.getArgs(); 73 | // 组装参数信息 74 | Map paramMap = new HashMap<>(); 75 | for (int i = 0; i < parameterNames.length; i++) { 76 | try { 77 | JSONObject json = (JSONObject)JSONObject.toJSON(args[i]); 78 | for (String key : json.keySet()) { 79 | paramMap.put(parameterNames[i].concat(".").concat(key), json.getString(key)); 80 | } 81 | } catch (Exception e) { 82 | paramMap.put(parameterNames[i], args[i] == null ? "" : args[i].toString()); 83 | } 84 | } 85 | StringBuffer paramKey = new StringBuffer(); 86 | for (int i = 0; i < lock.keys().length; i++) { 87 | paramKey.append(":").append(paramMap.get(lock.keys()[i])); 88 | } 89 | return lockKey.append(".").append(paramKey).toString(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/resources/static/css/client.css: -------------------------------------------------------------------------------- 1 | body{ 2 | /*基色*/ 3 | --base-color: #939597; 4 | /*主色*/ 5 | --main-color: #F5DF4D; 6 | /*辅色*/ 7 | --sup-color: #007bff; 8 | } 9 | 10 | @media (min-width: 768px) { 11 | } 12 | 13 | html, body { 14 | height: 100%; 15 | } 16 | 17 | body { 18 | display: -ms-flexbox; 19 | -ms-flex-align: center; 20 | align-items: center; 21 | padding-bottom: 2.4rem; 22 | background-color: #f5f5f5; 23 | } 24 | 25 | footer { 26 | padding-top: 3rem; 27 | padding-bottom: 2rem; 28 | } 29 | 30 | footer p { 31 | margin-bottom: .25rem; 32 | } 33 | 34 | .my-text-base { 35 | color: var(--base-color) !important; 36 | } 37 | 38 | .my-text-main { 39 | color: var(--main-color) !important; 40 | } 41 | 42 | .my-text-sup { 43 | color: var(--sup-color) !important; 44 | } 45 | 46 | .my-bg-base { 47 | background-color: var(--base-color) !important; 48 | } 49 | 50 | .my-bg-main { 51 | background-color: var(--main-color) !important; 52 | } 53 | 54 | .my-bg-sup { 55 | background-color: var(--sup-color) !important; 56 | } 57 | 58 | .jumbotron p:last-child { 59 | margin-bottom: 0; 60 | } 61 | 62 | .jumbotron h1 { 63 | font-weight: 300; 64 | } 65 | 66 | .jumbotron .container { 67 | max-width: 40rem; 68 | } 69 | 70 | .my-bd-placeholder-img { 71 | font-size: 1.125rem; 72 | text-anchor: middle; 73 | -webkit-user-select: none; 74 | -moz-user-select: none; 75 | -ms-user-select: none; 76 | user-select: none; 77 | } 78 | 79 | .my-form-signin { 80 | width: 100%; 81 | max-width: 22rem; 82 | padding: 0.9rem; 83 | padding-top: 1.5rem; 84 | margin: auto; 85 | } 86 | 87 | .my-form-signin .checkbox { 88 | font-weight: 400; 89 | } 90 | 91 | .my-form-signin .form-control { 92 | position: relative; 93 | box-sizing: border-box; 94 | height: auto; 95 | padding: 0.6rem; 96 | font-size: 1rem; 97 | } 98 | 99 | .my-form-signin .form-control:focus { 100 | z-index: 2; 101 | } 102 | 103 | .my-navbar-logo { 104 | width: 1.8rem; 105 | height: 1.8rem; 106 | border-radius:1.5rem; 107 | margin-right: 0.6rem; 108 | } 109 | 110 | .my-login-logo { 111 | width: 5rem; 112 | height: 5rem; 113 | border-radius:0.9rem; 114 | } 115 | 116 | .my-user-portrait { 117 | width: 5rem; 118 | height: 5rem; 119 | margin-top: 2rem; 120 | } 121 | 122 | .my-mid-vertical { 123 | float: none; 124 | display: inline-block; 125 | vertical-align: middle; 126 | } 127 | 128 | .my-main-top { 129 | margin-top: 3.5rem; 130 | } 131 | 132 | .my-avatar { 133 | width: 1.6rem; 134 | height: 1.6rem; 135 | } 136 | 137 | .my-btn-setting .card-header .btn { 138 | line-height: 2rem !important; 139 | } 140 | 141 | .my-img-captcha { 142 | width: 5.5rem; 143 | height: 100%; 144 | cursor: pointer; 145 | } 146 | 147 | /***************** 覆盖bootstrap的样式 *****************/ 148 | 149 | /* .nav-pills .nav-link.active, .nav-pills .show>.nav-link { 150 | color: #fff; 151 | background-color: var(--main-color) !important; 152 | } */ 153 | 154 | .dropdown-item.active, .dropdown-item:active { 155 | color: #fff; 156 | text-decoration: none; 157 | background-color: var(--base-color) !important; 158 | } 159 | --------------------------------------------------------------------------------
16 | [[${msg}]] 17 | 返回上一页 18 |
9 | emmm~~~ 10 | 好像发生了什么错误?! 11 | 容我给开发提个Bug~ 12 | 返回上一页 13 | 返回首页 14 |
16 | [[${msg}]] 17 | 返回上一页 18 | 返回首页 19 |
18 | emmm~~~ 19 | 页面好像不见了! 20 | 容我问问开发~ 21 | 返回上一页 22 | 23 |
18 | emmm~~~ 19 | 好像发生了什么错误?! 20 | 容我给开发提个Bug~ 21 | 返回上一页 22 | 23 |
30 | 31 | 32 | 阅读([[${detail?.readCount}]]) 33 | 34 |
【") 66 | .append(signer) 67 | .append("】验证码:") 68 | .append(emailCode) 69 | .append(",有效期10分钟。如非本人操作,那可能是某位小伙伴手抖了吧!