diff --git a/README.md b/README.md index d51f18b..905c149 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,30 @@ -##springboot-SpringSecurity0 +## 致歉 +由于自己懒以及身体对issuse 解决的不及时。请大家以后提issuse 的时候写清楚 模块名 比如“springboot-SpringSecurity4” 和问题,我会抽时间抓紧解决。 + +## springboot-SpringSecurity0 + 包含两部分代码: * 第一是 博客 springboot+mybatis+SpringSecurity 实现用户角色数据库管理 地址:http://blog.csdn.net/u012373815/article/details/54632176 * 第二是 博客 springBoot+springSecurity验证密码MD5加密 地址:http://blog.csdn.net/u012373815/article/details/54927070 -##springboot-SpringSecurity1 +## springboot-SpringSecurity1 * 博客 springBoot+springSecurity 数据库动态管理用户、角色、权限(二) 地址:http://blog.csdn.net/u012373815/article/details/54633046 -##springboot-SpringSecurity2 +## springboot-SpringSecurity2 * 博客 springboot+security restful权限控制官方推荐(五) 地址:http://blog.csdn.net/u012373815/article/details/59749385 -* 博客:spring security 同时只有一个用户在线,session 并发问题 地址: -##springboot-SpringSecurity3 +## springboot-SpringSecurity3 * 博客 springBoot+springSecurity 动态管理Restful风格权限(三) 地址:http://blog.csdn.net/u012373815/article/details/55225079 -##springboot-SpringSecurity4 +## springboot-SpringSecurity4 * 实战,项目中正在用 -##springboot-WebSocket +## springboot-WebSocket 包含三部分代码,三部分代码有交合: @@ -33,7 +36,7 @@ -##springboot-Cache +## springboot-Cache 包含两部分代码: @@ -41,12 +44,45 @@ * 第二部分是 博客 springboot缓存篇(二)-redis 做缓存 地址:http://blog.csdn.net/u012373815/article/details/54572687 -##springboot-Cache2 +## springboot-Cache2 * 是 博客 springboot缓存 之 GuavaCacheManager 地址:http://blog.csdn.net/u012373815/article/details/60468033 -##springboot-shiro + + +## springboot-shiro * 是博客 springboot集成shiro 实现权限控制 地址:http://blog.csdn.net/u012373815/article/details/57532292 +##springboot-shior2 + +是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换 + +springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 + +## springboot-swagger-ui +* 博客 spring boot +Swagger-ui 自动生成API文档 地址: https://blog.csdn.net/u012373815/article/details/82685962 + +## springBoot-Quartz +* 博客 springBoot-Quartz 定时任务 地址: https://abelyang.blog.csdn.net/article/details/86740625 + +## springboot 整合mybatis2 +* springboot 整合mybatis2 更简便的整合方式地址: https://abelyang.blog.csdn.net/article/details/89296273 + +## springboot+Kafka +* kafka 与 sprigboot 的结合,springboot 从Kafka中读取数据的小例子地址: https://abelyang.blog.csdn.net/article/details/89296305 + +## springboot+es +* Elasticsearch 与 sprigboot 的结合,springboot 操作es的小例子地址: https://abelyang.blog.csdn.net/article/details/89296320 + +## Springboot多数据源切换 +* springboot 多个数据源的配置, 一个springboot 项目操作多个数据库的数据:https://abelyang.blog.csdn.net/article/details/89296341 + +##springboot-dubbo + +该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务 +Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 + + + ##未完待续。。。 diff --git a/abel-parent/pom.xml b/abel-parent/pom.xml new file mode 100644 index 0000000..d87f059 --- /dev/null +++ b/abel-parent/pom.xml @@ -0,0 +1,378 @@ + + + 4.0.0 + + cn.abel + abel-parent + pom + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + UTF-8 + UTF-8 + 1.4.0 + 5.1.47 + + + + + + + + + org.apache.commons + commons-lang3 + 3.7 + + + org.apache.commons + commons-collections4 + 4.2 + + + org.apache.commons + commons-pool2 + 2.6.0 + + + + dom4j + dom4j + 1.6.1 + + + + mysql + mysql-connector-java + ${mysql.version} + runtime + + + + com.alibaba + druid + 1.1.10 + + + + org.apache.shiro + shiro-spring + ${shiro.version} + + + org.apache.shiro + shiro-ehcache + ${shiro.version} + + + org.apache.shiro + shiro-quartz + ${shiro.version} + + + org.opensymphony.quartz + quartz + + + + + net.mingsoft + shiro-freemarker-tags + 1.0.0 + + + + org.hibernate + hibernate-core + 5.3.4.Final + + + + com.fasterxml.jackson.core + jackson-core + 2.9.7 + + + com.fasterxml.jackson.core + jackson-databind + 2.9.9.1 + + + + com.alibaba + fastjson + 1.2.58 + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.5 + + + + org.quartz-scheduler + quartz + 2.2.1 + + + + + com.alibaba + dubbo + 2.8.4 + + + log4j + log4j + + + + + org.slf4j + log4j-over-slf4j + 1.7.25 + + + org.apache.zookeeper + zookeeper + 3.4.13 + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + + + + org.jboss.resteasy + resteasy-jaxrs + 3.0.26.Final + + + org.jboss.resteasy + resteasy-client + 3.0.26.Final + + + org.jboss.resteasy + resteasy-jackson-provider + 3.0.26.Final + + + javax.validation + validation-api + 2.0.1.Final + + + org.hibernate.validator + hibernate-validator + 6.0.13.Final + + + com.101tec + zkclient + 0.10 + + + + + com.google.code.gson + gson + 2.8.5 + + + org.apache.httpcomponents + httpcore + 4.4.10 + + + org.apache.httpcomponents + httpcore-nio + 4.4.10 + + + org.apache.httpcomponents + httpclient + 4.5.6 + + + org.apache.httpcomponents + httpasyncclient + 4.1.4 + + + + com.aliyun.oss + aliyun-sdk-oss + 3.3.0 + + + com.aliyun + aliyun-java-sdk-sts + 3.0.0 + + + + com.aliyun + aliyun-java-sdk-core + 4.2.0 + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + com.aliyun.mns + aliyun-sdk-mns + 1.1.8.6 + + + + + + org.mapstruct + mapstruct-jdk8 + 1.1.0.Final + + + + + + + Releases + http://maven.aliyun.com/nexus/content/groups/public/releases + + + Snapshots + http://maven.aliyun.com/nexus/content/groups/public/snapshots + + + + + + local + + local + + + true + + + + dev + + dev + + + + online + + online + + + + test + + test + + + + test-ali + + test-ali + + + + + + ${project.artifactId}-${project.version} + + + src/main/resources/${package.environment} + + *.* + + + + src/main/resources + + local/** + dev/** + test/** + test-ali/** + online/** + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + true + + true + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + UTF-8 + 1.8 + 1.8 + + + org.mapstruct + mapstruct-processor + 1.1.0.Final + + + + + + + + + diff --git a/abel-util/pom.xml b/abel-util/pom.xml new file mode 100644 index 0000000..faea57f --- /dev/null +++ b/abel-util/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + cn.abel + abel-util + 1.0.0-SNAPSHOT + jar + + cn.abel + abel-parent + 1.0.0-SNAPSHOT + + + UTF-8 + + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-collections4 + + + org.springframework + spring-web + 5.1.3.RELEASE + + + org.springframework.boot + spring-boot-starter-web + 2.0.4.RELEASE + + + com.fasterxml.jackson.core + jackson-databind + 2.9.8 + + + com.alibaba + fastjson + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + + junit + junit + 4.12 + test + + + + \ No newline at end of file diff --git a/abel-util/src/main/java/cn/abel/code/InfoCode.java b/abel-util/src/main/java/cn/abel/code/InfoCode.java new file mode 100644 index 0000000..be6d98e --- /dev/null +++ b/abel-util/src/main/java/cn/abel/code/InfoCode.java @@ -0,0 +1,64 @@ +package cn.abel.code; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 返回响应 Created by liyunfeng + */ +public enum InfoCode { + + //系统错误从200~10000 + SUCCESS(200, "OK"), + TIME_OUT(300, "超时"), + + //业务相关从10000自增 + // 10000开始 + INVALID_REQUEST(10000, "不支持的请求方式"), + + //用户相关(20000自增) + REQUEST_PARAM_ERROR(20000, "传入参数错误"), + REGISTER_TYPE_ERROR(20001, "不支持的注册类型"), + INVALID_SIGN(20002, "签名无效"), + USER_LOGIN_EXIST(20003, "用户已存在"), + USER_LOGIN_NOT_EXIST(20008, "用户不存在"), + PASSWORD_ERROR(20009, "用户名或密码错误"), + INVALID_TOKEN(20010, "无效token"), + INVALID_LOGIN(20011, "登录失效,重新登录"), + PASSWORD_SAME(20017, "密码重复"), + OLD_PASSWORD_ERROR(20018, "密码错误,不能修改"), + LOGIN_FAIL(20024, "登录失败"), + VISITOR_REGISTER_FAIL(20025, "游客注册失败"), + TOKEN_EXIST(20033, "token重复"), + LOGIN_TYPE_EXIST(20034, "登录方式已存在"), + USER_PROFILE_SEARCH_ERROR(20035, "用户查询失败"), + USER_PROFILE_LOCK(20036, "用户已锁定"), + ACCOUNT_SEARCH_FAIL(20037, "账号查询失败"), + LOGIN_NAME_TYPE_ERROR(20038, "登录名不为空时,登录方式不能为空"), + PASSWORD_SIMPLE_ERROR(20042, "密码错误,长度应为6-18,包含字母、数字和特殊字符"), + PASSWORD_ERROR_MORE_THAN(20043,"用户名密码连续错误已达5次,请15分钟后再试"), + LOGIN_TYPE_ERROR(20044, "不支持的登录类型"), + SERVICE_UNAVAILABLE(50000, "操作失败,请重试"); + + private int status; + + private String msg; + + private InfoCode(int status, String msg) { + this.status = status; + this.msg = msg; + } + + public int getStatus() { + return status; + } + + public String getMsg() { + return msg; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} diff --git a/abel-util/src/main/java/cn/abel/exception/AppRuntimeException.java b/abel-util/src/main/java/cn/abel/exception/AppRuntimeException.java new file mode 100644 index 0000000..aa0173e --- /dev/null +++ b/abel-util/src/main/java/cn/abel/exception/AppRuntimeException.java @@ -0,0 +1,33 @@ +package cn.abel.exception; + + +import cn.abel.code.InfoCode; + +/** + * 接口服务抛出的异常 + * + */ +public class AppRuntimeException extends RuntimeException { + + private static final long serialVersionUID = 2963760410777899525L; + private InfoCode infoCode; + + public AppRuntimeException() { + infoCode = InfoCode.SERVICE_UNAVAILABLE; + + } + + public AppRuntimeException(InfoCode infoCode) { + this.infoCode = infoCode; + } + + public AppRuntimeException(InfoCode infoCode, String message) { + super(message); + this.infoCode = infoCode; + } + + public InfoCode getInfoCode() { + return infoCode; + } + +} diff --git a/abel-util/src/main/java/cn/abel/exception/HttpExeption.java b/abel-util/src/main/java/cn/abel/exception/HttpExeption.java new file mode 100644 index 0000000..3e5cca8 --- /dev/null +++ b/abel-util/src/main/java/cn/abel/exception/HttpExeption.java @@ -0,0 +1,21 @@ +package cn.abel.exception; + +public class HttpExeption extends Exception { + + private static final long serialVersionUID = -4707210535385221192L; + + public HttpExeption() { + } + + public HttpExeption(String msg) { + super(msg); + } + + public HttpExeption(String msg, Throwable e) { + super(msg, e); + } + + public HttpExeption(Throwable e) { + super(e); + } +} \ No newline at end of file diff --git a/abel-util/src/main/java/cn/abel/exception/ServiceException.java b/abel-util/src/main/java/cn/abel/exception/ServiceException.java new file mode 100644 index 0000000..267a197 --- /dev/null +++ b/abel-util/src/main/java/cn/abel/exception/ServiceException.java @@ -0,0 +1,60 @@ +package cn.abel.exception; + +import cn.abel.code.*; + +/** + * 服务异常类 + * + */ +@SuppressWarnings("serial") +public class ServiceException extends Exception { + + //默认的错误码 + private int errorCode = 500; + + private String errorCodes; + + public ServiceException() { + } + + public ServiceException(Throwable e) { + super(e); + } + + public ServiceException(int errorCode) { + this.errorCode = errorCode; + } + + public int getErrorCode() { + return errorCode; + } + + public String getErrorCodes() { + return errorCodes; + } + + public ServiceException(InfoCode infoCode){ + super(infoCode.getMsg()); + this.errorCode = infoCode.getStatus(); + } + + public ServiceException(int errorCode, String msg) { + super(msg); + this.errorCode = errorCode; + } + + public ServiceException(String errorCode, String msg) { + super(msg); + this.errorCodes = errorCode; + } + + public ServiceException(int errorCode, String msg, Throwable e) { + super(msg, e); + this.errorCode = errorCode; + } + + public ServiceException(int errorCode, Throwable e) { + super(e); + this.errorCode = errorCode; + } +} diff --git a/abel-util/src/main/java/cn/abel/response/ResponseEntity.java b/abel-util/src/main/java/cn/abel/response/ResponseEntity.java new file mode 100644 index 0000000..b9a5de5 --- /dev/null +++ b/abel-util/src/main/java/cn/abel/response/ResponseEntity.java @@ -0,0 +1,72 @@ +package cn.abel.response; + + +import cn.abel.code.*; + +import java.util.HashMap; + +/** + * Created by guoshan on 2018/3/21. + *

+ * 服务端返回给前端或客户端使用 + */ +public class ResponseEntity { + int status = 200; + + String message = "ok"; + + Object data = new HashMap(); + + + private ResponseEntity() { + } + + public static ResponseEntity ok(Object data) { + ResponseEntity ResponseEntity = new ResponseEntity(); + ResponseEntity.setData(data); + return ResponseEntity; + } + + public static ResponseEntity error(InfoCode infoCode) { + ResponseEntity ResponseEntity = new ResponseEntity(); + ResponseEntity.setStatus(infoCode.getStatus()); + ResponseEntity.setMessage(infoCode.getMsg()); + return ResponseEntity; + } + + public static ResponseEntity ok() { + ResponseEntity ResponseEntity = new ResponseEntity(); + return ResponseEntity; + } + + public static ResponseEntity error(int code, String msg) { + ResponseEntity ResponseEntity = new ResponseEntity(); + ResponseEntity.setStatus(code); + ResponseEntity.setMessage(msg); + return ResponseEntity; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data == null ? new HashMap() : data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/abel-util/src/main/java/cn/abel/utils/DateTimeUtils.java b/abel-util/src/main/java/cn/abel/utils/DateTimeUtils.java new file mode 100644 index 0000000..6ceae80 --- /dev/null +++ b/abel-util/src/main/java/cn/abel/utils/DateTimeUtils.java @@ -0,0 +1,283 @@ +package cn.abel.utils; + +import cn.abel.exception.ServiceException; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.apache.commons.lang3.time.DateUtils; + +import java.text.ParseException; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Calendar; +import java.util.Date; + +/** + * 日期util。 + */ +public class DateTimeUtils { + + /** + * 一分钟。 + */ + public static final int ONE_MINUTE = 60 * 1000; + + /** + * 一小时。 + */ + public static final int ONE_HOUR = 60 * ONE_MINUTE; + + /** + * 一天。 + */ + public static final int ONE_DAY = 24 * ONE_HOUR; + + + public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; + private static final int ARG_ERROR_CODE = 400; + private static final String ARG_ERROR = "输入的参数有误"; + + + /** + * 根据给定的格式将时间转为字符串。 + * + * @param dateTime + * @param pattern + * @return + */ + public static String format(Date dateTime, String pattern) { + if (dateTime == null || pattern == null) { + return StringUtils.EMPTY; + } + + return DateFormatUtils.format(dateTime, pattern); + } + + /** + * 将时间转为默认格式的字符串。 + * + * @param dateTime + * @return + */ + public static String format(Date dateTime) { + return format(dateTime, DEFAULT_DATETIME_PATTERN); + } + + /** + * 根据给定的格式获取当前日期的字符串。 + * + * @param pattern + * @return + */ + public static String formatCurrent(String pattern) { + return format(new Date(), pattern); + } + + /** + * 获取当前日期的字符串。 + * + * @return + */ + public static String formatCurrent() { + return format(new Date(), DEFAULT_DATE_PATTERN); + } + + /** + * 去除时间中的时分秒毫秒,只保留日期部分。 + * + * @param dateTime + * @return + */ + public static Date removeTime(Date dateTime) { + if (dateTime == null) { + return null; + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(dateTime); + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + return calendar.getTime(); + } + + /** + * 获取明天的日期。 + * + * @return + */ + public static Date getTomorrowDate() { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + calendar.add(Calendar.DATE, 1); + return calendar.getTime(); + } + + /** + * 获取昨天的日期。 + * + * @return + */ + public static Date getYesterdayDate() { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + calendar.add(Calendar.DATE, -1); + return calendar.getTime(); + } + + /** + * 根据给定的格式将时间字符串转化成{@link Date}对象。 + * + * @param dateTimeStr + * @param pattern + * @return + * @throws ServiceException + */ + public static Date parse(String dateTimeStr, String pattern) throws ServiceException { + if (dateTimeStr == null || pattern == null) { + return null; + } + try { + return DateUtils.parseDate(dateTimeStr, pattern); + } catch (ParseException e) { + throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); + } + } + + /** + * 将时间字符串根据默认格式转换成{@link Date}对象。 + * + * @param dateTimeStr + * @return + * @throws ServiceException + */ + public static Date parse(String dateTimeStr) throws ServiceException { + return parse(dateTimeStr, DEFAULT_DATETIME_PATTERN); + } + + /** + * 获取日期中的月份。 + * + * @param date + * @return + */ + public static int getMonth(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.get(Calendar.MONTH) + 1; + } + + /** + * 获取日期中的年份。 + * + * @param date + * @return + */ + public static int getYear(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.get(Calendar.YEAR); + } + + /** + * 增加日期。 + * + * @param date + * @param days + * @return + * @throws ServiceException + */ + public static Date dateAdd(Date date, int days) throws ServiceException { + if (date == null) { + throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.DATE, days); + return calendar.getTime(); + } + + /** + * 增加月份。 + * + * @param date + * @param months + * @return + * @throws ServiceException + */ + public static Date monthAdd(Date date, int months) throws ServiceException { + if (date == null) { + throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); + } + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.MONTH, months); + return calendar.getTime(); + } + + /** + * 获取两个日期之间的差值。 + * + * @param one + * @param two + * @return + * @throws ServiceException + */ + public static int dateDiff(Date one, Date two) throws ServiceException { + if (one == null || two == null) { + throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); + } + long diff = Math.abs((one.getTime() - two.getTime()) / (1000 * 3600 * 24)); + return new Long(diff).intValue(); + } + + + /** + * 计算几天前的时间 + * + * @param date 当前时间 + * @param day 几天前 + * @return + */ + public static Date getDateBefore(Date date, int day) { + Calendar now = Calendar.getInstance(); + now.setTime(date); + now.set(Calendar.DATE, now.get(Calendar.DATE) - day); + return now.getTime(); + } + + /** + * 获取当前月第一天 + * + * @return Date + * @throws ParseException + */ + public static Date getFirstAndLastOfMonth() { + LocalDate today = LocalDate.now(); + LocalDate firstDay = LocalDate.of(today.getYear(),today.getMonth(),1); + ZoneId zone = ZoneId.systemDefault(); + Instant instant = firstDay.atStartOfDay().atZone(zone).toInstant(); + return Date.from(instant); + } + + /** + * 获取当前周第一天 + * + * @return Date + * @throws ParseException + */ + public static Date getWeekFirstDate(){ + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + Date date = cal.getTime(); + return date; + } + +} diff --git a/springboot-Cache/pom.xml b/springboot-Cache/pom.xml index fb8b681..eda2a37 100644 --- a/springboot-Cache/pom.xml +++ b/springboot-Cache/pom.xml @@ -63,7 +63,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-Cache2/pom.xml b/springboot-Cache2/pom.xml index 67364da..f255f15 100644 --- a/springboot-Cache2/pom.xml +++ b/springboot-Cache2/pom.xml @@ -52,7 +52,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-Quartz/pom.xml b/springboot-Quartz/pom.xml new file mode 100644 index 0000000..4a96830 --- /dev/null +++ b/springboot-Quartz/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.abel.quartz + springboot-Quartz + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.quartz-scheduler + quartz + 2.2.1 + + + + org.springframework.boot + spring-boot-starter-mail + + + + mysql + mysql-connector-java + + + + com.zaxxer + HikariCP + 3.2.0 + + + + org.springframework + spring-jdbc + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + + \ No newline at end of file diff --git a/springboot-Quartz/src/main/java/com/abel/quartz/Application.java b/springboot-Quartz/src/main/java/com/abel/quartz/Application.java new file mode 100644 index 0000000..38d1a0a --- /dev/null +++ b/springboot-Quartz/src/main/java/com/abel/quartz/Application.java @@ -0,0 +1,18 @@ +package com.abel.quartz; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportResource; + +/** + * Created by yangyibo on 2019/2/1. + */ +@SpringBootApplication +@ImportResource("classpath*:META-INF/spring/*.xml") +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + +} diff --git a/springboot-Quartz/src/main/java/com/abel/quartz/config/InvokingJobDetailFactory.java b/springboot-Quartz/src/main/java/com/abel/quartz/config/InvokingJobDetailFactory.java new file mode 100644 index 0000000..c8211b9 --- /dev/null +++ b/springboot-Quartz/src/main/java/com/abel/quartz/config/InvokingJobDetailFactory.java @@ -0,0 +1,57 @@ +package com.abel.quartz.config; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.quartz.QuartzJobBean; +import java.lang.reflect.Method; + + +/** + * Created by yangyibo on 2019/2/1. + */ +public class InvokingJobDetailFactory extends QuartzJobBean { + + /** + * 计划任务所在类 + */ + private String targetObject; + + /** + * 具体需要执行的计划任务 + */ + private String targetMethod; + + private ApplicationContext ctx; + + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + try { + Object obj = ctx.getBean(targetObject); + Method m = null; + try { + m = obj.getClass().getMethod(targetMethod); + //调用被代理对象的方法 + m.invoke(obj); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } catch (Exception e) { + throw new JobExecutionException(e); + } + } + + public void setApplicationContext(ApplicationContext applicationContext) { + this.ctx = applicationContext; + } + + public void setTargetObject(String targetObject) { + this.targetObject = targetObject; + } + + public void setTargetMethod(String targetMethod) { + this.targetMethod = targetMethod; + } +} diff --git a/springboot-Quartz/src/main/java/com/abel/quartz/config/QuartzConfig.java b/springboot-Quartz/src/main/java/com/abel/quartz/config/QuartzConfig.java new file mode 100644 index 0000000..2dbef04 --- /dev/null +++ b/springboot-Quartz/src/main/java/com/abel/quartz/config/QuartzConfig.java @@ -0,0 +1,225 @@ +package com.abel.quartz.config; + +import java.beans.PropertyVetoException; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.zaxxer.hikari.HikariDataSource; +import org.quartz.Job; +import org.quartz.JobDetail; +import org.quartz.Trigger; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.CronTriggerFactoryBean; +import org.springframework.scheduling.quartz.JobDetailFactoryBean; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + +/** + * Created by yangyibo on 2019/1/16. + */ +@Configuration +public class QuartzConfig { + + /** + * 1.通过name+group获取唯一的jobKey;2.通过groupname来获取其下的所有jobkey + */ + final static String GROUP_NAME = "QuartzJobGroups"; + + @Value("${quartz.scheduler.instanceName}") + private String quartzInstanceName; + + @Value("${spring.datasource.driverClassName}") + private String myDSDriver; + + @Value("${spring.datasource.url}") + private String myDSUrl; + + @Value("${spring.datasource.username}") + private String myDSUser; + + @Value("${spring.datasource.password}") + private String myDSPassword; + + @Value("${org.quartz.dataSource.myDS.maxConnections}") + private int myDSMaxConnections; + + /** + * 设置属性 + * + * @return + * @throws IOException + */ + private Properties quartzProperties() throws IOException { + Properties prop = new Properties(); + // 调度标识名 集群中每一个实例都必须使用相同的名称 + prop.put("quartz.scheduler.instanceName", quartzInstanceName); + // ID设置为自动获取 每一个必须不同 + prop.put("org.quartz.scheduler.instanceId", "AUTO"); + // 禁用quartz软件更新 + prop.put("org.quartz.scheduler.skipUpdateCheck", "true"); + prop.put("org.quartz.scheduler.jmx.export", "true"); + + + // 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库 + prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); + // 数据保存方式为数据库持久化 + prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); + // 数据库别名 随便取 + prop.put("org.quartz.jobStore.dataSource", "quartzDataSource"); + //prop.put("org.quartz.jobStore.dataSource", "myDS"); + // 表的前缀,默认QRTZ_ + prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); + // 是否加入集群 + prop.put("org.quartz.jobStore.isClustered", "true"); + + // 调度实例失效的检查时间间隔 + prop.put("org.quartz.jobStore.clusterCheckinInterval", "20000"); + prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); + // 信息保存时间 ms 默认值60秒 + prop.put("org.quartz.jobStore.misfireThreshold", "120000"); + prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); + prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE"); + + // 程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求) + prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); + // 定线程数,至少为1(无默认值)(一般设置为1-100之间的整数合适) + prop.put("org.quartz.threadPool.threadCount", "10"); + // 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5) + prop.put("org.quartz.threadPool.threadPriority", "5"); + prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true"); + + prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin"); + prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin"); + prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true"); + + //#自定义连接池 + //org.quartz.dataSource.myDS.connectionProvider.class=com.poly.pay.schedule.DruidConnectionProvider + + return prop; + } + + /** + * 数据源 + * + * @return + * @throws PropertyVetoException + */ + @Bean + public HikariDataSource createDataSource() throws PropertyVetoException { + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setJdbcUrl(myDSUrl); + dataSource.setDriverClassName(myDSDriver); + dataSource.setUsername(myDSUser); + dataSource.setPassword(myDSPassword); + dataSource.setMaximumPoolSize(myDSMaxConnections); + return dataSource; + } + + + /** + * 创建触发器工厂 + * + * @param jobDetail + * @param cronExpression + * @return + */ + private static CronTriggerFactoryBean cronTriggerFactoryBean(JobDetail jobDetail, String cronExpression) { + CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean(); + factoryBean.setJobDetail(jobDetail); + factoryBean.setCronExpression(cronExpression); + return factoryBean; + } + + +/****************************************************以下配置需要注意******************************************************/ + + + /** + * 调度工厂 + * 此处配置需要调度的触发器 例如 executeJobTrigger + * + * @param executeJobTrigger + * @return + * @throws IOException + * @throws PropertyVetoException + */ + @Bean + public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executeJobTrigger") Trigger executeJobTrigger) throws IOException, PropertyVetoException { + SchedulerFactoryBean factory = new SchedulerFactoryBean(); + // this allows to update triggers in DB when updating settings in config file: + //用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 + factory.setOverwriteExistingJobs(true); + //用于quartz集群,加载quartz数据源 + //factory.setDataSource(dataSource); + //QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动 + //factory.setStartupDelay(10); + //用于quartz集群,加载quartz数据源配置 + factory.setAutoStartup(true); + factory.setQuartzProperties(quartzProperties()); + factory.setApplicationContextSchedulerContextKey("applicationContext"); + factory.setDataSource(createDataSource()); + //注册触发器 + Trigger[] triggers = {executeJobTrigger}; + factory.setTriggers(triggers); + + return factory; + } + + + /** + * 加载触发器 + * + * 新建触发器进行job 的调度 例如 executeJobDetail + * @param jobDetail + * @return + */ + @Bean(name = "executeJobTrigger") + public CronTriggerFactoryBean executeJobTrigger(@Qualifier("executeJobDetail") JobDetail jobDetail) { + //每天凌晨3点执行 + return cronTriggerFactoryBean(jobDetail, "0 1 0 * * ? "); + } + + + /** + * 加载job + * + * 新建job 类用来代理 + * + * + * @return + */ + @Bean + public JobDetailFactoryBean executeJobDetail() { + return createJobDetail(InvokingJobDetailFactory.class, GROUP_NAME, "executeJob"); + } + + + /** + * 执行规则job工厂 + * + * 配置job 类中需要定时执行的 方法 execute + * @param jobClass + * @param groupName + * @param targetObject + * @return + */ + private static JobDetailFactoryBean createJobDetail(Class jobClass, + String groupName, + String targetObject) { + JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); + factoryBean.setJobClass(jobClass); + factoryBean.setDurability(true); + factoryBean.setRequestsRecovery(true); + factoryBean.setGroup(groupName); + Map map = new HashMap<>(); + map.put("targetMethod", "execute"); + map.put("targetObject", targetObject); + factoryBean.setJobDataAsMap(map); + return factoryBean; + } + +} \ No newline at end of file diff --git a/springboot-Quartz/src/main/java/com/abel/quartz/job/ExecuteJob.java b/springboot-Quartz/src/main/java/com/abel/quartz/job/ExecuteJob.java new file mode 100644 index 0000000..205b451 --- /dev/null +++ b/springboot-Quartz/src/main/java/com/abel/quartz/job/ExecuteJob.java @@ -0,0 +1,21 @@ +package com.abel.quartz.job; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + * Created by yangyibo on 2019/2/1. + */ +@Service +public class ExecuteJob { + private static final Logger logger = LoggerFactory.getLogger(ExecuteJob.class); + + /** + * 方法名在quartz定义 + */ + public void execute() { + System.out.println("定时任务执行了。。。。。"); + + } +} diff --git a/springboot-Quartz/src/main/resources/application.properties b/springboot-Quartz/src/main/resources/application.properties new file mode 100644 index 0000000..096d108 --- /dev/null +++ b/springboot-Quartz/src/main/resources/application.properties @@ -0,0 +1,47 @@ +## tomcat\u914D\u7F6E +server.port=8090 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.abel.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-Quartz +application.main=com.abel.quartz.Application + + +## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 +spring.datasource.url=jdbc:mysql://localhost:3306/quartz?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +## \u8FDE\u63A5\u6C60\u914D\u7F6E +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +#\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.datasource.hikari.minimum-idle=10 +#\u8FDE\u63A5\u6C60\u4E2D\u5141\u8BB8\u7684\u6700\u5927\u8FDE\u63A5\u6570\u3002\u7F3A\u7701\u503C\uFF1A10\uFF1B\u63A8\u8350\u7684\u516C\u5F0F\uFF1A((core_count * 2) + effective_spindle_count) +spring.datasource.hikari.maximum-pool-size=30 +#spring.datasource.hikari.auto-commit=true +#\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09\uFF0C\u8D85\u65F6\u5219\u88AB\u91CA\u653E\uFF08retired\uFF09\uFF0C\u7F3A\u7701:10\u5206\u949F\u3002minimumIdle + + springboot-quartz + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-SpringSecurity0/pom.xml b/springboot-SpringSecurity0/pom.xml index 6245cd1..22e6fd8 100644 --- a/springboot-SpringSecurity0/pom.xml +++ b/springboot-SpringSecurity0/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.us - springboot-security + springboot-security0 1.0-SNAPSHOT @@ -49,7 +49,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-SpringSecurity1/pom.xml b/springboot-SpringSecurity1/pom.xml index b1072e5..79b8c52 100644 --- a/springboot-SpringSecurity1/pom.xml +++ b/springboot-SpringSecurity1/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.us - springboot-security + springboot-security1 1.0-SNAPSHOT @@ -49,7 +49,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-dubbo/README.md b/springboot-dubbo/README.md new file mode 100644 index 0000000..16441b5 --- /dev/null +++ b/springboot-dubbo/README.md @@ -0,0 +1,10 @@ +##springboot-dubbo + +该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务 +Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 + +### abel-user-api +该模块是让消费者 引用的 api 模块,主要用来定义接口和数据传输实体 + +### abel-user-provider +该模块是真正的微服务提供者 diff --git a/springboot-dubbo/abel-user-api/pom.xml b/springboot-dubbo/abel-user-api/pom.xml new file mode 100644 index 0000000..650cd03 --- /dev/null +++ b/springboot-dubbo/abel-user-api/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + cn.abel + abel-parent + 1.0.0-SNAPSHOT + + + cn.abel + abel-user-api + 1.0.0-SNAPSHOT + jar + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Permission.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Permission.java new file mode 100644 index 0000000..e5059e7 --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Permission.java @@ -0,0 +1,65 @@ +package cn.abel.user.models; + + +import java.io.Serializable; + +public class Permission implements Serializable { + + private static final long serialVersionUID = 2079120477173696231L; + private Integer id; + private String name; + private String permissionUrl; + private String method; + private String description; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPermissionUrl() { + return permissionUrl; + } + + public void setPermissionUrl(String permissionUrl) { + this.permissionUrl = permissionUrl; + } + + public String getMethod() { + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "Permission{" + + "id=" + id + + ", name=" + name + + ", permissionUrl=" + permissionUrl + + ", method=" + method + + ", description=" + description + + '}'; + } +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Role.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Role.java new file mode 100644 index 0000000..6a55c5b --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Role.java @@ -0,0 +1,55 @@ +package cn.abel.user.models; + + +import java.io.Serializable; + +public class Role implements Serializable { + + private static final long serialVersionUID = -4873217276773065821L; + private Integer id; + private String name; + private Integer roleLevel; + private String description; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getRoleLevel() { + return roleLevel; + } + + public void setRoleLevel(Integer roleLevel) { + this.roleLevel = roleLevel; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "Role{" + + "id=" + id + + ", name=" + name + + ", roleLevel=" + roleLevel + + ", description=" + description + + '}'; + } +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/User.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/User.java new file mode 100644 index 0000000..07f8ab6 --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/User.java @@ -0,0 +1,88 @@ +package cn.abel.user.models; + + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.io.Serializable; +import java.util.List; + +public class User implements Serializable { + + private static final long serialVersionUID = -4523695542426439365L; + private Integer id; + private String cnname; + private String username; + + @JsonIgnore + private String password; + private String email; + private String mobilePhone; + + + private List roles; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getCnname() { + return cnname; + } + + public void setCnname(String cnname) { + this.cnname = cnname; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + + public String getMobilePhone() { + return mobilePhone; + } + + public void setMobilePhone(String mobilePhone) { + this.mobilePhone = mobilePhone; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", cnname=" + cnname + + ", username=" + username + + ", password=" + password + + ", email=" + email + + ", mobilePhone=" + mobilePhone + + '}'; + } +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/PermissionService.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/PermissionService.java new file mode 100644 index 0000000..5b03f89 --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/PermissionService.java @@ -0,0 +1,21 @@ +package cn.abel.user.service; + +import cn.abel.user.models.Permission; + +import java.util.List; +import java.util.Map; + +public interface PermissionService { + + List getByMap(Map map); + + Permission getById(Integer id); + + Permission create(Permission permission); + + + Permission update(Permission permission); + + int delete(Integer id); + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/RoleService.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/RoleService.java new file mode 100644 index 0000000..7c3cc0d --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/RoleService.java @@ -0,0 +1,22 @@ +package cn.abel.user.service; + + +import cn.abel.user.models.Role; + +import java.util.List; +import java.util.Map; + +public interface RoleService { + + + List getByMap(Map map); + + Role getById(Integer id); + + Role create(Role role); + + Role update(Role role); + + int delete(Integer id); + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/UserService.java b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/UserService.java new file mode 100644 index 0000000..c19eed5 --- /dev/null +++ b/springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/UserService.java @@ -0,0 +1,21 @@ +package cn.abel.user.service; + +import cn.abel.user.models.User; + +import java.util.List; +import java.util.Map; + +public interface UserService { + + List getByMap(Map map); + + User getById(Integer id); + + User create(User user); + + User update(User user); + + int delete(Integer id); + + User getByUserName(String userName); +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/doc/user.sql b/springboot-dubbo/abel-user-provider/doc/user.sql new file mode 100644 index 0000000..107c5ca --- /dev/null +++ b/springboot-dubbo/abel-user-provider/doc/user.sql @@ -0,0 +1,83 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 50719 + Source Host : 127.0.0.1:3306 + Source Schema : shiro + + Target Server Type : MySQL + Target Server Version : 50719 + File Encoding : 65001 + + Date: 20/03/2020 10:51:00 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for permission +-- ---------------------------- +DROP TABLE IF EXISTS `permission`; +CREATE TABLE `permission` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) COLLATE utf8_bin NOT NULL, + `permission_url` varchar(100) COLLATE utf8_bin DEFAULT NULL, + `method` varchar(100) COLLATE utf8_bin DEFAULT NULL, + `description` varchar(1000) COLLATE utf8_bin DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- ---------------------------- +-- Table structure for role +-- ---------------------------- +DROP TABLE IF EXISTS `role`; +CREATE TABLE `role` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) COLLATE utf8_bin NOT NULL, + `role_level` int(1) DEFAULT NULL, + `description` varchar(1000) COLLATE utf8_bin DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- ---------------------------- +-- Table structure for role_permission +-- ---------------------------- +DROP TABLE IF EXISTS `role_permission`; +CREATE TABLE `role_permission` ( + `role_id` int(11) NOT NULL, + `permission_id` int(11) NOT NULL, + PRIMARY KEY (`role_id`,`permission_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `cnname` varchar(50) COLLATE utf8_bin DEFAULT NULL, + `username` varchar(50) COLLATE utf8_bin NOT NULL, + `password` varchar(100) COLLATE utf8_bin NOT NULL, + `email` varchar(100) COLLATE utf8_bin DEFAULT NULL, + `mobile_phone` varchar(50) COLLATE utf8_bin DEFAULT NULL, + `status` int(11) DEFAULT '4' COMMENT '用户登录状态,1 : 在线 2 离开 3 忙碌 4 离线', + PRIMARY KEY (`id`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +-- ---------------------------- +-- Table structure for user_role +-- ---------------------------- +DROP TABLE IF EXISTS `user_role`; +CREATE TABLE `user_role` ( + `user_id` int(11) NOT NULL, + `role_id` int(11) NOT NULL, + PRIMARY KEY (`user_id`,`role_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-dubbo/abel-user-provider/pom.xml b/springboot-dubbo/abel-user-provider/pom.xml new file mode 100644 index 0000000..8c87478 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/pom.xml @@ -0,0 +1,177 @@ + + + 4.0.0 + + cn.abel + abel-parent + 1.0.0-SNAPSHOT + + + cn.abel + abel-user-provider + 1.0.0 + jar + + + + + cn.abel + abel-user-api + 1.0.0-SNAPSHOT + + + cn.abel + abel-util + 1.0.0-SNAPSHOT + + + org.apache.commons + commons-pool2 + + + + com.alibaba + fastjson + 1.2.58 + + + + + org.apache.commons + commons-collections4 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + mysql + mysql-connector-java + + + + + com.alibaba + dubbo + + + org.slf4j + log4j-over-slf4j + + + org.apache.zookeeper + zookeeper + + + org.jboss.resteasy + resteasy-jaxrs + + + org.jboss.resteasy + resteasy-client + + + org.jboss.resteasy + resteasy-jackson-provider + + + javax.validation + validation-api + + + org.hibernate.validator + hibernate-validator + + + com.101tec + zkclient + + + org.apache.httpcomponents + httpcore + + + org.apache.httpcomponents + httpcore-nio + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpasyncclient + + + it.uniroma1.dis.wsngroup.gexf4j + gexf4j + 1.0.0 + + + + io.sentry + sentry-logback + 1.7.3 + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.curator + curator-framework + 2.5.0 + + + org.javassist + javassist + 3.15.0-GA + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/UserProviderApplication.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/UserProviderApplication.java new file mode 100644 index 0000000..3a148b4 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/UserProviderApplication.java @@ -0,0 +1,14 @@ +package cn.abel.user; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportResource; + +@SpringBootApplication +@ImportResource("classpath*:META-INF/spring/*.xml") +public class UserProviderApplication { + + public static void main(String[] args) { + SpringApplication.run(UserProviderApplication.class, args); + } +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/constants/Constants.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/constants/Constants.java new file mode 100644 index 0000000..a614bc1 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/constants/Constants.java @@ -0,0 +1,7 @@ +package cn.abel.user.constants; + +/** + * 公用的常量类。 + */ +public interface Constants { +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/PermissionDao.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/PermissionDao.java new file mode 100644 index 0000000..4542b7d --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/PermissionDao.java @@ -0,0 +1,29 @@ +package cn.abel.user.dao; + + +import cn.abel.user.models.Permission; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; + +@Repository +@Mapper +public interface PermissionDao { + + List getByMap(Map map); + + Permission getById(Integer id); + + Integer create(Permission permission); + + int update(Permission permission); + + int delete(Integer id); + + List getList(); + + List getByUserId(Integer userId); + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/RoleDao.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/RoleDao.java new file mode 100644 index 0000000..20f3c92 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/RoleDao.java @@ -0,0 +1,20 @@ +package cn.abel.user.dao; + + + +import cn.abel.user.models.Role; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; +@Repository +@Mapper +public interface RoleDao { + + List getByMap(Map map); + Role getById(Integer id); + Integer create(Role role); + int update(Role role); + int delete(Integer id); +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/UserDao.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/UserDao.java new file mode 100644 index 0000000..9303a55 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/UserDao.java @@ -0,0 +1,20 @@ +package cn.abel.user.dao; + + +import cn.abel.user.models.User; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Map; +@Repository +@Mapper +public interface UserDao { + + List getByMap(Map map); + User getById(Integer id); + Integer create(User user); + int update(User user); + int delete(Integer id); + User getByUserName(String userName); +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/JsonExceptionMapper.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/JsonExceptionMapper.java new file mode 100644 index 0000000..93b8ef0 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/JsonExceptionMapper.java @@ -0,0 +1,31 @@ +package cn.abel.user.exception; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +import cn.abel.code.InfoCode; +import cn.abel.response.ResponseEntity; +import org.codehaus.jackson.JsonProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * json转换错误 + * + * @author ye + * @date 2018/11/02 14:20 + */ +public class JsonExceptionMapper implements ExceptionMapper { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(JsonExceptionMapper.class); + + @Override + public Response toResponse(JsonProcessingException exception) { + ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR); + logger.info("{}", InfoCode.REQUEST_PARAM_ERROR.getMsg()); + return Response.ok(entity, MediaType.APPLICATION_JSON).build(); + } + +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ReaderExceptionMapper.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ReaderExceptionMapper.java new file mode 100644 index 0000000..1b20cc8 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ReaderExceptionMapper.java @@ -0,0 +1,31 @@ +package cn.abel.user.exception; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +import cn.abel.code.InfoCode; +import cn.abel.response.ResponseEntity; +import org.jboss.resteasy.spi.ReaderException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * json转换错误 + * + * @author ye + * @date 2018/11/02 14:20 + */ +public class ReaderExceptionMapper implements ExceptionMapper { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(ReaderExceptionMapper.class); + + @Override + public Response toResponse(ReaderException exception) { + ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR); + logger.info("{}", InfoCode.REQUEST_PARAM_ERROR.getMsg()); + return Response.ok(entity, MediaType.APPLICATION_JSON).build(); + } + +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/RestExceptionMapper.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/RestExceptionMapper.java new file mode 100644 index 0000000..311e3bb --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/RestExceptionMapper.java @@ -0,0 +1,45 @@ +package cn.abel.user.exception; + +import javax.ws.rs.NotAllowedException; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.NotSupportedException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * http调用错误 + * + * @author ye + * @date 2018/11/02 14:20 + */ +public class RestExceptionMapper implements ExceptionMapper { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(WebApplicationException.class); + + @Override + public Response toResponse(WebApplicationException e) { + if (e instanceof NotAllowedException) { + logger.info("method错误。{}", e.getMessage()); + return null; + } + + //415 + if (e instanceof NotSupportedException) { + logger.info("content-type错误。{}", e.getMessage()); + return null; + } + + if (e instanceof NotFoundException) { + logger.info("url错误。{}", e.getMessage()); + return null; + } + + return null; + } + +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ServiceExceptionMapper.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ServiceExceptionMapper.java new file mode 100644 index 0000000..6f76d12 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ServiceExceptionMapper.java @@ -0,0 +1,29 @@ +package cn.abel.user.exception; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; + +import cn.abel.exception.ServiceException; +import cn.abel.response.ResponseEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ServiceExceptionMapper + * + * @author ye + * @date 2018/11/02 14:20 + */ +public class ServiceExceptionMapper implements ExceptionMapper { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(ServiceException.class); + + @Override + public Response toResponse(ServiceException exception) { + ResponseEntity entity = ResponseEntity.error(exception.getErrorCode(), exception.getMessage()); + logger.error("{},{}", exception.getErrorCode(), exception.getMessage()); + return Response.ok(entity, MediaType.APPLICATION_JSON).build(); + } +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ValidationExceptionMapper.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ValidationExceptionMapper.java new file mode 100644 index 0000000..a464d1b --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ValidationExceptionMapper.java @@ -0,0 +1,36 @@ +package cn.abel.user.exception; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.ws.rs.core.Response; + +import cn.abel.code.InfoCode; +import cn.abel.response.ResponseEntity; +import com.alibaba.dubbo.rpc.protocol.rest.RpcExceptionMapper; +import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; + +/** + * 参数校验异常 + * + * @author ye + * @date 2018/11/04 16:53 + */ +public class ValidationExceptionMapper extends RpcExceptionMapper { + + @Override + protected Response handleConstraintViolationException(ConstraintViolationException cve) { + //ViolationReport report = new ViolationReport(); + String msg = ""; + for (ConstraintViolation cv : cve.getConstraintViolations()) { + //report.addConstraintViolation(new RestConstraintViolation(cv.getPropertyPath().toString(), + // cv.getMessage(), cv.getInvalidValue() == null ? "null" : cv.getInvalidValue().toString())); + msg = cv.getPropertyPath().toString() + " " + cv.getMessage(); + } + + ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR.getStatus(), + InfoCode.REQUEST_PARAM_ERROR.getMsg() + "(" + msg + ")"); + + // 采用json输出代替xml输出 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(entity).type(ContentType.APPLICATION_JSON_UTF_8).build(); + } +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestFilter.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestFilter.java new file mode 100644 index 0000000..617b7c9 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestFilter.java @@ -0,0 +1,71 @@ +package cn.abel.user.filter; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.annotation.Priority; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MultivaluedMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 日志-复制并替代com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter + * + * @author ye + * @date 2018/11/02 15:20 + */ +@Priority(900) +@PreMatching +public class RestFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(RestFilter.class); + + @Override + public void filter(ClientRequestContext context) throws IOException { + logHttpHeaders(context.getStringHeaders()); + } + + @Override + public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { + logHttpHeaders(responseContext.getHeaders()); + } + + @Override + public void filter(ContainerRequestContext context) throws IOException { + logHttpHeaders(context.getHeaders()); + } + + @Override + public void filter(ContainerRequestContext requestContext, + ContainerResponseContext responseContext) throws IOException { + logHttpHeaders(responseContext.getStringHeaders()); + } + + protected void logHttpHeaders(MultivaluedMap headers) { + StringBuilder msg = new StringBuilder("The HTTP headers are: \n"); + for (Map.Entry> entry : headers.entrySet()) { + msg.append(entry.getKey()).append(": "); + for (int i = 0; i < entry.getValue().size(); i++) { + msg.append(entry.getValue().get(i)); + if (i < entry.getValue().size() - 1) { + msg.append(", "); + } + } + msg.append("\n"); + } + logger.info(msg.toString()); + } +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestInterceptor.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestInterceptor.java new file mode 100644 index 0000000..75170c2 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestInterceptor.java @@ -0,0 +1,88 @@ +package cn.abel.user.filter; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.ext.ReaderInterceptor; +import javax.ws.rs.ext.ReaderInterceptorContext; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 日志-复制并替代com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter + * + * @author ye + * @date 2018/11/04 16:34 + */ +public class RestInterceptor implements WriterInterceptor, ReaderInterceptor { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(RestInterceptor.class); + + @Override + public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException { + byte[] buffer = IOUtils.toByteArray(context.getInputStream()); + logger.info("The contents of request body is: \n" + new String(buffer, "UTF-8") + "\n"); + context.setInputStream(new ByteArrayInputStream(buffer)); + return context.proceed(); + } + + @Override + public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { + RestInterceptor.OutputStreamWrapper wrapper = + new RestInterceptor.OutputStreamWrapper(context.getOutputStream()); + context.setOutputStream(wrapper); + context.proceed(); + logger.info("The contents of response body is: \n" + new String(wrapper.getBytes(), "UTF-8") + "\n"); + } + + protected static class OutputStreamWrapper extends OutputStream { + + private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + private final OutputStream output; + + private OutputStreamWrapper(OutputStream output) { + this.output = output; + } + + @Override + public void write(int i) throws IOException { + buffer.write(i); + output.write(i); + } + + @Override + public void write(byte[] b) throws IOException { + buffer.write(b); + output.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + buffer.write(b, off, len); + output.write(b, off, len); + } + + @Override + public void flush() throws IOException { + output.flush(); + } + + @Override + public void close() throws IOException { + output.close(); + } + + public byte[] getBytes() { + return buffer.toByteArray(); + } + } + +} diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/PermissionServiceImpl.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/PermissionServiceImpl.java new file mode 100644 index 0000000..69531f9 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/PermissionServiceImpl.java @@ -0,0 +1,44 @@ +package cn.abel.user.service.impl; + +import cn.abel.user.dao.PermissionDao; +import cn.abel.user.models.Permission; +import cn.abel.user.service.PermissionService; +import com.alibaba.dubbo.config.annotation.Service; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Map; + +@Service(protocol = {"dubbo"}, validation = "false") +public class PermissionServiceImpl implements PermissionService { + @Autowired + private PermissionDao permissionDao; + + @Override + public List getByMap(Map map) { + return permissionDao.getByMap(map); + } + + @Override + public Permission getById(Integer id) { + return permissionDao.getById(id); + } + + @Override + public Permission create(Permission permission) { + permissionDao.create(permission); + return permission; + } + + @Override + public Permission update(Permission permission) { + permissionDao.update(permission); + return permission; + } + + @Override + public int delete(Integer id) { + return permissionDao.delete(id); + } + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/RoleServiceImpl.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..d24eec1 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/RoleServiceImpl.java @@ -0,0 +1,40 @@ +package cn.abel.user.service.impl; + + +import cn.abel.user.dao.RoleDao; +import cn.abel.user.models.Role; +import cn.abel.user.service.RoleService; +import com.alibaba.dubbo.config.annotation.Service; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Map; + +@Service(protocol = {"dubbo"}, validation = "false") +public class RoleServiceImpl implements RoleService{ + @Autowired + private RoleDao roleDao; + @Override + public List getByMap(Map map) { + return roleDao.getByMap(map); + } + @Override + public Role getById(Integer id) { + return roleDao.getById(id); + } + @Override + public Role create(Role role) { + roleDao.create(role); + return role; + } + @Override + public Role update(Role role) { + roleDao.update(role); + return role; + } + @Override + public int delete(Integer id) { + return roleDao.delete(id); + } + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/UserServiceImpl.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..3d2ab10 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/UserServiceImpl.java @@ -0,0 +1,49 @@ +package cn.abel.user.service.impl; + +import cn.abel.user.dao.UserDao; +import cn.abel.user.models.User; +import cn.abel.user.service.UserService; +import com.alibaba.dubbo.config.annotation.Service; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; +import java.util.Map; + +@Service(protocol = {"dubbo"}, validation = "false") +public class UserServiceImpl implements UserService { + @Autowired + private UserDao userDao; + + @Override + public List getByMap(Map map) { + return userDao.getByMap(map); + } + + @Override + public User getById(Integer id) { + return userDao.getById(id); + } + + @Override + public User create(User user) { + userDao.create(user); + return user; + } + + @Override + public User update(User user) { + userDao.update(user); + return user; + } + + @Override + public int delete(Integer id) { + return userDao.delete(id); + } + + @Override + public User getByUserName(String userName) { + return userDao.getByUserName(userName); + } + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/utils/CommentUtils.java b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/utils/CommentUtils.java new file mode 100644 index 0000000..6ffa68a --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/utils/CommentUtils.java @@ -0,0 +1,28 @@ +package cn.abel.user.utils; + +import com.alibaba.fastjson.JSON; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yyb + * @time 2020/3/10 + */ +public class CommentUtils { + + /** + * + * @param list + * @param + * @return + */ + public static List copyList(List list) { + if (CollectionUtils.isEmpty(list)) { + return new ArrayList(); + } + return JSON.parseArray(JSON.toJSONString(list), list.get(0).getClass()); + } + +} diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/META-INF/spring/provider.xml b/springboot-dubbo/abel-user-provider/src/main/resources/META-INF/spring/provider.xml new file mode 100644 index 0000000..c65bacf --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/META-INF/spring/provider.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/dev/application.properties b/springboot-dubbo/abel-user-provider/src/main/resources/dev/application.properties new file mode 100644 index 0000000..f2da32a --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/dev/application.properties @@ -0,0 +1,53 @@ +#application +spring.application.name=abel-user-provider +application.main=cn.abel.user.UserProviderApplication +server.port=9658 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +server.tomcat.max-threads=200 +server.session-timeout=60 +log4j.logger.java.sql.Connection=DEBUG + + +#dubbo +dubbo.application.name=abel-user-provider +dubbo.registry.group=abel +dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.version=1.0.0 +dubbo.protocol.port=12885 +dubbo.protocol.rest.port=12886 +dubbo.annotation.package=cn.abel.user +dubbo.log.file=/logs/abel-user-provider/abel-user-provider-dubbo.log + +#db +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +#DataSource +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.maximum-pool-size=30 +spring.datasource.hikari.idle-timeout=120000 +spring.datasource.hikari.max-lifetime=1800000 +spring.datasource.hikari.connection-timeout=30000 +spring.datasource.hikari.validation-timeout=3000 +spring.datasource.hikari.connection-test-query=SELECT 1 + + +#mybatis +logging.level.cn.abel.user.dao=info +mybatis.type-aliases-package=cn.abel.user.model +mybatis.mapper-locations=classpath*:mapper/*Mapper.xml + +#PageHelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + +logging.file=/logs/abel-user-provider/abel-user-provider.log diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/dev/banner.txt b/springboot-dubbo/abel-user-provider/src/main/resources/dev/banner.txt new file mode 100644 index 0000000..07d3606 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/dev/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# dev # +# # +######################################################## \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/dev/logback-spring.xml b/springboot-dubbo/abel-user-provider/src/main/resources/dev/logback-spring.xml new file mode 100644 index 0000000..78f9a29 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/dev/logback-spring.xml @@ -0,0 +1,40 @@ + + + abel_user + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/local/application.properties b/springboot-dubbo/abel-user-provider/src/main/resources/local/application.properties new file mode 100644 index 0000000..9c996b1 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/local/application.properties @@ -0,0 +1,53 @@ +#application +spring.application.name=abel-user-provider +application.main=cn.abel.user.UserProviderApplication +server.port=9658 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +server.tomcat.max-threads=200 +server.session-timeout=60 +log4j.logger.java.sql.Connection=DEBUG + + +#dubbo +dubbo.application.name=abel-user-provider +dubbo.registry.group=abel +dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.version=1.0.0 +dubbo.protocol.port=12885 +dubbo.protocol.rest.port=12886 +dubbo.annotation.package=cn.abel.user +dubbo.log.file=./logs/abel-user-provider/abel-user-provider-dubbo.log + +#db +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +#DataSource +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.maximum-pool-size=30 +spring.datasource.hikari.idle-timeout=120000 +spring.datasource.hikari.max-lifetime=1800000 +spring.datasource.hikari.connection-timeout=30000 +spring.datasource.hikari.validation-timeout=3000 +spring.datasource.hikari.connection-test-query=SELECT 1 + + +#mybatis +logging.level.cn.abel.user.dao=info +mybatis.type-aliases-package=cn.abel.user.model +mybatis.mapper-locations=classpath*:mapper/*Mapper.xml + +#PageHelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + +logging.file=./logs/abel-user-provider/abel-user-provider.log diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/local/banner.txt b/springboot-dubbo/abel-user-provider/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/local/logback-spring.xml b/springboot-dubbo/abel-user-provider/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..29daaef --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/local/logback-spring.xml @@ -0,0 +1,41 @@ + + + abel_user + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/mapper/PermissionDaoMapper.xml b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/PermissionDaoMapper.xml new file mode 100644 index 0000000..1f0c2b5 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/PermissionDaoMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + and id = #{id} + + + and name = #{name} + + + and permission_url = #{permissionUrl} + + + and method = #{method} + + + and description = #{description} + + + + + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO permission( + id, + name, + permission_url, + method, + description + )VALUES( + #{id}, + #{name}, + #{permissionUrl}, + #{method}, + #{description} + ) + + + + UPDATE permission SET + name = #{name}, + permission_url = #{permissionUrl}, + method = #{method}, + description = #{description} + WHERE id = #{id} + + + + DELETE FROM permission WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/mapper/RoleDaoMapper.xml b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/RoleDaoMapper.xml new file mode 100644 index 0000000..34242c2 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/RoleDaoMapper.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + and id = #{id} + + + and name = #{name} + + + and role_level = #{roleLevel} + + + and description = #{description} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO role( + id, + name, + role_level, + description + )VALUES( + #{id}, + #{name}, + #{roleLevel}, + #{description} + ) + + + + UPDATE role SET + name = #{name}, + role_level = #{roleLevel}, + description = #{description} + WHERE id = #{id} + + + + DELETE FROM role WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/resources/mapper/UserDaoMapper.xml b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/UserDaoMapper.xml new file mode 100644 index 0000000..d7cb24c --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/resources/mapper/UserDaoMapper.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + and id = #{id} + + + and cnname = #{cnname} + + + and username = #{username} + + + and password = #{password} + + + and email = #{email} + + + and mobile_phone = #{mobilePhone} + + + and ( + cnname like CONCAT('%', #{keywords},'%') + OR username like CONCAT('%', #{keywords},'%') + OR mobile_phone like CONCAT('%', #{keywords},'%') + OR email like CONCAT('%', #{keywords},'%') + ) + + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO user( + id, + cnname, + username, + password, + email, + mobile_phone + )VALUES( + #{id}, + #{cnname}, + #{username}, + #{password}, + #{email}, + #{mobilePhone} + ) + + + + UPDATE user SET + cnname = #{cnname}, + username = #{username}, + password = #{password}, + email = #{email}, + mobile_phone = #{mobilePhone} + WHERE id = #{id} + + + + DELETE FROM user WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/BaseTest.java b/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/BaseTest.java new file mode 100644 index 0000000..27a7973 --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/BaseTest.java @@ -0,0 +1,33 @@ +package cn.abel.user; + +/** + * @author yyb + * @time 2020/3/9 + */ + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = UserProviderApplication.class) +@TestPropertySource("/application.properties") +public class BaseTest { + + @Configuration + @ComponentScan(basePackages = {"cn.abel.user"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) + static class ComponentScanConfig { + + } + + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/service/impl/PermissionServiceImplTest.java b/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/service/impl/PermissionServiceImplTest.java new file mode 100644 index 0000000..5513a6c --- /dev/null +++ b/springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/service/impl/PermissionServiceImplTest.java @@ -0,0 +1,55 @@ +package cn.abel.user.service.impl; + +import cn.abel.user.BaseTest; +import cn.abel.user.models.Permission; +import cn.abel.user.service.PermissionService; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import static org.junit.Assert.*; + +/** + * @author yyb + * @time 2020/3/20 + */ +public class PermissionServiceImplTest extends BaseTest { + @Autowired + private PermissionService permissionService; + @Test + public void getByMap() throws Exception { + permissionService.getByMap(null); + } + + @Test + public void getById() throws Exception { + Permission permission = permissionService.getById(1); + System.out.println(); + } + + @Test + public void create() throws Exception { + Permission permission = new Permission(); + permission.setDescription("234234"); + permission.setName("新增"); + permission.setMethod("nicai"); + permission.setPermissionUrl("zsdfsf_sf"); + permissionService.create(permission); + } + + @Test + public void update() throws Exception { + Permission permission = new Permission(); + permission.setId(1); + permission.setDescription("234234"); + permission.setName("新增"); + permission.setMethod("nicai"); + permission.setPermissionUrl("zsdfsf_sf"); + permissionService.update(permission); + } + + @Test + public void delete() throws Exception { + permissionService.delete(1); + } + +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/pom.xml b/springboot-dynamicDataSource/pom.xml new file mode 100644 index 0000000..9992b8b --- /dev/null +++ b/springboot-dynamicDataSource/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + cn.abel + springboot-dynamicDataSource + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.5 + + + mysql + mysql-connector-java + 5.1.40 + + + + org.apache.commons + commons-lang3 + 3.4 + + + + \ No newline at end of file diff --git a/springboot-dynamicDataSource/sql/news.sql b/springboot-dynamicDataSource/sql/news.sql new file mode 100644 index 0000000..82fd1e2 --- /dev/null +++ b/springboot-dynamicDataSource/sql/news.sql @@ -0,0 +1,33 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 50719 + Source Host : 127.0.0.1 + Source Database : oldMan + + Target Server Type : MySQL + Target Server Version : 50719 + File Encoding : utf-8 + + Date: 04/02/2019 15:38:58 PM +*/ + +SET NAMES utf8; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for `news` +-- ---------------------------- +DROP TABLE IF EXISTS `news`; +CREATE TABLE `news` ( + `id` int(11) NOT NULL, + `title` varchar(100) DEFAULT NULL, + `content` text, + `image_path` varchar(100) DEFAULT NULL, + `read_sum` int(11) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-dynamicDataSource/sql/user.sql b/springboot-dynamicDataSource/sql/user.sql new file mode 100644 index 0000000..a42941a --- /dev/null +++ b/springboot-dynamicDataSource/sql/user.sql @@ -0,0 +1,35 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 50719 + Source Host : 127.0.0.1 + Source Database : oldMan + + Target Server Type : MySQL + Target Server Version : 50719 + File Encoding : utf-8 + + Date: 04/02/2019 15:27:32 PM +*/ + +SET NAMES utf8; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for `user` +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) DEFAULT NULL, + `address` varchar(200) DEFAULT NULL, + `mobile` varchar(50) DEFAULT NULL, + `email` varchar(100) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `role` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/Application.java b/springboot-dynamicDataSource/src/main/java/cn/abel/Application.java new file mode 100644 index 0000000..4c77f67 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/Application.java @@ -0,0 +1,16 @@ +package cn.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/3/26 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/bean/News.java b/springboot-dynamicDataSource/src/main/java/cn/abel/bean/News.java new file mode 100644 index 0000000..5462104 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/bean/News.java @@ -0,0 +1,50 @@ +package cn.abel.bean; + + +public class News { + private Integer id; + private String title; + private String content; + private String imagePath; + private Integer readSum; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getImagePath() { + return imagePath; + } + + public void setImagePath(String imagePath) { + this.imagePath = imagePath; + } + + public Integer getReadSum() { + return readSum; + } + + public void setReadSum(Integer readSum) { + this.readSum = readSum; + } +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/bean/User.java b/springboot-dynamicDataSource/src/main/java/cn/abel/bean/User.java new file mode 100644 index 0000000..58acdf2 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/bean/User.java @@ -0,0 +1,70 @@ +package cn.abel.bean; + +import java.util.Date; + + +public class User { + private Integer id; + private String name; + private String address; + private String mobile; + private String email; + private Date createTime; + private Integer role; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getRole() { + return role; + } + + public void setRole(Integer role) { + this.role = role; + } +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSource.java b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSource.java new file mode 100644 index 0000000..99e3af5 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSource.java @@ -0,0 +1,15 @@ +package cn.abel.config; + +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * @author yyb + * @time 2019/3/27 + */ +public class DynamicDataSource extends AbstractRoutingDataSource { + @Override + protected Object determineCurrentLookupKey() { + return DynamicDataSourceContextHolder.getDatabaseType(); + } +} + diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceConfig.java b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceConfig.java new file mode 100644 index 0000000..3cbc3cd --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceConfig.java @@ -0,0 +1,83 @@ +package cn.abel.config; + +import cn.abel.enums.DatabaseTypeEnum; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.Map; + +/** + * @author yyb + * @time 2019/3/27 + */ +@Configuration +@MapperScan(basePackages = "cn.abel.dao") +public class DynamicDataSourceConfig { + @Value("${spring.datasource.primary.url}") + private String primaryUrl; + @Value("${spring.datasource.user.url}") + private String userUrl; + @Value("${mybatis.mapper-locations}") + private String resources; + //当两个数据库连接账号密码不一样时 +// @Value("${spring.datasource.user.username}") +// private String userName; +// @Value("${spring.datasource.user.password}") +// private String password; + + @Autowired + private HikariConfig hikariConfig; + + @Primary + @Bean(name = "primaryDataSource") + public DataSource getPrimaryDataSource() { + return hikariConfig.getHikariDataSource(primaryUrl); + } + + @Bean(name = "userDataSource") + public DataSource getUserDataSource() { + return hikariConfig.getHikariDataSource(userUrl); + } + + + //当两个数据库连接账号密码不一样时使用 +// @Bean(name = "userDataSource") +// public DataSource getUserDataSource() { +// return hikariConfig.getHikariDataSource(userUrl, userName, password); +// } + + + @Bean("dynamicDataSource") + public DynamicDataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource, + @Qualifier("userDataSource") DataSource userDataSource) { + Map targetDataSources = new HashMap<>(); + targetDataSources.put(DatabaseTypeEnum.PRIMARY, primaryDataSource); + targetDataSources.put(DatabaseTypeEnum.USER, userDataSource); + + DynamicDataSource dataSource = new DynamicDataSource(); + dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法 + dataSource.setDefaultTargetDataSource(primaryDataSource);// 默认的datasource设置为myTestDbDataSource + return dataSource; + } + + /** + * 根据数据源创建SqlSessionFactory + */ + @Bean + public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dynamicDataSource); + bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(resources)); + return bean.getObject(); + } +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceContextHolder.java b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..701602e --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceContextHolder.java @@ -0,0 +1,23 @@ +package cn.abel.config; + +import cn.abel.enums.DatabaseTypeEnum; + +/** + * @author yyb + * @time 2019/3/27 + */ +public class DynamicDataSourceContextHolder { + private static final ThreadLocal contextHolder = new ThreadLocal<>(); + + public static void setDatabaseType(DatabaseTypeEnum type){ + contextHolder.set(type); + } + + public static DatabaseTypeEnum getDatabaseType(){ + return contextHolder.get(); + } + + public static void resetDatabaseType() { + contextHolder.set(DatabaseTypeEnum.PRIMARY); + } +} diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/config/HikariConfig.java b/springboot-dynamicDataSource/src/main/java/cn/abel/config/HikariConfig.java new file mode 100644 index 0000000..2cd63eb --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/config/HikariConfig.java @@ -0,0 +1,81 @@ +package cn.abel.config; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +/** + * @author yyb + * @time 2019/3/27 + */ +@Service +public class HikariConfig { + @Value("${spring.datasource.username}") + private String userName; + @Value("${spring.datasource.password}") + private String password; + @Value("${spring.datasource.driver-class-name}") + private String driverClassName; + @Value("${spring.datasource.min-idle}") + private Integer minIdle; + @Value("${spring.datasource.max-active}") + private Integer maxActive; + @Value("${spring.datasource.validation-query}") + private String validationQuery; + @Value("${spring.datasource.connection-timeout}") + private Integer connectionTimeout; + @Value("${spring.datasource.max-left-time}") + private Integer maxLeftTime; + @Value("${spring.datasource.validation-time-out}") + private Integer validationTimeout; + @Value("${spring.datasource.idle-time-out}") + private Integer idleTimeout; + @Value("${spring.datasource.connection-init-sql}") + private String connectionInitSql; + + /** + * 配置Hikari数据连接池 + * + * @param url 数据源 + * @return 连接池对象 + */ + public HikariDataSource getHikariDataSource(String url) { + com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig(); + config.setMinimumIdle(minIdle); + config.setMaximumPoolSize(maxActive); + config.setConnectionTestQuery(validationQuery); + config.setJdbcUrl(url); + config.setUsername(userName); + config.setPassword(password); + config.setDriverClassName(driverClassName); + config.setConnectionTimeout(connectionTimeout); + config.setMaxLifetime(maxLeftTime); + config.setValidationTimeout(validationTimeout); + config.setConnectionInitSql(connectionInitSql); + return new HikariDataSource(config); + } + + /** + * 用于两个库账号密码不一样的时候 + * + * @param url + * @param userName + * @param passwod + * @return + */ + public HikariDataSource getHikariDataSource(String url, String userName, String passwod) { + com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig(); + config.setMinimumIdle(minIdle); + config.setMaximumPoolSize(maxActive); + config.setConnectionTestQuery(validationQuery); + config.setJdbcUrl(url); + config.setUsername(userName); + config.setPassword(passwod); + config.setConnectionTimeout(connectionTimeout); + config.setDriverClassName(driverClassName); + config.setMaxLifetime(maxLeftTime); + config.setValidationTimeout(validationTimeout); + config.setConnectionInitSql(connectionInitSql); + return new HikariDataSource(config); + } +} diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/dao/NewsDao.java b/springboot-dynamicDataSource/src/main/java/cn/abel/dao/NewsDao.java new file mode 100644 index 0000000..b32f0f2 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/dao/NewsDao.java @@ -0,0 +1,23 @@ +package cn.abel.dao; + +import java.util.List; +import java.util.Map; + +import cn.abel.bean.News; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Repository +@Mapper +public interface NewsDao { + + List getByMap(Map map); + + News getById(Integer id); + + Integer create(News news); + + int update(News news); + + int delete(Integer id); +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/dao/UserDao.java b/springboot-dynamicDataSource/src/main/java/cn/abel/dao/UserDao.java new file mode 100644 index 0000000..077d1f5 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/dao/UserDao.java @@ -0,0 +1,23 @@ +package cn.abel.dao; + +import java.util.List; +import java.util.Map; + +import cn.abel.bean.User; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Repository +@Mapper +public interface UserDao { + + List getByMap(Map map); + + User getById(Integer id); + + Integer create(User user); + + int update(User user); + + int delete(Integer id); +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/enums/DatabaseTypeEnum.java b/springboot-dynamicDataSource/src/main/java/cn/abel/enums/DatabaseTypeEnum.java new file mode 100644 index 0000000..03d86b1 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/enums/DatabaseTypeEnum.java @@ -0,0 +1,32 @@ +package cn.abel.enums; + +/** + * @author yyb + * @time 2019/3/27 + */ +public enum DatabaseTypeEnum { + PRIMARY("1"), USER("2"); + + private String code; + + DatabaseTypeEnum(String code) { + this.code = code; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public static DatabaseTypeEnum getDatabaseTypeEnum(String code) { + for (DatabaseTypeEnum databaseTypeEnum : DatabaseTypeEnum.values()) { + if (databaseTypeEnum.getCode().equals(code)) { + return databaseTypeEnum; + } + } + return null; + } +} diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/service/NewsService.java b/springboot-dynamicDataSource/src/main/java/cn/abel/service/NewsService.java new file mode 100644 index 0000000..1c6f1ee --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/service/NewsService.java @@ -0,0 +1,47 @@ +package cn.abel.service; + +import java.util.List; +import java.util.Map; + +import cn.abel.config.DynamicDataSource; +import cn.abel.config.DynamicDataSourceContextHolder; +import cn.abel.enums.DatabaseTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.abel.dao.NewsDao; +import cn.abel.bean.News; + +@Service +public class NewsService { + @Autowired + private NewsDao newsDao; + + public List getByMap(Map map) { + DynamicDataSourceContextHolder.resetDatabaseType(); + return newsDao.getByMap(map); + } + + public News getById(Integer id) { + DynamicDataSourceContextHolder.resetDatabaseType(); + return newsDao.getById(id); + } + + public News create(News news) { + DynamicDataSourceContextHolder.resetDatabaseType(); + newsDao.create(news); + return news; + } + + public News update(News news) { + DynamicDataSourceContextHolder.resetDatabaseType(); + newsDao.update(news); + return news; + } + + public int delete(Integer id) { + DynamicDataSourceContextHolder.resetDatabaseType(); + return newsDao.delete(id); + } + +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/java/cn/abel/service/UserService.java b/springboot-dynamicDataSource/src/main/java/cn/abel/service/UserService.java new file mode 100644 index 0000000..4766a40 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/java/cn/abel/service/UserService.java @@ -0,0 +1,46 @@ +package cn.abel.service; + +import java.util.List; +import java.util.Map; + +import cn.abel.config.DynamicDataSourceContextHolder; +import cn.abel.enums.DatabaseTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.abel.dao.UserDao; +import cn.abel.bean.User; + +@Service +public class UserService { + @Autowired + private UserDao userDao; + + public List getByMap(Map map){ + DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); + return userDao.getByMap(map); + } + + public User getById(Integer id){ + DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); + return userDao.getById(id); + } + + public User create(User user){ + DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); + userDao.create(user); + return user; + } + + public User update(User user){ + DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); + userDao.update(user); + return user; + } + + public int delete(Integer id){ + DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); + return userDao.delete(id); + } + +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/resources/local/application.properties b/springboot-dynamicDataSource/src/main/resources/local/application.properties new file mode 100644 index 0000000..28ba7a9 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/resources/local/application.properties @@ -0,0 +1,60 @@ +## tomcat\u914D\u7F6E +server.port=8009 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.abel.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-dynamicDataSource +application.main=cn.abel.Application + +## LOG +logging.file=./logs/springboot-dynamicDataSource.log + + +## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 +spring.datasource.primary.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.user.url=jdbc:mysql://localhost:3306/rules?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false + +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +#\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.datasource.min-idle=5 +#\u6700\u5927\u8FDE\u63A5\u6570\u91CF +spring.datasource.max-active=100 +#\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 +spring.datasource.validation-query=select 1 from dual +#\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.connection-timeout=60000 +#\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.max-left-time=60000 +#\u751F\u6548\u8D85\u65F6 +spring.datasource.validation-time-out=3000 +#\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.idle-time-out=60000 +#\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 +spring.datasource.connection-init-sql= set names utf8mb4 + +logging.level.cn.abel.dao=debug +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E +mybatis.mapper-locations=classpath*:mapper/*Mapper.xml +smybatis.type-aliases-package=cn.abel.bean +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E + +## pagehelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + + diff --git a/springboot-dynamicDataSource/src/main/resources/local/banner.txt b/springboot-dynamicDataSource/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/resources/local/logback-spring.xml b/springboot-dynamicDataSource/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..d600f43 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/resources/local/logback-spring.xml @@ -0,0 +1,41 @@ + + + springboot-dataSource + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/resources/mapper/NewsDaoMapper.xml b/springboot-dynamicDataSource/src/main/resources/mapper/NewsDaoMapper.xml new file mode 100644 index 0000000..b4eeb93 --- /dev/null +++ b/springboot-dynamicDataSource/src/main/resources/mapper/NewsDaoMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + and id = #{id} + + + and title = #{title} + + + and content = #{content} + + + and image_path = #{imagePath} + + + and read_sum = #{readSum} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO news( + id, + title, + content, + image_path, + read_sum + )VALUES( + #{id}, + #{title}, + #{content}, + #{imagePath}, + #{readSum} + ) + + + + UPDATE news SET + title = #{title}, + content = #{content}, + image_path = #{imagePath}, + read_sum = #{readSum} + WHERE id = #{id} + + + + DELETE FROM news WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/main/resources/mapper/UserDaoMapper.xml b/springboot-dynamicDataSource/src/main/resources/mapper/UserDaoMapper.xml new file mode 100644 index 0000000..ec2ce2a --- /dev/null +++ b/springboot-dynamicDataSource/src/main/resources/mapper/UserDaoMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + and id = #{id} + + + and name = #{name} + + + and address = #{address} + + + and mobile = #{mobile} + + + and email = #{email} + + + and role = #{role} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO user( + id, + name, + address, + mobile, + email, + create_time, + role + )VALUES( + #{id}, + #{name}, + #{address}, + #{mobile}, + #{email}, + NOW(), + #{role} + ) + + + + UPDATE user SET + name = #{name}, + address = #{address}, + mobile = #{mobile}, + email = #{email}, + role = #{role} + WHERE id = #{id} + + + + DELETE FROM user WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/test/java/cn/abel/BaseTest.java b/springboot-dynamicDataSource/src/test/java/cn/abel/BaseTest.java new file mode 100644 index 0000000..2cb1d62 --- /dev/null +++ b/springboot-dynamicDataSource/src/test/java/cn/abel/BaseTest.java @@ -0,0 +1,32 @@ +package cn.abel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author yyb + * @time 2019/3/27 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@TestPropertySource("/application.properties") +public class BaseTest { + + @Configuration + @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) + static class ComponentScanConfig { + + } + + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/springboot-dynamicDataSource/src/test/java/cn/abel/service/ServiceTest.java b/springboot-dynamicDataSource/src/test/java/cn/abel/service/ServiceTest.java new file mode 100644 index 0000000..a4ddd52 --- /dev/null +++ b/springboot-dynamicDataSource/src/test/java/cn/abel/service/ServiceTest.java @@ -0,0 +1,29 @@ +package cn.abel.service; + +import cn.abel.BaseTest; +import cn.abel.bean.News; +import cn.abel.bean.User; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author yyb + * @time 2019/3/27 + */ +public class ServiceTest extends BaseTest { + + @Autowired + private NewsService newsService; + @Autowired + private UserService userService; + + @Test + public void dynamicDataSourceTest() throws Exception { + List newsList = newsService.getByMap(null); + List userList = userService.getByMap(null); + System.out.println("newsList----" + newsList.size() + "--userList---" + userList.size()); + + } +} diff --git a/springboot-elasticsearch/README.md b/springboot-elasticsearch/README.md new file mode 100644 index 0000000..90a60de --- /dev/null +++ b/springboot-elasticsearch/README.md @@ -0,0 +1,9 @@ + +## springboot-elasticsearch + +* 本项目是speingboot结合es 的小李子。 +* 演示了同一个项目配置多个es 数据源 +* es操作是用es的rest api 进行操作,操作语句是 通过 JSONObject 对象进行拼接,可以执行增、删、改、查 行为。 +具体的操作命令可以查看 Es RESTful API 官方文档 + +https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html \ No newline at end of file diff --git a/springboot-elasticsearch/pom.xml b/springboot-elasticsearch/pom.xml new file mode 100644 index 0000000..bcf0f44 --- /dev/null +++ b/springboot-elasticsearch/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + cn.abel + springboot-elasticserach + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.5 + + + mysql + mysql-connector-java + 5.1.40 + + + org.apache.commons + commons-lang3 + 3.4 + + + + + org.elasticsearch.client + elasticsearch-rest-client + 6.8.0 + + + + com.alibaba + fastjson + 1.2.40 + + + + + \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/java/cn/abel/Application.java b/springboot-elasticsearch/src/main/java/cn/abel/Application.java new file mode 100644 index 0000000..4c77f67 --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/Application.java @@ -0,0 +1,16 @@ +package cn.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/3/26 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-elasticsearch/src/main/java/cn/abel/bean/User.java b/springboot-elasticsearch/src/main/java/cn/abel/bean/User.java new file mode 100644 index 0000000..e1ddbf5 --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/bean/User.java @@ -0,0 +1,89 @@ +package cn.abel.bean; + +import java.util.Date; + + +public class User { + private Integer id; + private String name; + private String address; + private String mobile; + private String email; + private Date createTime; + private Integer role; + private String idCard; + private int type; + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getRole() { + return role; + } + + public void setRole(Integer role) { + this.role = role; + } + + public String getIdCard() { + return idCard; + } + + public void setIdCard(String idCard) { + this.idCard = idCard; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } +} \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClient2Config.java b/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClient2Config.java new file mode 100644 index 0000000..694d8d6 --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClient2Config.java @@ -0,0 +1,48 @@ +package cn.abel.config; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 第二数据源 + * @author yyb + * @time 2020/4/2 + */ +@Configuration +public class ESRestClient2Config { + public static final String NAME = "ESRestClient2Config"; + + @Value("${elasticsearch2.userName}") + private String userName; + @Value("${elasticsearch2.password}") + private String password; + @Value("${elasticsearch2.rest.hostNames}") + private String hostName; + @Value("${elasticsearch2.rest.port}") + private Integer port; + + @Bean(name = NAME, destroyMethod = "close") + public RestClient getRestClient() { + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(userName, password)); + RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostName, port)); + //配置身份验证 + restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { + @Override + public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + }); + return restClientBuilder.build(); + } +} diff --git a/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClientConfig.java b/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClientConfig.java new file mode 100644 index 0000000..8f122ab --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClientConfig.java @@ -0,0 +1,48 @@ +package cn.abel.config; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 第一数据源 + * @author yangyibo + * @time 2019/4/2 + */ +@Configuration +public class ESRestClientConfig { + public static final String NAME = "ESRestClientConfig"; + + @Value("${elasticsearch.userName}") + private String userName; + @Value("${elasticsearch.password}") + private String password; + @Value("${elasticsearch.rest.hostNames}") + private String hostName; + @Value("${elasticsearch.rest.port}") + private Integer port; + + @Bean(name = NAME, destroyMethod = "close") + public RestClient getRestClient() { + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(userName, password)); + RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostName, port)); + //配置身份验证 + restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { + @Override + public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { + return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + }); + return restClientBuilder.build(); + } +} diff --git a/springboot-elasticsearch/src/main/java/cn/abel/constants/Constants.java b/springboot-elasticsearch/src/main/java/cn/abel/constants/Constants.java new file mode 100644 index 0000000..d3b38be --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/constants/Constants.java @@ -0,0 +1,33 @@ +package cn.abel.constants; + +/** + * @author yangyibo + * @time 2019/4/3 + */ +public class Constants { + + /** + * es 查询query 拼接 前缀 + */ + public static final String ES_QUERY_JSON_PREFIX = "{\n" + + " \"query\": {\n" + + " \"term\": {\n" + + " \"userId\": {\n" + + " \"value\": \""; + /** + * es 查询query 拼接后缀 + */ + public static final String ES_QUERY_JSON_SUFFIX = "\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}\n"; + + /** + * 需要查询的es的 index + */ + public static final String ES_INDEX_PATH = "/logstash_indes/_search"; + +} + + diff --git a/springboot-elasticsearch/src/main/java/cn/abel/dao/UserDao.java b/springboot-elasticsearch/src/main/java/cn/abel/dao/UserDao.java new file mode 100644 index 0000000..077d1f5 --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/dao/UserDao.java @@ -0,0 +1,23 @@ +package cn.abel.dao; + +import java.util.List; +import java.util.Map; + +import cn.abel.bean.User; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Repository +@Mapper +public interface UserDao { + + List getByMap(Map map); + + User getById(Integer id); + + Integer create(User user); + + int update(User user); + + int delete(Integer id); +} \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/java/cn/abel/service/UserService.java b/springboot-elasticsearch/src/main/java/cn/abel/service/UserService.java new file mode 100644 index 0000000..10f08f2 --- /dev/null +++ b/springboot-elasticsearch/src/main/java/cn/abel/service/UserService.java @@ -0,0 +1,245 @@ +package cn.abel.service; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; +import org.elasticsearch.client.RestClient; +import cn.abel.config.ESRestClient2Config; +import cn.abel.config.ESRestClientConfig; +import cn.abel.constants.Constants; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.entity.ContentType; +import org.apache.http.nio.entity.NStringEntity; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +import cn.abel.dao.UserDao; +import cn.abel.bean.User; + +/** + * @author yyb + */ +@Service +public class UserService { + private static final Logger logger = LoggerFactory.getLogger(UserService.class); + protected static final ObjectMapper mapper = new ObjectMapper(); + + @Autowired + private UserDao userDao; + + /** + * 数据源1 + */ + @Autowired + @Qualifier(ESRestClientConfig.NAME) + private RestClient restClient; + + /** + * 数据源2 + */ + @Autowired + @Qualifier(ESRestClient2Config.NAME) + private RestClient restClient2; + + + public List getByMap(Map map) { + return userDao.getByMap(map); + } + + public User getById(Integer id) throws Exception { + //拼接es 的查询query + String json = Constants.ES_QUERY_JSON_PREFIX + id + Constants.ES_QUERY_JSON_SUFFIX; + HttpEntity entry = new NStringEntity(json, ContentType.APPLICATION_JSON); + Response response = restClient.performRequest(HttpGet.METHOD_NAME, Constants.ES_INDEX_PATH, Collections.emptyMap(), entry); + JSONObject responseJson = JSONObject.parseObject(EntityUtils.toString(response.getEntity())); + //es 中查询的结果 + System.out.println(responseJson); + return userDao.getById(id); + } + + + /** + * 查询用户列表 + * + * @param keyword 关键字用户名字/用户手机号/用户身份证号 + * @param type 用户类型/1:注册用户/2:转化用户 + * @param startTime 时间范围 起始时间 + * @param endTime 时间范围 结束时间 + * @param pageSize + * @param pageIndex + * @return + * @throws Exception + */ + public JSONObject getList(String keyword, Integer type, String startTime, String endTime, int pageSize, int pageIndex) throws Exception { + JsonNode searchResponse; + JSONObject response = new JSONObject(); + JSONObject search = searchListQuery(keyword, type, startTime, endTime, pageSize, pageIndex); + //根据档案英文名切换不同的索引 + String endpoint = "/user_Info_index/user/_search"; + + searchResponse = esSearch(search, endpoint, restClient); + if (null == searchResponse) { + return response; + } + JsonNode hitsNode = searchResponse.get("hits"); + ArrayNode hitsArray = (ArrayNode) hitsNode.get("hits"); + response.put("total", hitsNode.get("total").intValue()); + JSONArray list = new JSONArray(); + for (JsonNode hit : hitsArray) { + JSONObject result = (JSONObject) JSONObject.parse(hit.get("_source").toString()); + list.add(result); + } + response.put("list", list); + return response; + } + + + public User create(User user) { + userDao.create(user); + return user; + } + + public User update(User user) { + userDao.update(user); + return user; + } + + public int delete(Integer id) { + return userDao.delete(id); + } + + + /** + * 拼装列表查询query + * + * @param keyword + * @return + */ + private JSONObject searchListQuery(String keyword, Integer type, String startTime, String endTime, int pageSize, int pageIndex) { + //只返回列表所需数据 + String[] source = new String[]{"id", "user_name", "id_card", "user_name", "mobile", "type", "create_time"}; + JSONObject search = new JSONObject(); + search.put("_source", source); + if (pageIndex <= 0) { + pageIndex = 1; + } + JSONObject bool = new JSONObject(); + JSONArray sort = new JSONArray(); + + //查询类型 + JSONArray mustArray = new JSONArray(); + if (null != type) { + mustArray.add(getJSONObject("term", getJSONObject("type", type))); + } + bool.put("must", mustArray); + + //关键字查询 + if (StringUtils.isNotEmpty(keyword)) { + JSONObject multiMatch = new JSONObject(); + multiMatch.put("query", keyword); + multiMatch.put("fields", new String[]{"user_name.keyword", "user_name"}); + //查询条件 + JSONArray shouldArray = new JSONArray(); + //虚化查询 + shouldArray.add(getJSONObject("term", getJSONObject("id_card", keyword))); + shouldArray.add(getJSONObject("term", getJSONObject("mobile", keyword))); + shouldArray.add(getJSONObject("multi_match", multiMatch)); + //关键字评分排序 + sort.add(getJSONObject("_score", getJSONObject("order", "desc"))); + //should 必须命中一个 + bool.put("minimum_should_match", 1); + bool.put("should", shouldArray); + } + + //排序和时间过滤 + JSONObject rangeField = new JSONObject(); + //筛选创建时间大于 startTime 小于 endTime 的数据 + rangeField.put("gte", startTime); + rangeField.put("lte", endTime); + JSONObject range = new JSONObject(); + range.put("range", getJSONObject("create_time", rangeField)); + //按照创建时间规则倒叙排序 + sort.add(getJSONObject("create_time", getJSONObject("order", "desc"))); + bool.put("filter", range); + + search.put("sort", sort); + search.put("query", getJSONObject("bool", bool)); + return setPage(pageIndex, pageSize, search); + } + + + /** + * ES查询 + * + * @param search + * @return + */ + public JsonNode esSearch(JSONObject search, String endpoint, RestClient restClient) { + JsonNode responseNode = null; + try { + logger.info("查询es语句为 {}, endpoint 为:{}", search, endpoint.toString()); + + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + if (search != null) { + String data = search.toString(); + request.setJsonEntity(data); + } + try { + restClient.performRequest(request); + } catch (IOException e) { + logger.error("查询es语句报错为 {}", e.getMessage()); + } + Response response = restClient.performRequest(request); + String responseStr = EntityUtils.toString(response.getEntity()); + logger.info("查询结果为", responseStr); + responseNode = mapper.readTree(responseStr); + } catch (IOException e) { + logger.error("查询失败", e); + } + return responseNode; + } + + + /** + * 设置页面 + * + * @param pageIndex + * @param pageSize + * @param search + * @return + */ + public static JSONObject setPage(Integer pageIndex, Integer pageSize, JSONObject search) { + search.put("from", (pageIndex - 1) * pageSize); + search.put("size", pageSize); + return search; + } + + + /** + * 获取json 对象 + * + * @param key + * @param value + * @return + */ + public static JSONObject getJSONObject(String key, Object value) { + JSONObject term = new JSONObject(); + term.put(key, value); + return term; + } +} \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/resources/local/application.properties b/springboot-elasticsearch/src/main/resources/local/application.properties new file mode 100644 index 0000000..0186699 --- /dev/null +++ b/springboot-elasticsearch/src/main/resources/local/application.properties @@ -0,0 +1,70 @@ +## tomcat\u914D\u7F6E +server.port=8009 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.es.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-elasticsearch +application.main=cn.abel.Application + +## LOG +logging.file=./logs/springboot-elasticsearch.log + + +## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 +spring.datasource.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false + +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +#\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.datasource.min-idle=5 +#\u6700\u5927\u8FDE\u63A5\u6570\u91CF +spring.datasource.max-active=100 +#\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 +spring.datasource.validation-query=select 1 from dual +#\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.connection-timeout=60000 +#\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.max-left-time=60000 +#\u751F\u6548\u8D85\u65F6 +spring.datasource.validation-time-out=3000 +#\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.idle-time-out=60000 +#\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 +spring.datasource.connection-init-sql= set names utf8mb4 + +logging.level.cn.abel.dao=debug +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E +mybatis.mapper-locations=classpath*:mapper/*Mapper.xml +smybatis.type-aliases-package=cn.abel.bean +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E + +## pagehelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + +#es\u670D\u52A1\u5668\u5730\u5740\u914D\u7F6E +elasticsearch.userName= +elasticsearch.password= +elasticsearch.rest.hostNames=127.0.0.1 +elasticsearch.rest.port=9200 + + +#es2\u670D\u52A1\u5668\u5730\u5740\u914D\u7F6E +elasticsearch2.userName= +elasticsearch2.password= +elasticsearch2.rest.hostNames=127.0.0.1 +elasticsearch2.rest.port=9200 \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/resources/local/banner.txt b/springboot-elasticsearch/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-elasticsearch/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/resources/local/logback-spring.xml b/springboot-elasticsearch/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..18df5a2 --- /dev/null +++ b/springboot-elasticsearch/src/main/resources/local/logback-spring.xml @@ -0,0 +1,41 @@ + + + springboot-es + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-elasticsearch/src/main/resources/mapper/UserDaoMapper.xml b/springboot-elasticsearch/src/main/resources/mapper/UserDaoMapper.xml new file mode 100644 index 0000000..ec2ce2a --- /dev/null +++ b/springboot-elasticsearch/src/main/resources/mapper/UserDaoMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + and id = #{id} + + + and name = #{name} + + + and address = #{address} + + + and mobile = #{mobile} + + + and email = #{email} + + + and role = #{role} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO user( + id, + name, + address, + mobile, + email, + create_time, + role + )VALUES( + #{id}, + #{name}, + #{address}, + #{mobile}, + #{email}, + NOW(), + #{role} + ) + + + + UPDATE user SET + name = #{name}, + address = #{address}, + mobile = #{mobile}, + email = #{email}, + role = #{role} + WHERE id = #{id} + + + + DELETE FROM user WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-elasticsearch/src/test/java/cn/abel/BaseTest.java b/springboot-elasticsearch/src/test/java/cn/abel/BaseTest.java new file mode 100644 index 0000000..2cb1d62 --- /dev/null +++ b/springboot-elasticsearch/src/test/java/cn/abel/BaseTest.java @@ -0,0 +1,32 @@ +package cn.abel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author yyb + * @time 2019/3/27 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@TestPropertySource("/application.properties") +public class BaseTest { + + @Configuration + @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) + static class ComponentScanConfig { + + } + + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/springboot-elasticsearch/src/test/java/cn/abel/service/ServiceTest.java b/springboot-elasticsearch/src/test/java/cn/abel/service/ServiceTest.java new file mode 100644 index 0000000..b9ded5a --- /dev/null +++ b/springboot-elasticsearch/src/test/java/cn/abel/service/ServiceTest.java @@ -0,0 +1,25 @@ +package cn.abel.service; + +import cn.abel.BaseTest; +import cn.abel.bean.User; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + + +/** + * @author yyb + * @time 2019/3/27 + */ +public class ServiceTest extends BaseTest { + + + @Autowired + private UserService userService; + + @Test + public void dynamicDataSourceTest() throws Exception { + User user = userService.getById(1); + System.out.println("--userList---" + user.toString()); + + } +} diff --git a/springboot-jpa/pom.xml b/springboot-jpa/pom.xml index 0f1cc9a..6e54fd3 100644 --- a/springboot-jpa/pom.xml +++ b/springboot-jpa/pom.xml @@ -42,7 +42,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-kafka/pom.xml b/springboot-kafka/pom.xml new file mode 100644 index 0000000..8778b54 --- /dev/null +++ b/springboot-kafka/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + + cn.abel + springboot-kafka + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.alibaba + fastjson + 1.2.40 + + + + + org.springframework.kafka + spring-kafka + + + + org.projectlombok + lombok + true + + + \ No newline at end of file diff --git a/springboot-kafka/src/main/java/cn/abel/Application.java b/springboot-kafka/src/main/java/cn/abel/Application.java new file mode 100644 index 0000000..f2e2b4c --- /dev/null +++ b/springboot-kafka/src/main/java/cn/abel/Application.java @@ -0,0 +1,15 @@ +package cn.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; + +/** + * Created by yyb on 2018/12/12. + */ +@SpringBootApplication(exclude = KafkaAutoConfiguration.class) +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/springboot-kafka/src/main/java/cn/abel/config/KafkaConfig.java b/springboot-kafka/src/main/java/cn/abel/config/KafkaConfig.java new file mode 100644 index 0000000..f68bd15 --- /dev/null +++ b/springboot-kafka/src/main/java/cn/abel/config/KafkaConfig.java @@ -0,0 +1,88 @@ +package cn.abel.config; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.config.KafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by yyb on 2018/12/12. + */ +@Configuration +@EnableKafka +public class KafkaConfig { + + /** + * kafka地址 + */ + @Value("${spring.kafka.bootstrap-servers}") + private String bootstrapServers; + /** + * 默认组 + */ + @Value("${spring.kafka.consumer.group-id}") + private String groupId; + /** + * 自动消费设定 + */ + @Value("${spring.kafka.consumer.auto-offset-reset}") + private String autoOffsetReset; + /** + * 一次批量处理的数据量 + */ + @Value("${spring.kafka.consumer.max-poll-records}") + private int maxPollRecords; + /** + * 一次批量处理的时间间隔 + */ + @Value("${spring.kafka.consumer.max-poll-interval-ms}") + private int maxPollIntervalMs; + + @Value("${spring.kafka.listener.concurrency}") + private int cocurrency; + + @Value("${spring.kafka.consumer.auto-commit-interval}") + private Integer commitInterval; + + @Bean(name = "kafkaListenerContainerFactory") + public KafkaListenerContainerFactory batchFactory() { + ConcurrentKafkaListenerContainerFactory factory = + new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory()); + factory.setConcurrency(cocurrency); + //设置为批量消费,每个批次数量在Kafka配置参数中设置ConsumerConfig.MAX_POLL_RECORDS_CONFIG + factory.setBatchListener(true); + return factory; + } + + @Bean + public ConsumerFactory consumerFactory() { + return new DefaultKafkaConsumerFactory<>(consumerConfigs()); + } + @Bean + public Map consumerConfigs() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); + props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, commitInterval); + props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); + //每一批数量 + props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset); + return props; + } + + +} diff --git a/springboot-kafka/src/main/java/cn/abel/service/prehandle/KafkaConsumerService.java b/springboot-kafka/src/main/java/cn/abel/service/prehandle/KafkaConsumerService.java new file mode 100644 index 0000000..c454557 --- /dev/null +++ b/springboot-kafka/src/main/java/cn/abel/service/prehandle/KafkaConsumerService.java @@ -0,0 +1,28 @@ +package cn.abel.service.prehandle; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * Created by yyb on 2018/12/10. + */ + +@Component +public class KafkaConsumerService { + + @Autowired + private SplitService splitService; + + @KafkaListener(topics = "${log.statistical.kafka.topic}", containerFactory = "kafkaListenerContainerFactory") + public void processMessage(List> records) { + + for (ConsumerRecord record : records) { + String message = (String) record.value(); + splitService.saveAndSplitLog(message); + } + } +} diff --git a/springboot-kafka/src/main/java/cn/abel/service/prehandle/SplitService.java b/springboot-kafka/src/main/java/cn/abel/service/prehandle/SplitService.java new file mode 100644 index 0000000..7529274 --- /dev/null +++ b/springboot-kafka/src/main/java/cn/abel/service/prehandle/SplitService.java @@ -0,0 +1,26 @@ +package cn.abel.service.prehandle; + + +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + * Created by yyb on 2018/12/10. + */ +@Service +@Slf4j +public class SplitService { + + private static final Logger logger = LoggerFactory.getLogger(SplitService.class); + + public void saveAndSplitLog(String message) { + JSONObject jsonObject = JSONObject.parseObject(message); + // 从kafka 中获取到数据 + String content = jsonObject.getString("message"); + } + +} diff --git a/springboot-kafka/src/main/resources/local/application.properties b/springboot-kafka/src/main/resources/local/application.properties new file mode 100644 index 0000000..af51498 --- /dev/null +++ b/springboot-kafka/src/main/resources/local/application.properties @@ -0,0 +1,18 @@ +server.port=8090 +spring.kafka.bootstrap-servers=127.0.0.1:9092 +spring.kafka.consumer.group-id=springboot-kafka +spring.kafka.consumer.auto-offset-reset=latest +spring.kafka.consumer.enable-auto-commit=true +spring.kafka.consumer.auto-commit-interval=2000 +spring.kafka.listener.concurrency= 1 +spring.kafka.consumer.max-poll-records=50 +spring.kafka.consumer.max-poll-interval-ms=4000 +# topic +log.statistical.kafka.topic=nginx_log + + +logging.file=./logs/springboot-kafka.log + + + + diff --git a/springboot-kafka/src/main/resources/local/banner.txt b/springboot-kafka/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-kafka/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-kafka/src/main/resources/local/logback-spring.xml b/springboot-kafka/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..9a98e4a --- /dev/null +++ b/springboot-kafka/src/main/resources/local/logback-spring.xml @@ -0,0 +1,35 @@ + + + springboot-kafka + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 30 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-mybatis/pom.xml b/springboot-mybatis/pom.xml index 6ee2fd2..6227a2a 100644 --- a/springboot-mybatis/pom.xml +++ b/springboot-mybatis/pom.xml @@ -44,7 +44,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-mybatis2/pom.xml b/springboot-mybatis2/pom.xml new file mode 100644 index 0000000..9aac0cf --- /dev/null +++ b/springboot-mybatis2/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + cn.abel + springboot-mybatis2 + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.5 + + + mysql + mysql-connector-java + 5.1.40 + + + + org.apache.commons + commons-lang3 + 3.4 + + + + \ No newline at end of file diff --git a/springboot-mybatis2/sql/user.sql b/springboot-mybatis2/sql/user.sql new file mode 100644 index 0000000..a42941a --- /dev/null +++ b/springboot-mybatis2/sql/user.sql @@ -0,0 +1,35 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 50719 + Source Host : 127.0.0.1 + Source Database : oldMan + + Target Server Type : MySQL + Target Server Version : 50719 + File Encoding : utf-8 + + Date: 04/02/2019 15:27:32 PM +*/ + +SET NAMES utf8; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for `user` +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) DEFAULT NULL, + `address` varchar(200) DEFAULT NULL, + `mobile` varchar(50) DEFAULT NULL, + `email` varchar(100) DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `role` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/springboot-mybatis2/src/main/java/cn/abel/Application.java b/springboot-mybatis2/src/main/java/cn/abel/Application.java new file mode 100644 index 0000000..4c77f67 --- /dev/null +++ b/springboot-mybatis2/src/main/java/cn/abel/Application.java @@ -0,0 +1,16 @@ +package cn.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/3/26 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-mybatis2/src/main/java/cn/abel/bean/User.java b/springboot-mybatis2/src/main/java/cn/abel/bean/User.java new file mode 100644 index 0000000..58acdf2 --- /dev/null +++ b/springboot-mybatis2/src/main/java/cn/abel/bean/User.java @@ -0,0 +1,70 @@ +package cn.abel.bean; + +import java.util.Date; + + +public class User { + private Integer id; + private String name; + private String address; + private String mobile; + private String email; + private Date createTime; + private Integer role; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getRole() { + return role; + } + + public void setRole(Integer role) { + this.role = role; + } +} \ No newline at end of file diff --git a/springboot-mybatis2/src/main/java/cn/abel/dao/UserDao.java b/springboot-mybatis2/src/main/java/cn/abel/dao/UserDao.java new file mode 100644 index 0000000..077d1f5 --- /dev/null +++ b/springboot-mybatis2/src/main/java/cn/abel/dao/UserDao.java @@ -0,0 +1,23 @@ +package cn.abel.dao; + +import java.util.List; +import java.util.Map; + +import cn.abel.bean.User; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Repository; + +@Repository +@Mapper +public interface UserDao { + + List getByMap(Map map); + + User getById(Integer id); + + Integer create(User user); + + int update(User user); + + int delete(Integer id); +} \ No newline at end of file diff --git a/springboot-mybatis2/src/main/java/cn/abel/service/UserService.java b/springboot-mybatis2/src/main/java/cn/abel/service/UserService.java new file mode 100644 index 0000000..e21f61c --- /dev/null +++ b/springboot-mybatis2/src/main/java/cn/abel/service/UserService.java @@ -0,0 +1,39 @@ +package cn.abel.service; + +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import cn.abel.dao.UserDao; +import cn.abel.bean.User; + +@Service +public class UserService { + @Autowired + private UserDao userDao; + + public List getByMap(Map map){ + return userDao.getByMap(map); + } + + public User getById(Integer id){ + return userDao.getById(id); + } + + public User create(User user){ + userDao.create(user); + return user; + } + + public User update(User user){ + userDao.update(user); + return user; + } + + public int delete(Integer id){ + return userDao.delete(id); + } + +} \ No newline at end of file diff --git a/springboot-mybatis2/src/main/resources/local/application.properties b/springboot-mybatis2/src/main/resources/local/application.properties new file mode 100644 index 0000000..831a031 --- /dev/null +++ b/springboot-mybatis2/src/main/resources/local/application.properties @@ -0,0 +1,58 @@ +## tomcat\u914D\u7F6E +server.port=8009 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.risk.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-mybatis2 +application.main=cn.abel.Application + +## LOG +logging.file=./logs/springboot-mybatis2.log + + +## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 +spring.datasource.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false +spring.datasource.username=root +spring.datasource.password=admin +spring.datasource.driverClassName=com.mysql.jdbc.Driver + +spring.datasource.type=com.zaxxer.hikari.HikariDataSource +#\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.datasource.min-idle=5 +#\u6700\u5927\u8FDE\u63A5\u6570\u91CF +spring.datasource.max-active=100 +#\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 +spring.datasource.validation-query=select 1 from dual +#\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.connection-timeout=60000 +#\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.max-left-time=60000 +#\u751F\u6548\u8D85\u65F6 +spring.datasource.validation-time-out=3000 +#\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 +spring.datasource.idle-time-out=60000 +#\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 +spring.datasource.connection-init-sql= set names utf8mb4 + +logging.level.cn.abel.dao=debug +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E +mybatis.mapper-locations=classpath*:mapper/*Mapper.xml +smybatis.type-aliases-package=cn.abel.bean +#Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E + +## pagehelper +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql + + diff --git a/springboot-mybatis2/src/main/resources/local/banner.txt b/springboot-mybatis2/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-mybatis2/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-mybatis2/src/main/resources/local/logback-spring.xml b/springboot-mybatis2/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..52e1a99 --- /dev/null +++ b/springboot-mybatis2/src/main/resources/local/logback-spring.xml @@ -0,0 +1,41 @@ + + + abel_user + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-mybatis2/src/main/resources/mapper/NewsDaoMapper.xml b/springboot-mybatis2/src/main/resources/mapper/NewsDaoMapper.xml new file mode 100644 index 0000000..b4eeb93 --- /dev/null +++ b/springboot-mybatis2/src/main/resources/mapper/NewsDaoMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + and id = #{id} + + + and title = #{title} + + + and content = #{content} + + + and image_path = #{imagePath} + + + and read_sum = #{readSum} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO news( + id, + title, + content, + image_path, + read_sum + )VALUES( + #{id}, + #{title}, + #{content}, + #{imagePath}, + #{readSum} + ) + + + + UPDATE news SET + title = #{title}, + content = #{content}, + image_path = #{imagePath}, + read_sum = #{readSum} + WHERE id = #{id} + + + + DELETE FROM news WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-mybatis2/src/main/resources/mapper/UserDaoMapper.xml b/springboot-mybatis2/src/main/resources/mapper/UserDaoMapper.xml new file mode 100644 index 0000000..ec2ce2a --- /dev/null +++ b/springboot-mybatis2/src/main/resources/mapper/UserDaoMapper.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + and id = #{id} + + + and name = #{name} + + + and address = #{address} + + + and mobile = #{mobile} + + + and email = #{email} + + + and role = #{role} + + + + + + + + + + + + SELECT LAST_INSERT_ID() + + INSERT INTO user( + id, + name, + address, + mobile, + email, + create_time, + role + )VALUES( + #{id}, + #{name}, + #{address}, + #{mobile}, + #{email}, + NOW(), + #{role} + ) + + + + UPDATE user SET + name = #{name}, + address = #{address}, + mobile = #{mobile}, + email = #{email}, + role = #{role} + WHERE id = #{id} + + + + DELETE FROM user WHERE id = #{id} + + + \ No newline at end of file diff --git a/springboot-mybatis2/src/test/java/cn/abel/BaseTest.java b/springboot-mybatis2/src/test/java/cn/abel/BaseTest.java new file mode 100644 index 0000000..2cb1d62 --- /dev/null +++ b/springboot-mybatis2/src/test/java/cn/abel/BaseTest.java @@ -0,0 +1,32 @@ +package cn.abel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author yyb + * @time 2019/3/27 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@TestPropertySource("/application.properties") +public class BaseTest { + + @Configuration + @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) + static class ComponentScanConfig { + + } + + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/springboot-mybatis2/src/test/java/cn/abel/service/ServiceTest.java b/springboot-mybatis2/src/test/java/cn/abel/service/ServiceTest.java new file mode 100644 index 0000000..f1d4046 --- /dev/null +++ b/springboot-mybatis2/src/test/java/cn/abel/service/ServiceTest.java @@ -0,0 +1,26 @@ +package cn.abel.service; + +import cn.abel.BaseTest; +import cn.abel.bean.User; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author yyb + * @time 2019/3/27 + */ +public class ServiceTest extends BaseTest { + + + @Autowired + private UserService userService; + + @Test + public void dynamicDataSourceTest() throws Exception { + List userList = userService.getByMap(null); + System.out.println("--userList---" + userList.size()); + + } +} diff --git "a/springboot-neo4j/doc/\346\225\210\346\236\234\345\233\276.png" "b/springboot-neo4j/doc/\346\225\210\346\236\234\345\233\276.png" new file mode 100644 index 0000000..dd49d1c Binary files /dev/null and "b/springboot-neo4j/doc/\346\225\210\346\236\234\345\233\276.png" differ diff --git a/springboot-neo4j/pom.xml b/springboot-neo4j/pom.xml new file mode 100644 index 0000000..0276891 --- /dev/null +++ b/springboot-neo4j/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + + cn.abel + springboot-neo4j + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-freemarker + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.5 + + + mysql + mysql-connector-java + 5.1.40 + + + + + org.apache.commons + commons-lang3 + 3.4 + + + com.alibaba + fastjson + 1.2.40 + + + + + org.springframework.boot + spring-boot-starter-data-neo4j + + + org.neo4j + neo4j-ogm-http-driver + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + \ No newline at end of file diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/Application.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/Application.java new file mode 100644 index 0000000..ee58401 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/Application.java @@ -0,0 +1,17 @@ +package cn.abel.neo4j; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +/** + * @author yyb + * @time 2019/3/26 + */ +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/King.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/King.java new file mode 100644 index 0000000..86a0f56 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/King.java @@ -0,0 +1,141 @@ +package cn.abel.neo4j.bean; + + +import cn.abel.neo4j.bean.relation.FatherAndSonRelation; +import org.neo4j.ogm.annotation.NodeEntity; +import org.neo4j.ogm.annotation.Relationship; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * 皇帝 + * + * @author yyb + * @time 2020/3/23 + */ +@NodeEntity(label = "King") +public class King extends Person implements Serializable { + + /** + * 名字 + */ + private String name; + /** + * 家系:家族关系 + */ + private String clan; + /** + * 年号:生活的时代 + */ + private String times; + /** + * 谥号:人死之后,后人给予评价 + */ + private String posthumousTitle; + /** + * 庙号:君主于庙中被供奉时所称呼的名号 + */ + private String TempleNumber; + /** + * 陵墓 + */ + private String tomb; + /** + * 大事件 + */ + private String remark; + + @Relationship(type = "传位") + King successor; + + /** + * 第二种保存关系的方式 + */ + @Relationship + List sons; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClan() { + return clan; + } + + public void setClan(String clan) { + this.clan = clan; + } + + public String getTimes() { + return times; + } + + public void setTimes(String times) { + this.times = times; + } + + public String getPosthumousTitle() { + return posthumousTitle; + } + + public void setPosthumousTitle(String posthumousTitle) { + this.posthumousTitle = posthumousTitle; + } + + public String getTempleNumber() { + return TempleNumber; + } + + public void setTempleNumber(String templeNumber) { + TempleNumber = templeNumber; + } + + public String getTomb() { + return tomb; + } + + public void setTomb(String tomb) { + this.tomb = tomb; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public King getSuccessor() { + return successor; + } + + public void setSuccessor(King successor) { + this.successor = successor; + } + + public List getSons() { + return sons; + } + + public void setSons(List sons) { + this.sons = sons; + } + + /** + * 添加友谊的关系 + * @param + */ + public void addRelation(FatherAndSonRelation fatherAndSonRelation){ + if(this.sons == null){ + this.sons = new ArrayList<>(); + } + this.sons.add(fatherAndSonRelation); + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Person.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Person.java new file mode 100644 index 0000000..684069c --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Person.java @@ -0,0 +1,25 @@ +package cn.abel.neo4j.bean; + +import org.neo4j.ogm.annotation.GeneratedValue; +import org.neo4j.ogm.annotation.Id; +import org.neo4j.ogm.annotation.Index; + +/** + * @author yyb + * @time 2020/3/23 + */ +public class Person { + + @Id +// @GeneratedValue 该注解应去除否则插入不成功 + @Index + private long id; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Queen.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Queen.java new file mode 100644 index 0000000..db5dec5 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Queen.java @@ -0,0 +1,111 @@ +package cn.abel.neo4j.bean; + +import org.neo4j.ogm.annotation.Relationship; + +/** + * 皇后 + * + * @author yyb + * @time 2020/3/23 + */ +public class Queen extends Person { + /** + * 名字 + */ + private String name; + /** + * 家系:家族关系 + */ + private String clan; + /** + * 年号:生活的时代 + */ + private String times; + /** + * 庙号:君主于庙中被供奉时所称呼的名号 + */ + private String TempleNumber; + /** + * 谥号:人死之后,后人给予评价 + */ + private String posthumousTitle; + /** + * 陵墓 + */ + private String son; + /** + * 备注 + */ + private String remark; + + /** + * 关系指向自己 + */ + @Relationship(type = "皇后", direction = Relationship.INCOMING) + private King king; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClan() { + return clan; + } + + public void setClan(String clan) { + this.clan = clan; + } + + public String getTimes() { + return times; + } + + public void setTimes(String times) { + this.times = times; + } + + public String getTempleNumber() { + return TempleNumber; + } + + public void setTempleNumber(String templeNumber) { + TempleNumber = templeNumber; + } + + public String getPosthumousTitle() { + return posthumousTitle; + } + + public void setPosthumousTitle(String posthumousTitle) { + this.posthumousTitle = posthumousTitle; + } + + public String getSon() { + return son; + } + + public void setSon(String son) { + this.son = son; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public King getKing() { + return king; + } + + public void setKing(King king) { + this.king = king; + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/relation/FatherAndSonRelation.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/relation/FatherAndSonRelation.java new file mode 100644 index 0000000..1b71a26 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/bean/relation/FatherAndSonRelation.java @@ -0,0 +1,49 @@ +package cn.abel.neo4j.bean.relation; + +import cn.abel.neo4j.bean.King; +import org.neo4j.ogm.annotation.EndNode; +import org.neo4j.ogm.annotation.Id; +import org.neo4j.ogm.annotation.RelationshipEntity; +import org.neo4j.ogm.annotation.StartNode; + +/** + * 父子关系实体 + * @author yyb + * @time 2020/3/24 + */ +@RelationshipEntity(type = "father_son") +public class FatherAndSonRelation { + + @Id + private long id; + + @StartNode + private King from; + + @EndNode + private King to; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public King getFrom() { + return from; + } + + public void setFrom(King from) { + this.from = from; + } + + public King getTo() { + return to; + } + + public void setTo(King to) { + this.to = to; + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/controller/KingController.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/controller/KingController.java new file mode 100644 index 0000000..0a34f80 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/controller/KingController.java @@ -0,0 +1,45 @@ +package cn.abel.neo4j.controller; + + +import cn.abel.neo4j.bean.King; +import cn.abel.neo4j.service.KingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yyb + * @time 2020/3/23 + */ +@Controller +@RequestMapping("/king") +public class KingController { + + @Autowired + private KingService kingService; + @RequestMapping(value = "/save/{id}", method = RequestMethod.GET) + @ResponseBody + public String save(@PathVariable long id){ + List kingList = new ArrayList<>(); + King king = new King(); + king.setId(id); + king.setName("朱元璋"); + king.setClan("创业者"); + king.setPosthumousTitle("高皇帝"); + king.setTimes("洪武(1368年——1398年)"); + king.setTempleNumber("太祖"); + king.setTomb("孝陵"); + king.setRemark("空印案,胡惟庸案"); + kingList.add(king); + kingService.saveKing(kingList); + return "ok"; + } + + +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/KingDao.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/KingDao.java new file mode 100644 index 0000000..3bb635e --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/KingDao.java @@ -0,0 +1,39 @@ +package cn.abel.neo4j.dao; + +import cn.abel.neo4j.bean.King; +import org.springframework.data.neo4j.annotation.Query; +import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 使用Springboot - data - neo4j 生成 + * + * @author yyb + * @time 2020/3/23 + */ +@Repository +@Transactional(rollbackFor = Exception.class) +public interface KingDao extends Neo4jRepository { + + /** + * 通过名字查找King + * + * @param name + * @return + */ + King findByName(String name); + + + /** + * 获取当前节点下的所有king + * + * @param name + * @return + */ + @Query("match p=(a:King)-[r:`传位`*0..]->(b:King) where a.name={0} return p") + List getKings(String name); + +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jDao.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jDao.java new file mode 100644 index 0000000..6469a75 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jDao.java @@ -0,0 +1,55 @@ +package cn.abel.neo4j.dao; + +import org.neo4j.ogm.config.Configuration; +import org.neo4j.ogm.config.ConfigurationSource; +import org.neo4j.ogm.session.SessionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Repository; + +import java.util.Properties; + +/** + * @author yyb + * @time 2020/3/23 + */ +@Repository +public class Neo4jDao { + private static final Logger logger = LoggerFactory.getLogger(Neo4jDao.class); + private static final String packages = "cn.abel.neo4j.bean"; + + private SessionFactory sessionFactory = null; + + @Value("${neo4j.url}") + private String boltUri; + @Value("${neo4j.username}") + private String username; + @Value("${neo4j.password}") + private String password; + + /** + * 打开一个到neo4j的连接会话。 + */ + public Neo4jSession open() { + SessionFactory factory = getSessionFactory(); + Neo4jSession session = new Neo4jSession(factory); + return session; + } + + private synchronized SessionFactory getSessionFactory() { + if (sessionFactory == null) { + ConfigurationSource props = () -> { + Properties properties = new Properties(); + properties.setProperty("URI", boltUri); + properties.setProperty("username", username); + properties.setProperty("password", password); + return properties; + }; + Configuration configuration = new Configuration.Builder(props).build(); + sessionFactory = new SessionFactory(configuration, packages); + } + return sessionFactory; + } +} + diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jSession.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jSession.java new file mode 100644 index 0000000..9e91857 --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jSession.java @@ -0,0 +1,59 @@ +package cn.abel.neo4j.dao; + +import org.neo4j.ogm.session.Session; +import org.neo4j.ogm.session.SessionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +/** + * @author yyb + * @time 2020/3/23 + */ +public class Neo4jSession { + private static final Logger logger = LoggerFactory.getLogger(Neo4jSession.class); + private Session session; + private static final int DEPTH_ENTITY = 1; + + public Neo4jSession(SessionFactory factory) { + session = factory.openSession(); + } + + /** + * 执行cypher命令。 + * 增、删、改、查的 cypher 命令都可以用此方法操作 + * + * @param cypher + * @return + */ + public Iterator> exec(String cypher) { + long time = System.currentTimeMillis(); + Iterator> it = session.query(cypher, Collections.EMPTY_MAP).iterator(); + logger.info("ExecCypher {} cost:{}ms", cypher, System.currentTimeMillis() - time); + return it; + } + + + /** + * 存储对象 + * + * @param o + * @return + */ + public void execSave(Object o) { + long time = System.currentTimeMillis(); + session.clear(); + session.save(o); + logger.info("ExecCypher {} cost:{}ms", o.toString(), System.currentTimeMillis() - time); + } + + /** + * 清空 session 缓存。 + */ + public void clear() { + session.clear(); + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/dto/GraphDTO.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/dto/GraphDTO.java new file mode 100644 index 0000000..a7f1a7c --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/dto/GraphDTO.java @@ -0,0 +1,29 @@ +package cn.abel.neo4j.dto; + +import java.util.List; + +/** + * 用于输出图 + * @author yyb + * @time 2020/3/24 + */ +public class GraphDTO { + private List nodes; + private List links; + + public List getNodes() { + return nodes; + } + + public void setNodes(List nodes) { + this.nodes = nodes; + } + + public List getLinks() { + return links; + } + + public void setLinks(List links) { + this.links = links; + } +} diff --git a/springboot-neo4j/src/main/java/cn/abel/neo4j/service/KingService.java b/springboot-neo4j/src/main/java/cn/abel/neo4j/service/KingService.java new file mode 100644 index 0000000..a68487f --- /dev/null +++ b/springboot-neo4j/src/main/java/cn/abel/neo4j/service/KingService.java @@ -0,0 +1,150 @@ +package cn.abel.neo4j.service; + +import cn.abel.neo4j.bean.King; +import cn.abel.neo4j.bean.Queen; +import cn.abel.neo4j.bean.relation.FatherAndSonRelation; +import cn.abel.neo4j.dao.KingDao; +import cn.abel.neo4j.dao.Neo4jDao; +import cn.abel.neo4j.dao.Neo4jSession; +import cn.abel.neo4j.dto.GraphDTO; +import org.neo4j.driver.internal.InternalNode; +import org.neo4j.driver.internal.InternalPath; +import org.neo4j.driver.internal.InternalRelationship; +import org.neo4j.driver.v1.types.Node; +import org.neo4j.driver.v1.types.Relationship; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author yyb + * @time 2020/3/23 + */ +@Service +public class KingService { + @Autowired + private Neo4jDao neo4jDao; + + @Autowired + private KingDao kingDao; + + /** + * 保存皇帝信息 + * + * @param list + */ + public void saveKing(List list) { + Neo4jSession session = neo4jDao.open(); + list.forEach(x -> { + session.execSave(x); + }); + } + + /** + * 保存皇后信息 + * + * @param list + */ + public void saveQueen(List list) { + Neo4jSession session = neo4jDao.open(); + list.forEach(x -> { + session.execSave(x); + }); + } + + + /** + * 通过皇帝名字,查到当前的皇后和上一任皇帝 + * + * @param + */ + public GraphDTO getKingAndQueen(String kingName) { + Neo4jSession session = neo4jDao.open(); + String cypher = "match p=(a:King)-[r:`传位`]->(b:King)-[r2:`皇后`*1..]->(c:Queen) where a.name ='" + kingName + "' return p"; +// 通过皇帝名字查询到当前皇帝皇后以及上一任皇帝皇后 +// match p=(a:King)-[r:`传位`]->(b:King)-[r2:`皇后`*1..]->(c:Queen), (a:King)-[r3:`皇后`*1..]->(d:Queen) where b.name ='朱棣' return a,b,c,d + Iterator> iterator = session.exec(cypher); + GraphDTO gto = mapToGraph(iterator); + return gto; + } + + + private GraphDTO mapToGraph( + Iterator> neo4jDataIterator) { + Map nodeMap = new HashMap<>(); + Map linkMap = new HashMap<>(); + + while (neo4jDataIterator.hasNext()) { + Map each = neo4jDataIterator.next(); + if (!each.containsKey("p")) { + continue; + } + + InternalPath internalPath = (InternalPath) each.get("p"); + //归纳出所有节点。 + for (Node node : internalPath.nodes()) { + InternalNode internalNode = (InternalNode) node; + if (nodeMap.containsKey(internalNode.id())) { + continue; + } + nodeMap.put(internalNode.id(), internalNode); + } + //归纳出所有关系。 + for (Relationship relation : internalPath.relationships()) { + InternalRelationship internalRelation = (InternalRelationship) relation; + if (linkMap.containsKey(internalRelation.id())) { + continue; + } + linkMap.put(internalRelation.id(), internalRelation); + } + } + + GraphDTO dto = new GraphDTO(); + dto.setNodes(nodeMap.values().stream().collect(Collectors.toList())); + dto.setLinks(linkMap.values().stream().collect(Collectors.toList())); + return dto; + } + + + /** + * 查询一个皇帝信息,此处使用spring-data-neo4j 接口 + * + * @param name + */ + public King findByName(String name) { + King t = kingDao.findByName(name); + return t; + } + + + /** + * 获取当前节点下的所有king + * + * @param name + * @return + */ + public List getKings(String name) { + return kingDao.getKings(name); + } + + + /** + * 保存父子关系 + * + * @param fatherName + * @param sonName + * @return + */ + public void saveRelation(String fatherName, String sonName) { + King from = kingDao.findByName(fatherName); + King to = kingDao.findByName(sonName); + FatherAndSonRelation fatherAndSonRelation = new FatherAndSonRelation(); + fatherAndSonRelation.setFrom(from); + fatherAndSonRelation.setTo(to); + from.addRelation(fatherAndSonRelation); + kingDao.save(from); + } +} diff --git a/springboot-neo4j/src/main/resources/application.properties b/springboot-neo4j/src/main/resources/application.properties new file mode 100644 index 0000000..92cf343 --- /dev/null +++ b/springboot-neo4j/src/main/resources/application.properties @@ -0,0 +1,24 @@ +#application +spring.application.name=springboot-neo4j +application.main=cn.abel.Application +server.port=9657 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +server.tomcat.max-threads=200 +server.session-timeout=60 +log4j.logger.java.sql.Connection=DEBUG + + +logging.file=./logs/springboot-neo4j/springboot-neo4j.log + +spring.data.neo4j.url=bolt://localhost:7687 +spring.data.neo4j.username=neo4j +spring.data.neo4j.password=admin + + +neo4j.url=bolt://localhost:7687 +neo4j.username=neo4j +neo4j.password=admin \ No newline at end of file diff --git a/springboot-neo4j/src/main/resources/banner.txt b/springboot-neo4j/src/main/resources/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-neo4j/src/main/resources/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-neo4j/src/main/resources/logback-spring.xml b/springboot-neo4j/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..6b5d7c9 --- /dev/null +++ b/springboot-neo4j/src/main/resources/logback-spring.xml @@ -0,0 +1,41 @@ + + + springboot-neo4j + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-neo4j/src/test/java/cn/abel/neo4j/BaseTest.java b/springboot-neo4j/src/test/java/cn/abel/neo4j/BaseTest.java new file mode 100644 index 0000000..c432af8 --- /dev/null +++ b/springboot-neo4j/src/test/java/cn/abel/neo4j/BaseTest.java @@ -0,0 +1,32 @@ +package cn.abel.neo4j; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * @author yyb + * @time 2019/3/27 + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class) +@TestPropertySource("/application.properties") +public class BaseTest { + + @Configuration + @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) + static class ComponentScanConfig { + + } + + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/springboot-neo4j/src/test/java/cn/abel/neo4j/service/InitData.java b/springboot-neo4j/src/test/java/cn/abel/neo4j/service/InitData.java new file mode 100644 index 0000000..4789cfa --- /dev/null +++ b/springboot-neo4j/src/test/java/cn/abel/neo4j/service/InitData.java @@ -0,0 +1,642 @@ +package cn.abel.neo4j.service; + +import cn.abel.neo4j.bean.King; +import cn.abel.neo4j.bean.Queen; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yyb + * @time 2020/3/24 + */ +public class InitData { + + public static List initKing() { + List kingList = new ArrayList<>(); + + King king1 = new King(); + king1.setId(1L); + king1.setName("朱元璋"); + king1.setClan("朱五四之子朱棣之父"); + king1.setPosthumousTitle("高皇帝"); + king1.setTimes("洪武(1368年——1398年)"); + king1.setTempleNumber("太祖"); + king1.setTomb("孝陵"); + king1.setRemark("空印案,胡惟庸案"); + + King king2 = new King(); + king2.setId(2L); + king2.setName("朱允炆"); + king2.setClan("朱元璋之孙朱标次子"); + king2.setPosthumousTitle("成皇帝"); + king2.setTimes("建文(1399年——1402年)"); + king2.setTempleNumber("惠宗"); + king2.setTomb("上金贝古墓"); + king2.setRemark(""); + + + King king3 = new King(); + king3.setId(3L); + king3.setName("朱棣"); + king3.setClan("朱元璋四子"); + king3.setPosthumousTitle("文皇帝"); + king3.setTimes("永乐(1403年——1424年)"); + king3.setTempleNumber("成祖(原为太宗)"); + king3.setTomb("长陵"); + king3.setRemark(""); + + King king4 = new King(); + king4.setId(4L); + king4.setName("朱高炽"); + king4.setClan("朱棣长子"); + king4.setPosthumousTitle("昭皇帝"); + king4.setTimes("洪熙(1424年——1425年)"); + king4.setTempleNumber("仁宗"); + king4.setTomb("献陵"); + king4.setRemark(""); + + King king5 = new King(); + king5.setId(5L); + king5.setName("朱瞻基"); + king5.setClan("朱高炽长子"); + king5.setPosthumousTitle("章皇帝"); + king5.setTimes("宣德(1426年——1435年)"); + king5.setTempleNumber("宣宗"); + king5.setTomb("景陵"); + king5.setRemark(""); + + King king6 = new King(); + king6.setId(6L); + king6.setName("朱祁镇"); + king6.setClan("朱瞻基长子"); + king6.setPosthumousTitle("睿皇帝"); + king6.setTimes("正统(1436年——1449年) 天顺(1457年——1464年)"); + king6.setTempleNumber("英宗"); + king6.setTomb("裕陵"); + king6.setRemark(""); + + King king7 = new King(); + king7.setId(7L); + king7.setName("朱祁钰"); + king7.setClan("朱瞻基次子(庶出),朱祁镇之弟(后英宗复位,代宗被废)"); + king7.setPosthumousTitle("景皇帝"); + king7.setTimes("景泰(1450年——1457年) "); + king7.setTempleNumber("代宗"); + king7.setTomb("景泰陵"); + king7.setRemark(""); + + King king8 = new King(); + king8.setId(8L); + king8.setName("朱见深"); + king8.setClan("乃朱祁镇长子(庶出),朱祁钰从子"); + king8.setPosthumousTitle("纯皇帝"); + king8.setTimes("成化(1465年——1487年)"); + king8.setTempleNumber("宪宗"); + king8.setTomb("茂陵"); + king8.setRemark(""); + + King king9 = new King(); + king9.setId(9L); + king9.setName("朱祐樘"); + king9.setClan("乃朱见深三子(庶出)"); + king9.setPosthumousTitle("敬皇帝"); + king9.setTimes("弘治(1488年——1505年)"); + king9.setTempleNumber("孝宗"); + king9.setTomb("泰陵"); + king9.setRemark(""); + + King king10 = new King(); + king10.setId(10L); + king10.setName("朱厚照"); + king10.setClan("乃朱祐樘长子(武宗无嗣,乃由旁支皇室选择朱厚熜入继大统)"); + king10.setPosthumousTitle("高皇帝"); + king10.setTimes("洪武(1368年——1398年)"); + king10.setTempleNumber("武宗"); + king10.setTomb("孝陵"); + king10.setRemark(""); + + King king11 = new King(); + king11.setId(11L); + king11.setName("朱厚熜"); + king11.setClan("乃朱见深四子兴献王朱祐杬(庶出)之嫡长子,朱祐樘从子,朱厚照从弟"); + king11.setPosthumousTitle("肃皇帝"); + king11.setTimes("嘉靖(1522年——1566年)"); + king11.setTempleNumber("世宗"); + king11.setTomb("永陵"); + king11.setRemark("大仪礼"); + + King king12 = new King(); + king12.setId(12L); + king12.setName("朱载垕"); + king12.setClan("乃朱厚熜三子(庶出)"); + king12.setPosthumousTitle("庄皇帝"); + king12.setTimes("隆庆(1567年——1572年)"); + king12.setTempleNumber("穆宗"); + king12.setTomb("昭陵"); + king12.setRemark(""); + + + King king13 = new King(); + king13.setId(13L); + king13.setName("朱翊钧"); + king13.setClan("乃朱载垕三子(庶出)"); + king13.setPosthumousTitle("显皇帝"); + king13.setTimes("万历(1573年——1620年)"); + king13.setTempleNumber("神宗"); + king13.setTomb("定陵"); + king13.setRemark(""); + + King king14 = new King(); + king14.setId(14L); + king14.setName("朱常洛"); + king14.setClan("乃朱翊钧长子"); + king14.setPosthumousTitle("贞皇帝"); + king14.setTimes("泰昌(1620年)实际在位一个月"); + king14.setTempleNumber("光宗"); + king14.setTomb("庆陵"); + king14.setRemark(""); + + + King king15 = new King(); + king15.setId(15L); + king15.setName("朱由校"); + king15.setClan("乃朱常洛长子(庶出)(熹宗死后无嗣,乃诏令五弟信王朱由检入继大统)"); + king15.setPosthumousTitle("悊皇帝"); + king15.setTimes("天启(1621年——1627年)"); + king15.setTempleNumber("熹宗"); + king15.setTomb("德陵"); + king15.setRemark(""); + + + King king16 = new King(); + king16.setId(16L); + king16.setName("朱由检"); + king16.setClan("乃朱常洛五子(庶出)(毅宗死后,明朝覆灭,宗室乃于南方割据)"); + king16.setPosthumousTitle("烈皇帝"); + king16.setTimes("崇祯(1628年——1644年)"); + king16.setTempleNumber("毅宗(原为思宗)"); + king16.setTomb("思陵"); + king16.setRemark(""); + + + king1.setSuccessor(king2); + king2.setSuccessor(king3); + king3.setSuccessor(king4); + king4.setSuccessor(king5); + king5.setSuccessor(king6); + king6.setSuccessor(king7); + king7.setSuccessor(king8); + king8.setSuccessor(king9); + king9.setSuccessor(king10); + king10.setSuccessor(king11); + king11.setSuccessor(king12); + king12.setSuccessor(king13); + king13.setSuccessor(king14); + king14.setSuccessor(king15); + king15.setSuccessor(king16); + + kingList.add(king1); + kingList.add(king2); + kingList.add(king3); + kingList.add(king4); + kingList.add(king5); + kingList.add(king6); + kingList.add(king7); + kingList.add(king8); + kingList.add(king9); + kingList.add(king10); + kingList.add(king11); + kingList.add(king12); + kingList.add(king13); + kingList.add(king14); + kingList.add(king15); + kingList.add(king16); + + + return kingList; + } + + public static List initQueen() { + + King king1 = new King(); + king1.setId(1L); + king1.setName("朱元璋"); + king1.setClan("朱五四之子朱棣之父"); + king1.setPosthumousTitle("高皇帝"); + king1.setTimes("洪武(1368年——1398年)"); + king1.setTempleNumber("太祖"); + king1.setTomb("孝陵"); + king1.setRemark("空印案,胡惟庸案"); + + King king2 = new King(); + king2.setId(2L); + king2.setName("朱允炆"); + king2.setClan("朱元璋之孙朱标次子"); + king2.setPosthumousTitle("成皇帝"); + king2.setTimes("建文(1399年——1402年)"); + king2.setTempleNumber("惠宗"); + king2.setTomb("上金贝古墓"); + king2.setRemark(""); + + + King king3 = new King(); + king3.setId(3L); + king3.setName("朱棣"); + king3.setClan("朱元璋四子"); + king3.setPosthumousTitle("文皇帝"); + king3.setTimes("永乐(1403年——1424年)"); + king3.setTempleNumber("成祖(原为太宗)"); + king3.setTomb("长陵"); + king3.setRemark(""); + + King king4 = new King(); + king4.setId(4L); + king4.setName("朱高炽"); + king4.setClan("朱棣长子"); + king4.setPosthumousTitle("昭皇帝"); + king4.setTimes("洪熙(1424年——1425年)"); + king4.setTempleNumber("仁宗"); + king4.setTomb("献陵"); + king4.setRemark(""); + + King king5 = new King(); + king5.setId(5L); + king5.setName("朱瞻基"); + king5.setClan("朱高炽长子"); + king5.setPosthumousTitle("章皇帝"); + king5.setTimes("宣德(1426年——1435年)"); + king5.setTempleNumber("宣宗"); + king5.setTomb("景陵"); + king5.setRemark(""); + + King king6 = new King(); + king6.setId(6L); + king6.setName("朱祁镇"); + king6.setClan("朱瞻基长子"); + king6.setPosthumousTitle("睿皇帝"); + king6.setTimes("正统(1436年——1449年) 天顺(1457年——1464年)"); + king6.setTempleNumber("英宗"); + king6.setTomb("裕陵"); + king6.setRemark(""); + + King king7 = new King(); + king7.setId(7L); + king7.setName("朱祁钰"); + king7.setClan("朱瞻基次子(庶出),朱祁镇之弟(后英宗复位,代宗被废)"); + king7.setPosthumousTitle("景皇帝"); + king7.setTimes("景泰(1450年——1457年) "); + king7.setTempleNumber("代宗"); + king7.setTomb("景泰陵"); + king7.setRemark(""); + + King king8 = new King(); + king8.setId(8L); + king8.setName("朱见深"); + king8.setClan("乃朱祁镇长子(庶出),朱祁钰从子"); + king8.setPosthumousTitle("纯皇帝"); + king8.setTimes("成化(1465年——1487年)"); + king8.setTempleNumber("宪宗"); + king8.setTomb("茂陵"); + king8.setRemark(""); + + King king9 = new King(); + king9.setId(9L); + king9.setName("朱祐樘"); + king9.setClan("乃朱见深三子(庶出)"); + king9.setPosthumousTitle("敬皇帝"); + king9.setTimes("弘治(1488年——1505年)"); + king9.setTempleNumber("孝宗"); + king9.setTomb("泰陵"); + king9.setRemark(""); + + King king10 = new King(); + king10.setId(10L); + king10.setName("朱厚照"); + king10.setClan("乃朱祐樘长子(武宗无嗣,乃由旁支皇室选择朱厚熜入继大统)"); + king10.setPosthumousTitle("高皇帝"); + king10.setTimes("洪武(1368年——1398年)"); + king10.setTempleNumber("武宗"); + king10.setTomb("孝陵"); + king10.setRemark(""); + + King king11 = new King(); + king11.setId(11L); + king11.setName("朱厚熜"); + king11.setClan("乃朱见深四子兴献王朱祐杬(庶出)之嫡长子,朱祐樘从子,朱厚照从弟"); + king11.setPosthumousTitle("肃皇帝"); + king11.setTimes("嘉靖(1522年——1566年)"); + king11.setTempleNumber("世宗"); + king11.setTomb("永陵"); + king11.setRemark("大仪礼"); + + King king12 = new King(); + king12.setId(12L); + king12.setName("朱载垕"); + king12.setClan("乃朱厚熜三子(庶出)"); + king12.setPosthumousTitle("庄皇帝"); + king12.setTimes("隆庆(1567年——1572年)"); + king12.setTempleNumber("穆宗"); + king12.setTomb("昭陵"); + king12.setRemark(""); + + + King king13 = new King(); + king13.setId(13L); + king13.setName("朱翊钧"); + king13.setClan("乃朱载垕三子(庶出)"); + king13.setPosthumousTitle("显皇帝"); + king13.setTimes("万历(1573年——1620年)"); + king13.setTempleNumber("神宗"); + king13.setTomb("定陵"); + king13.setRemark(""); + + King king14 = new King(); + king14.setId(14L); + king14.setName("朱常洛"); + king14.setClan("乃朱翊钧长子"); + king14.setPosthumousTitle("贞皇帝"); + king14.setTimes("泰昌(1620年)实际在位一个月"); + king14.setTempleNumber("光宗"); + king14.setTomb("庆陵"); + king14.setRemark(""); + + + King king15 = new King(); + king15.setId(15L); + king15.setName("朱由校"); + king15.setClan("乃朱常洛长子(庶出)(熹宗死后无嗣,乃诏令五弟信王朱由检入继大统)"); + king15.setPosthumousTitle("悊皇帝"); + king15.setTimes("天启(1621年——1627年)"); + king15.setTempleNumber("熹宗"); + king15.setTomb("德陵"); + king15.setRemark(""); + + + King king16 = new King(); + king16.setId(16L); + king16.setName("朱由检"); + king16.setClan("乃朱常洛五子(庶出)(毅宗死后,明朝覆灭,宗室乃于南方割据)"); + king16.setPosthumousTitle("烈皇帝"); + king16.setTimes("崇祯(1628年——1644年)"); + king16.setTempleNumber("毅宗(原为思宗)"); + king16.setTomb("思陵"); + king16.setRemark(""); + + /** + * 初始化皇后信息 + */ + List queenList = new ArrayList<>(); + + Queen queen1 = new Queen(); + queen1.setId(101L); + queen1.setPosthumousTitle("孝慈高皇后"); + queen1.setName("马秀英"); + queen1.setRemark("安徽宿州人,早年丧母,被郭子兴夫妇收养为义女。1382年(洪武十五年)五十一岁的马皇后病逝。"); + queen1.setTimes("1368年1月-1382年"); + queen1.setSon("明兴宗朱标、秦愍王朱樉、晋恭王朱㭎、明成祖朱棣、周定王朱橚(五子皆存疑),宁国公主,安庆公主"); + queen1.setKing(king1); + + + Queen queen2 = new Queen(); + queen2.setId(102L); + queen2.setPosthumousTitle("孝愍让皇后"); + queen2.setName("马全女"); + queen2.setRemark("洪武二十八年十月,册后为皇太孙妃。建文改元,立为后。生二子,文煃、文圭。"); + queen2.setTimes("1399年-1402年"); + queen2.setSon("和简太子朱文奎,润怀王朱文圭"); + queen2.setKing(king2); + + Queen queen3 = new Queen(); + queen3.setId(103L); + queen3.setPosthumousTitle("孝文皇后"); + queen3.setName("徐氏 "); + queen3.setTimes("1402年11月-1407年"); + queen3.setSon("明仁宗朱高炽、汉王朱高煦、赵王朱高燧"); + queen3.setRemark("洪武九年(1376年)册封为燕王妃,朱棣称帝册封为皇后。永乐五年(1407年)七月四日去世,享年46岁。"); + queen3.setKing(king3); + + Queen queen4 = new Queen(); + queen4.setId(104L); + queen4.setPosthumousTitle("诚孝昭皇后"); + queen4.setName("张氏"); + queen4.setRemark("仁宗元配,永城人,指挥使赠彭城侯张麒诚孝昭皇后画像之女。洪武二十八年(1395年)封燕王世子妃,永乐二年(1404年)封皇太子妃。仁宗即位,册立为皇后。宣宗即位,尊为皇太后。英宗即位,尊为太皇太后。正统七年(1442年)十月十八日去世."); + queen4.setTimes("1424年7月-1442年"); + queen4.setSon("明宣宗朱瞻基、越靖王朱瞻墉、襄宪王朱瞻墡、嘉兴公主"); + queen4.setKing(king4); + + Queen queen5 = new Queen(); + queen5.setId(105L); + queen5.setPosthumousTitle("恭让章皇后"); + queen5.setName("胡善祥"); + queen5.setTimes("1426年-1428年"); + queen5.setSon("顺德公主"); + queen5.setRemark("皇后,后被废黜,后被追谥为恭让章皇后"); + queen5.setKing(king5); + + Queen queen51 = new Queen(); + queen51.setId(106L); + queen51.setPosthumousTitle("孝翼皇后"); + queen51.setName("吴氏"); + queen51.setSon("明代宗朱祁钰"); + queen51.setRemark("太子妾,贤妃,后成皇太后,后被废,南明追谥孝翼温惠淑慎慈仁匡天锡圣太后"); + queen51.setKing(king5); + + Queen queen52 = new Queen(); + queen52.setId(107L); + queen52.setPosthumousTitle("孝恭章皇后"); + queen52.setName("孙氏"); + queen52.setTimes("1426年-1462年"); + queen52.setSon("常德公主、明英宗(存疑)"); + queen52.setRemark(""); + queen52.setKing(king5); + + Queen queen6 = new Queen(); + queen6.setId(108L); + queen6.setPosthumousTitle("孝庄睿皇后"); + queen6.setName("钱氏"); + queen6.setTimes("1442年-1468年6月"); + queen6.setRemark("英宗元配,海州人,都指挥佥事(后封安昌伯)钱贵女。正统七年(1442年)立为皇后。宪宗即位,尊为皇太后,加“慈懿”徽号。成化四年(1468年)六月二十六日,钱氏病故。 "); + queen6.setKing(king6); + + Queen queen61 = new Queen(); + queen61.setId(109L); + queen61.setPosthumousTitle("孝肃后"); + queen61.setName("周氏"); + queen61.setTimes("1464年-1504"); + queen61.setSon("重庆公主、明宪宗朱见深、崇简王朱见泽"); + queen61.setRemark("宪宗生母,昌平州文宁里柳林村(今属北京市海淀区)人,锦衣卫千户追封庆云侯赠宁国公周能的女儿。正统十二年(1447年)生宪宗皇帝,天顺元年(1457年)册封为贵妃。宪宗即位,尊为皇太后。孝宗即位后,尊为太皇太后。弘治十七年(1504年)三月一日去世."); + queen61.setKing(king6); + + Queen queen7 = new Queen(); + queen7.setId(110L); + queen7.setPosthumousTitle("孝渊皇后"); + queen7.setName("汪氏"); + queen7.setTimes("1449年-1452年"); + queen7.setSon("固安公主、二公主(出家)"); + queen7.setRemark("北京人,祖父汪泉世为金吾左卫指挥使。正统十年(1445),郕王朱祁钰18岁,册封汪氏为郕王妃。正统十四年(1449) 册封王妃汪氏为皇后。进汪皇后祖父汪泉为都指挥同知;,汪氏去世与景帝合葬金山。"); + queen7.setKing(king7); + + Queen queen71 = new Queen(); + queen71.setId(111L); + queen71.setPosthumousTitle("肃孝皇后"); + queen71.setName("杭氏"); + queen71.setSon("怀献太子朱见济"); + queen71.setTimes("1452年-1453年"); + queen71.setRemark("妾,后为贵妃,后成皇后,后被明英宗追废"); + queen71.setKing(king7); + + Queen queen8 = new Queen(); + queen8.setId(112L); + queen8.setPosthumousTitle("皇后"); + queen8.setName("吴氏"); + queen8.setTimes("1464年7月27日-1464年8月28日"); + queen8.setSon("曾抚养明孝宗朱祐樘"); + queen8.setRemark("皇后,后被废黜,在位仅31日。为明朝在位时期最短的皇后。"); + queen8.setKing(king8); + + Queen queen81 = new Queen(); + queen81.setId(113L); + queen81.setPosthumousTitle("孝贞纯皇后"); + queen81.setName("王氏"); + queen81.setTimes("1464年10月12日-1518年2月"); + queen81.setRemark("皇后,后成皇太后"); + queen81.setKing(king8); + + + Queen queen82 = new Queen(); + queen82.setId(114L); + queen82.setPosthumousTitle("孝穆皇后"); + queen82.setName("纪氏"); + queen82.setSon("明孝宗朱祐樘"); + queen82.setRemark("宫人,后成淑妃,后被追谥孝穆皇后, 瑶族人。暴死"); + queen82.setKing(king8); + + Queen queen83 = new Queen(); + queen83.setId(115L); + queen83.setPosthumousTitle("孝惠皇后"); + queen83.setName("邵氏"); + queen83.setSon("宸妃,后成贵妃,嘉靖帝尊为寿安皇太后,后被追谥孝惠皇后"); + queen83.setRemark("宫人,后成淑妃,后被追谥孝穆皇后, 瑶族人。暴死"); + queen83.setKing(king8); + + Queen queen9 = new Queen(); + queen9.setId(116L); + queen9.setPosthumousTitle("孝成敬皇后"); + queen9.setName("张氏"); + queen9.setTimes("1486年-1541年"); + queen9.setSon("明武宗朱厚照、朱厚炜、太康公主朱秀荣"); + queen9.setRemark("皇后,后成皇伯母皇太后,追谥孝康敬皇后,后改谥孝成敬皇后,丈夫孝宗在世期间未曾册封嫔妃,是中国历史上唯一终生一夫一妻的皇帝"); + queen9.setKing(king9); + + + + Queen queen10 = new Queen(); + queen10.setId(117L); + queen10.setPosthumousTitle("孝静皇后"); + queen10.setName("夏氏"); + queen10.setTimes("1506年-1535年1月"); + queen10.setRemark("皇后,嘉靖帝尊封为皇嫂庄肃皇后"); + queen10.setKing(king10); + + + + Queen queen11 = new Queen(); + queen11.setId(118L); + queen11.setPosthumousTitle("孝洁肃皇后"); + queen11.setName("陈氏"); + queen11.setTimes("1522年-1528年10月"); + queen11.setRemark("皇后,谥悼灵皇后,后改谥孝洁恭懿慈睿安庄相天翊圣肃皇后, 受惊流产而亡"); + queen11.setKing(king11); + + Queen queen12 = new Queen(); + queen12.setId(119L); + queen12.setPosthumousTitle("孝懿庄皇后"); + queen12.setName("李氏"); + queen12.setTimes("?-1558年4月"); + queen12.setSon("宪怀太子朱翊、蓬莱公主"); + queen12.setRemark("结髪之妻,正室,后被追谥为孝懿贞惠顺哲恭仁俪天襄圣庄皇后"); + queen12.setKing(king12); + + + Queen queen121 = new Queen(); + queen121.setId(120L); + queen121.setPosthumousTitle("孝安皇后"); + queen121.setName("陈氏"); + queen121.setTimes("1567年3月-1596年7月"); + queen121.setSon("太和公主"); + queen121.setRemark("继室,后为皇后,后成皇太后,后被追谥为孝安贞懿恭纯温惠佐天弘圣皇后"); + queen121.setKing(king12); + + Queen queen13 = new Queen(); + queen13.setId(121L); + queen13.setPosthumousTitle("孝端皇后"); + queen13.setName("王喜姐"); + queen13.setTimes("1578年-1620年"); + queen13.setRemark("荣昌公主朱轩媖"); + queen13.setKing(king13); + + + Queen queen14 = new Queen(); + queen14.setId(122L); + queen14.setPosthumousTitle("孝元贞皇后"); + queen14.setName("郭氏"); + queen14.setSon("怀淑公主朱徽娟"); + queen14.setRemark("结髪之妻,正室太子妃,后被追谥为孝元昭懿哲惠庄仁合天弼圣贞皇后"); + queen14.setKing(king14); + + + Queen queen15 = new Queen(); + queen15.setId(123L); + queen15.setPosthumousTitle("孝哀悊皇后"); + queen15.setName("张氏"); + queen15.setTimes("1621年4月-1644年2月28日"); + queen15.setSon("太子朱慈燃"); + queen15.setRemark("皇后,崇祯帝尊封为皇嫂懿安皇后,南明追谥孝哀慈靖恭惠温贞偕天协圣悊皇后,明亡时自缢身亡。"); + queen15.setKing(king15); + + + Queen queen16 = new Queen(); + queen16.setId(124L); + queen16.setPosthumousTitle("孝节烈皇后"); + queen16.setName("周氏"); + queen16.setTimes("1628年-1644年2月28日"); + queen16.setSon("坤仪公主、明悼帝朱慈烺、怀隐王朱慈烜、定哀王朱慈炯"); + queen16.setRemark("结髪之妻,正室,后成皇后,清追谥为庄烈愍皇后,南明追谥孝节贞肃渊恭庄毅奉天靖圣烈皇后,自杀"); + queen16.setKing(king16); + + + queenList.add(queen1); + queenList.add(queen2); + queenList.add(queen3); + queenList.add(queen4); + queenList.add(queen5); + queenList.add(queen5); + queenList.add(queen51); + queenList.add(queen52); + + queenList.add(queen6); + queenList.add(queen61); + + queenList.add(queen7); + queenList.add(queen71); + + queenList.add(queen8); + queenList.add(queen81); + queenList.add(queen82); + queenList.add(queen83); + + queenList.add(queen9); + queenList.add(queen10); + queenList.add(queen11); + queenList.add(queen12); + queenList.add(queen121); + + queenList.add(queen13); + queenList.add(queen14); + queenList.add(queen15); + queenList.add(queen16); + + return queenList; + } +} diff --git a/springboot-neo4j/src/test/java/cn/abel/neo4j/service/KingServiceTest.java b/springboot-neo4j/src/test/java/cn/abel/neo4j/service/KingServiceTest.java new file mode 100644 index 0000000..d3066a7 --- /dev/null +++ b/springboot-neo4j/src/test/java/cn/abel/neo4j/service/KingServiceTest.java @@ -0,0 +1,56 @@ +package cn.abel.neo4j.service; + +import cn.abel.neo4j.BaseTest; +import cn.abel.neo4j.bean.King; +import cn.abel.neo4j.bean.Queen; +import cn.abel.neo4j.dao.KingDao; +import cn.abel.neo4j.dto.GraphDTO; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + + +/** + * @author yyb + * @time 2020/3/23 + */ +public class KingServiceTest extends BaseTest { + @Autowired + private KingService kingService; + @Autowired + private KingDao kingDao; + + + @Test + public void saveKing() throws Exception { + List kingList = InitData.initKing(); + kingService.saveKing(kingList); + } + + @Test + public void saveQueen() throws Exception { + List queenList = InitData.initQueen(); + kingService.saveQueen(queenList); + } + + @Test + public void saveRelation() throws Exception { + kingService.saveRelation("朱元璋", "朱棣"); + } + + @Test + public void getOneKing() throws Exception { + King king = kingService.findByName("朱棣"); + System.out.println(); + + } + + @Test + public void getKingAndQueen() throws Exception { + GraphDTO graphDTO = kingService.getKingAndQueen("朱棣"); + System.out.println(); + + } + +} \ No newline at end of file diff --git a/springboot-redis-queue/pom.xml b/springboot-redis-queue/pom.xml new file mode 100644 index 0000000..e7b6b0b --- /dev/null +++ b/springboot-redis-queue/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + cn.abel + springboot-redis-queue + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.apache.commons + commons-pool2 + + + org.springframework.boot + spring-boot-autoconfigure + + + + redis.clients + jedis + 3.0.1 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + + \ No newline at end of file diff --git a/springboot-redis-queue/src/main/java/cn/abel/queue/Application.java b/springboot-redis-queue/src/main/java/cn/abel/queue/Application.java new file mode 100644 index 0000000..287bdd7 --- /dev/null +++ b/springboot-redis-queue/src/main/java/cn/abel/queue/Application.java @@ -0,0 +1,16 @@ +package cn.abel.queue; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/8/13 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-redis-queue/src/main/java/cn/abel/queue/config/RedisConfig.java b/springboot-redis-queue/src/main/java/cn/abel/queue/config/RedisConfig.java new file mode 100644 index 0000000..371a1e9 --- /dev/null +++ b/springboot-redis-queue/src/main/java/cn/abel/queue/config/RedisConfig.java @@ -0,0 +1,161 @@ +package cn.abel.queue.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +/** + * @author yyb + * @time 2019/8/13 + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + /** + * logger + */ + private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); + @Value("${spring.redis.database}") + private Integer database; + @Value("${spring.redis.host}") + private String host; + @Value("${spring.redis.port}") + private Integer port; + @Value("${spring.redis.password}") + private String password; + @Value("${spring.redis.lettuce.pool.max-active}") + private Integer maxActive; + @Value("${spring.redis.lettuce.pool.max-wait}") + private Integer maxWait; + @Value("${spring.redis.lettuce.pool.max-idle}") + private Integer maxIdle; + @Value("${spring.redis.lettuce.pool.min-idle}") + private Integer minIdle; + @Value("${spring.redis.lettuce.shutdown-timeout}") + private Integer timeout; + + /** + * 在使用@Cacheable时,如果不指定key,则使用这个默认的key生成器生成的key + * + * @return + */ + @Override + @Bean + public KeyGenerator keyGenerator() { + return (target, method, params) -> { + StringBuilder sb = new StringBuilder(); + sb.append(target.getClass().getName()); + sb.append(method.getName()); + for (Object obj : params) { + sb.append(obj.toString()); + } + return sb.toString(); + }; + } + + @Bean(name = "redisTemplate") + public RedisTemplate redisTemplate() { + return getTemplate(redisConnectionFactory()); + } + + private RedisConnectionFactory redisConnectionFactory() { + return connectionFactory(maxActive, maxIdle, minIdle, maxWait, host, password, timeout, port, database); + } + + + /** + * 创建连接 + * + * @param maxActive + * @param maxIdle + * @param minIdle + * @param maxWait + * @param host + * @param password + * @param timeout + * @param port + * @param database + * @return + */ + private RedisConnectionFactory connectionFactory(Integer maxActive, + Integer maxIdle, + Integer minIdle, + Integer maxWait, + String host, + String password, + Integer timeout, + Integer port, + Integer database) { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(host); + redisStandaloneConfiguration.setPort(port); + redisStandaloneConfiguration.setDatabase(database); + redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); + + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + poolConfig.setMaxTotal(maxActive); + poolConfig.setMinIdle(minIdle); + poolConfig.setMaxIdle(maxIdle); + poolConfig.setMaxWaitMillis(maxWait); + LettuceClientConfiguration lettucePoolingConfig = LettucePoolingClientConfiguration.builder() + .poolConfig(poolConfig).shutdownTimeout(Duration.ofMillis(timeout)).build(); + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, + lettucePoolingConfig); + connectionFactory.afterPropertiesSet(); + + return connectionFactory; + } + + /** + * 创建 RedisTemplate 连接类型,此处为hash + * + * @param factory + * @return + */ + private RedisTemplate getTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + template.setValueSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); + + template.afterPropertiesSet(); + return template; + } + + /** + * 对value 进行序列化 + * + * @param objectMapper + * @return + */ + private Jackson2JsonRedisSerializer jackson2JsonRedisSerializer(ObjectMapper objectMapper) { + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = + new Jackson2JsonRedisSerializer<>(Object.class); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + return jackson2JsonRedisSerializer; + } +} diff --git a/springboot-redis-queue/src/main/java/cn/abel/queue/controller/PublisherController.java b/springboot-redis-queue/src/main/java/cn/abel/queue/controller/PublisherController.java new file mode 100644 index 0000000..8246841 --- /dev/null +++ b/springboot-redis-queue/src/main/java/cn/abel/queue/controller/PublisherController.java @@ -0,0 +1,35 @@ +package cn.abel.queue.controller; + +import cn.abel.queue.service.ProducerService; +import cn.abel.queue.service.ReceiverService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yyb + * @time 2019/8/13 + */ + +@RestController +@RequestMapping("/publisher") +public class PublisherController { + @Autowired + private ProducerService producerService; + @Autowired + private ReceiverService receiverService; + + @RequestMapping(value = "{name}",method = RequestMethod.GET) + public String sendMessage(@PathVariable("name") String name) { + return producerService.sendMessage(name); + } + + + @RequestMapping(value = "/get",method =RequestMethod.GET ) + public String getMessage() { + return receiverService.getMessage(); + } + +} diff --git a/springboot-redis-queue/src/main/java/cn/abel/queue/service/ProducerService.java b/springboot-redis-queue/src/main/java/cn/abel/queue/service/ProducerService.java new file mode 100644 index 0000000..469f3bb --- /dev/null +++ b/springboot-redis-queue/src/main/java/cn/abel/queue/service/ProducerService.java @@ -0,0 +1,29 @@ +package cn.abel.queue.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + + +/** + * @author yyb + * @time 2019/8/13 + */ + +@Service +public class ProducerService { + @Autowired + private StringRedisTemplate redisTemplate; + + public String sendMessage(String name) { + try { + redisTemplate.opsForList().leftPush("quere", name); + return "消息发送成功了"; + + } catch (Exception e) { + e.printStackTrace(); + return "消息发送失败了"; + } + } + +} \ No newline at end of file diff --git a/springboot-redis-queue/src/main/java/cn/abel/queue/service/ReceiverService.java b/springboot-redis-queue/src/main/java/cn/abel/queue/service/ReceiverService.java new file mode 100644 index 0000000..07fb207 --- /dev/null +++ b/springboot-redis-queue/src/main/java/cn/abel/queue/service/ReceiverService.java @@ -0,0 +1,21 @@ +package cn.abel.queue.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +/** + * @author yyb + * @time 2019/8/13 + */ +@Service +public class ReceiverService { + @Autowired + private StringRedisTemplate redisTemplate; + + public String getMessage() { + String value = redisTemplate.opsForList().rightPop("quere"); + return value; + } +} + diff --git a/springboot-redis-queue/src/main/resources/local/application.properties b/springboot-redis-queue/src/main/resources/local/application.properties new file mode 100644 index 0000000..286c930 --- /dev/null +++ b/springboot-redis-queue/src/main/resources/local/application.properties @@ -0,0 +1,52 @@ +## tomcat\u914D\u7F6E +server.port=9666 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=redis-queue +application.main=cn.abel.queue.Application + +## LOG +logging.file=./logs/redis-queue.log + + +## spring cache +#\u7F13\u5B58\u7684\u540D\u79F0\u96C6\u5408\uFF0C\u591A\u4E2A\u91C7\u7528\u9017\u53F7\u5206\u5272 +#spring.cache.cache-names=admin,role +#\u7F13\u5B58\u7684\u7C7B\u578B\uFF0C\u5B98\u65B9\u63D0\u4F9B\u4E86\u5F88\u591A\uFF0C\u8FD9\u91CC\u6211\u4EEC\u586B\u5199redis +spring.cache.type=redis +#\u662F\u5426\u7F13\u5B58null\u6570\u636E\uFF0C\u9ED8\u8BA4\u662Ffalse +#spring.cache.redis.cache-null-values=false +#redis\u4E2D\u7F13\u5B58\u8D85\u65F6\u7684\u65F6\u95F4\uFF0C\u9ED8\u8BA460000ms +#spring.cache.redis.time-to-live=60000 +#\u7F13\u5B58\u6570\u636Ekey\u662F\u5426\u4F7F\u7528\u524D\u7F00\uFF0C\u9ED8\u8BA4\u662Ftrue +#spring.cache.redis.use-key-prefix=true +#\u7F13\u5B58\u6570\u636Ekey\u7684\u524D\u7F00\uFF0C\u5728\u4E0A\u9762\u7684\u914D\u7F6E\u4E3Atrue\u65F6\u6709\u6548\uFF0C + +# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u5E93\uFF09 +spring.redis.database=2 +# Redis\u670D\u52A1\u5668\u5730\u5740 +spring.redis.host=127.0.0.1 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3 +spring.redis.port=6379 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09 +spring.redis.password= +# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-active=100 +# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-wait=1000 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.max-idle=50 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.min-idle=0 +# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09 +spring.redis.lettuce.shutdown-timeout=0 \ No newline at end of file diff --git a/springboot-redis-queue/src/main/resources/local/banner.txt b/springboot-redis-queue/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-redis-queue/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-redis-queue/src/main/resources/local/logback-spring.xml b/springboot-redis-queue/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..2e2778f --- /dev/null +++ b/springboot-redis-queue/src/main/resources/local/logback-spring.xml @@ -0,0 +1,33 @@ + + + demo + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/springboot-rocketmq-ali/pom.xml b/springboot-rocketmq-ali/pom.xml new file mode 100644 index 0000000..87feb02 --- /dev/null +++ b/springboot-rocketmq-ali/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + cn.abel + springboot-rocketmq-ali + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.apache.commons + commons-pool2 + + + org.springframework.boot + spring-boot-autoconfigure + + + + com.aliyun.openservices + ons-client + 1.8.3.Final + + + com.alibaba + fastjson + 1.2.58 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + + \ No newline at end of file diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/Application.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/Application.java new file mode 100644 index 0000000..287bdd7 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/Application.java @@ -0,0 +1,16 @@ +package cn.abel.queue; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/8/13 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiConsumerClient.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiConsumerClient.java new file mode 100644 index 0000000..ebb5b66 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiConsumerClient.java @@ -0,0 +1,79 @@ +package cn.abel.queue.config; + +import cn.abel.queue.service.MessageHandler; +import com.aliyun.openservices.ons.api.MessageListener; +import com.aliyun.openservices.ons.api.PropertyKeyConst; +import com.aliyun.openservices.ons.api.bean.ConsumerBean; +import com.aliyun.openservices.ons.api.bean.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * @author yyb + * @time 2020/3/25 + */ + +@Configuration +public class ALiConsumerClient { + private static final Logger logger = LoggerFactory.getLogger(ALiConsumerClient.class); + /** + * topic tag。 + */ + private static final String TOPIC_TAG = "*"; + /** + * 消费者线程数。 + */ + private static final int CONSUMER_THREAD_COUNT = 10; + /** + * 重新消费次数。 + */ + private static final int RECONSUME_TIMES = 2; + + private MessageHandler handler; + + @Value("${ali.rocket.mq.access-key}") + private String accessKey; + @Value("${ali.rocket.mq.secret-key}") + private String secretKey; + @Value("${ali.rocket.mq.name-srv-addr}") + private String nameSrvAddr; + @Value("${ali.rocket.mq.test-topic}") + private String topic; + @Value("${ali.rocket.mq.test-group-id}") + private String group; + + @Bean(initMethod = "start", destroyMethod = "shutdown") + public ConsumerBean buildConsumer() { + ConsumerBean consumerBean = new ConsumerBean(); + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.AccessKey, accessKey); + properties.setProperty(PropertyKeyConst.SecretKey, secretKey); + properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, nameSrvAddr); + properties.setProperty(PropertyKeyConst.GROUP_ID, group); + properties.setProperty(PropertyKeyConst.ConsumeThreadNums, String.valueOf(CONSUMER_THREAD_COUNT)); + properties.setProperty(PropertyKeyConst.MaxReconsumeTimes, String.valueOf(RECONSUME_TIMES)); + consumerBean.setProperties(properties); + + Map subscriptionTable = new HashMap<>(); + Subscription subscription = new Subscription(); + subscription.setTopic(topic); + subscription.setExpression(TOPIC_TAG); + subscriptionTable.put(subscription, handler); + consumerBean.setSubscriptionTable(subscriptionTable); + logger.info("初始化rocketMq完成 config:{}"); + return consumerBean; + } + + @Autowired + public ALiConsumerClient(MessageHandler handler) { + this.handler = handler; + } +} diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiMqConfig.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiMqConfig.java new file mode 100644 index 0000000..3fb00d8 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiMqConfig.java @@ -0,0 +1,79 @@ +package cn.abel.queue.config; + +import com.aliyun.openservices.ons.api.PropertyKeyConst; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.Properties; + +/** + * @author yyb + * @time 2020/3/25 + */ +@Component +@ConfigurationProperties(prefix = "ali.rocket.mq") +public class ALiMqConfig { + private String accessKey; + private String secretKey; + private String nameSrvAddr; + private String testTopic; + private String testGroupId; + private String testTag; + + public Properties getMqProperties() { + Properties properties = new Properties(); + properties.setProperty(PropertyKeyConst.AccessKey, this.accessKey); + properties.setProperty(PropertyKeyConst.SecretKey, this.secretKey); + properties.setProperty(PropertyKeyConst.GROUP_ID, testGroupId); + properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr); + return properties; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getNameSrvAddr() { + return nameSrvAddr; + } + + public void setNameSrvAddr(String nameSrvAddr) { + this.nameSrvAddr = nameSrvAddr; + } + + public String getTestTopic() { + return testTopic; + } + + public void setTestTopic(String testTopic) { + this.testTopic = testTopic; + } + + public String getTestGroupId() { + return testGroupId; + } + + public void setTestGroupId(String testGroupId) { + this.testGroupId = testGroupId; + } + + public String getTestTag() { + return testTag; + } + + public void setTestTag(String testTag) { + this.testTag = testTag; + } +} diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiProducerClient.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiProducerClient.java new file mode 100644 index 0000000..c81c137 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiProducerClient.java @@ -0,0 +1,28 @@ +package cn.abel.queue.config; + +import com.aliyun.openservices.ons.api.bean.ProducerBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +/** + * @author yyb + * @time 2020/3/25 + */ +@Component +public class ALiProducerClient { + @Autowired + private ALiMqConfig aLiMqConfig; + + @Bean(name = "producer", initMethod = "start", destroyMethod = "shutdown") + public ProducerBean build() { + ProducerBean bean = new ProducerBean(); + bean.setProperties(aLiMqConfig.getMqProperties()); + return bean; + } + + @Autowired + public ALiProducerClient(ALiMqConfig aLiMqConfig) { + this.aLiMqConfig = aLiMqConfig; + } +} \ No newline at end of file diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/MessageHandler.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/MessageHandler.java new file mode 100644 index 0000000..7dcca53 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/MessageHandler.java @@ -0,0 +1,30 @@ +package cn.abel.queue.service; + +import com.aliyun.openservices.ons.api.Action; +import com.aliyun.openservices.ons.api.ConsumeContext; +import com.aliyun.openservices.ons.api.Message; +import com.aliyun.openservices.ons.api.MessageListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; + +/** + * @author yyb + * @time 2020/3/25 + */ +@Component +public class MessageHandler implements MessageListener { + private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class); + + @Override + public Action consume(Message message, ConsumeContext consumeContext) { + String msgStr = new String(message.getBody(), StandardCharsets.UTF_8); + //接收到消息 + logger.info("Receive message msgId:{} retryTimes:{} body:{}", message.getMsgID(), + message.getReconsumeTimes(), msgStr); + //提交 + return Action.CommitMessage; + } +} diff --git a/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/ProducerService.java b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/ProducerService.java new file mode 100644 index 0000000..17e70c1 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/ProducerService.java @@ -0,0 +1,67 @@ +package cn.abel.queue.service; + +import cn.abel.queue.config.ALiMqConfig; +import com.alibaba.fastjson.JSON; +import com.aliyun.openservices.ons.api.Message; +import com.aliyun.openservices.ons.api.OnExceptionContext; +import com.aliyun.openservices.ons.api.SendCallback; +import com.aliyun.openservices.ons.api.SendResult; +import com.aliyun.openservices.ons.api.bean.ProducerBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; +import java.util.function.Predicate; + + +/** + * @author yyb + * @time 2019/8/13 + */ + +@Service +public class ProducerService { + private static final Logger logger = LoggerFactory.getLogger(ProducerService.class); + + @Autowired + private ALiMqConfig aLiMqConfig; + @Autowired + private ProducerBean producer; + + + /** + * 调用此方法 发送消息,o 为自定义的消息体 + */ + public void sendMessage(Object o) { + Message message = new Message(aLiMqConfig.getStockTopic(), "test", JSON.toJSON(o).toString().getBytes(StandardCharsets.UTF_8)); + //向mq发送消息 + sendAsync(ProducerBean::isStarted, producer, message); + } + + /** + * 向阿里云rocket mq发送消息。 + * + * @param predicate 断言 + * @param bean 发送消息bean + * @param message 需要发送的消息 + */ + private static void sendAsync(Predicate predicate, ProducerBean bean, Message message) { + if (predicate.test(bean)) { + bean.sendAsync(message, new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + logger.info("向mq推送库存消息成功,消息是:{}", sendResult.toString()); + } + @Override + public void onException(OnExceptionContext e) { + logger.error("向mq推送库存消息失败,消息id 为 {} 错误是:{}", e.getMessageId(), e.getException().getMessage()); + } + }); + } else { + logger.error("mq库存生产端启动失败!!!消息是:{}", message.toString()); + } + } + +} \ No newline at end of file diff --git a/springboot-rocketmq-ali/src/main/resources/local/application.properties b/springboot-rocketmq-ali/src/main/resources/local/application.properties new file mode 100644 index 0000000..c815b81 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/resources/local/application.properties @@ -0,0 +1,28 @@ +## tomcat\u914D\u7F6E +server.port=9666 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=rocketmq-ali-queue +application.main=cn.abel.queue.Application + +## LOG +logging.file=./logs/rocketmq-queue-ali.log + + +# rocket mq +ali.rocket.mq.access-key=xxxxx +ali.rocket.mq.secret-key=xxxxxx +ali.rocket.mq.name-srv-addr=127.0.0.1:9876 +ali.rocket.mq.test-topic=mq_test +ali.rocket.mq.test-group-id=test +ali.rocket.mq.test-tag= \ No newline at end of file diff --git a/springboot-rocketmq-ali/src/main/resources/local/banner.txt b/springboot-rocketmq-ali/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-rocketmq-ali/src/main/resources/local/logback-spring.xml b/springboot-rocketmq-ali/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..1f021e4 --- /dev/null +++ b/springboot-rocketmq-ali/src/main/resources/local/logback-spring.xml @@ -0,0 +1,33 @@ + + + springboot-rocketmq-ali + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/springboot-rocketmq/pom.xml b/springboot-rocketmq/pom.xml new file mode 100644 index 0000000..af5a513 --- /dev/null +++ b/springboot-rocketmq/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + cn.abel + springboot-rocketmq + 1.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.apache.commons + commons-pool2 + + + org.springframework.boot + spring-boot-autoconfigure + + + + org.apache.rocketmq + rocketmq-client + 4.3.0 + + + org.codehaus.groovy + groovy + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + true + + + + + \ No newline at end of file diff --git a/springboot-rocketmq/src/main/java/cn/abel/queue/Application.java b/springboot-rocketmq/src/main/java/cn/abel/queue/Application.java new file mode 100644 index 0000000..287bdd7 --- /dev/null +++ b/springboot-rocketmq/src/main/java/cn/abel/queue/Application.java @@ -0,0 +1,16 @@ +package cn.abel.queue; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author yyb + * @time 2019/8/13 + */ +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-rocketmq/src/main/java/cn/abel/queue/config/JmsConfig.java b/springboot-rocketmq/src/main/java/cn/abel/queue/config/JmsConfig.java new file mode 100644 index 0000000..d5d4695 --- /dev/null +++ b/springboot-rocketmq/src/main/java/cn/abel/queue/config/JmsConfig.java @@ -0,0 +1,16 @@ +package cn.abel.queue.config; + +/** + * @author yyb + * @time 2019/11/26 + */ +public class JmsConfig { + /** + * Name Server 地址,因为是集群部署 所以有多个用 分号 隔开 + */ + public static final String NAME_SERVER = "10.33.20.223:9876"; + /** + * 主题名称 主题一般是服务器设置好 而不能在代码里去新建topic( 如果没有创建好,生产者往该主题发送消息 会报找不到topic错误) + */ + public static final String TOPIC = "stock_change"; +} diff --git a/springboot-rocketmq/src/main/java/cn/abel/queue/controller/PublisherController.java b/springboot-rocketmq/src/main/java/cn/abel/queue/controller/PublisherController.java new file mode 100644 index 0000000..3731621 --- /dev/null +++ b/springboot-rocketmq/src/main/java/cn/abel/queue/controller/PublisherController.java @@ -0,0 +1,57 @@ +package cn.abel.queue.controller; + +import cn.abel.queue.config.JmsConfig; +import cn.abel.queue.service.ProducerService; +import cn.abel.queue.service.ReceiverService; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yyb + * @time 2019/8/13 + */ + +@RestController +@RequestMapping("/publisher") +public class PublisherController { + @Autowired + private ProducerService producerService; + @Autowired + private ReceiverService receiverService; + + private List mesList; + + /** + * 初始化消息 + */ + public PublisherController() { + mesList = new ArrayList<>(); + mesList.add("小小"); + mesList.add("爸爸"); + mesList.add("妈妈"); + mesList.add("爷爷"); + mesList.add("奶奶"); + + } + + @RequestMapping("/text/rocketmq") + public Object callback() throws Exception { + //总共发送五次消息 + for (String s : mesList) { + //创建生产信息 + Message message = new Message(JmsConfig.TOPIC, "testtag", ("小小一家人的称谓:" + s).getBytes()); + //发送 + SendResult sendResult = producerService.getProducer().send(message); + System.out.println(String.format("输出生产者信息={ %s }",sendResult)); + } + return "成功"; + } +} diff --git a/springboot-rocketmq/src/main/java/cn/abel/queue/service/ProducerService.java b/springboot-rocketmq/src/main/java/cn/abel/queue/service/ProducerService.java new file mode 100644 index 0000000..a7a69dc --- /dev/null +++ b/springboot-rocketmq/src/main/java/cn/abel/queue/service/ProducerService.java @@ -0,0 +1,50 @@ +package cn.abel.queue.service; + +import cn.abel.queue.config.JmsConfig; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + + +/** + * @author yyb + * @time 2019/8/13 + */ + +@Service +@Component +public class ProducerService { + private String producerGroup = "test_producer"; + private DefaultMQProducer producer; + + public ProducerService(){ + //示例生产者 + producer = new DefaultMQProducer(producerGroup); + //不开启vip通道 开通口端口会减2 + producer.setVipChannelEnabled(false); + //绑定name server + producer.setNamesrvAddr(JmsConfig.NAME_SERVER); + start(); + } + /** + * 对象在使用之前必须要调用一次,只能初始化一次 + */ + public void start(){ + try { + this.producer.start(); + } catch (MQClientException e) { + e.printStackTrace(); + } + } + + public DefaultMQProducer getProducer(){ + return this.producer; + } + /** + * 一般在应用上下文,使用上下文监听器,进行关闭 + */ + public void shutdown(){ + this.producer.shutdown(); + } +} \ No newline at end of file diff --git a/springboot-rocketmq/src/main/java/cn/abel/queue/service/ReceiverService.java b/springboot-rocketmq/src/main/java/cn/abel/queue/service/ReceiverService.java new file mode 100644 index 0000000..3e6095e --- /dev/null +++ b/springboot-rocketmq/src/main/java/cn/abel/queue/service/ReceiverService.java @@ -0,0 +1,61 @@ +package cn.abel.queue.service; + +import cn.abel.queue.config.JmsConfig; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.Message; +import org.springframework.stereotype.Service; + +import java.io.UnsupportedEncodingException; + +/** + * @author yyb + * @time 2019/8/13 + */ +@Service +public class ReceiverService { + /** + * 消费者实体对象 + */ + private DefaultMQPushConsumer consumer; + /** + * 消费者组 + */ + public static final String CONSUMER_GROUP = "test_consumer"; + /** + * 通过构造函数 实例化对象 + */ + public ReceiverService() throws MQClientException { + + consumer = new DefaultMQPushConsumer(CONSUMER_GROUP); + consumer.setNamesrvAddr(JmsConfig.NAME_SERVER); + //消费模式:一个新的订阅组第一次启动从队列的最后位置开始消费 后续再启动接着上次消费的进度开始消费 + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); + //订阅主题和 标签( * 代表所有标签)下信息 + consumer.subscribe(JmsConfig.TOPIC, "*"); + // //注册消费的监听 并在此监听中消费信息,并返回消费的状态信息 + consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> { + // msgs中只收集同一个topic,同一个tag,并且key相同的message + // 会把不同的消息分别放置到不同的队列中 + try { + for (Message msg : msgs) { + + //消费者获取消息 这里只输出 不做后面逻辑处理 + String body = new String(msg.getBody(), "utf-8"); + System.out.println(String.format("Consumer-获取消息-主题topic为={ %s }, 消费消息为={ %s }", msg.getTopic(), body)); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + }); + + consumer.start(); + System.out.println("消费者 启动成功======="); + } +} + diff --git a/springboot-rocketmq/src/main/resources/local/application.properties b/springboot-rocketmq/src/main/resources/local/application.properties new file mode 100644 index 0000000..45a7d43 --- /dev/null +++ b/springboot-rocketmq/src/main/resources/local/application.properties @@ -0,0 +1,21 @@ +## tomcat\u914D\u7F6E +server.port=9666 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=rocketmq-queue +application.main=cn.abel.queue.Application + +## LOG +logging.file=./logs/rocketmq-queue.log + + diff --git a/springboot-rocketmq/src/main/resources/local/banner.txt b/springboot-rocketmq/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-rocketmq/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-rocketmq/src/main/resources/local/logback-spring.xml b/springboot-rocketmq/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..2e2778f --- /dev/null +++ b/springboot-rocketmq/src/main/resources/local/logback-spring.xml @@ -0,0 +1,33 @@ + + + demo + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/springboot-shiro/pom.xml b/springboot-shiro/pom.xml index f48819e..e953479 100644 --- a/springboot-shiro/pom.xml +++ b/springboot-shiro/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.us - shiro + com.abel-shiro + springboot-shiro 1.0-SNAPSHOT @@ -87,7 +87,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-shiro2/README.md b/springboot-shiro2/README.md new file mode 100644 index 0000000..8fe9437 --- /dev/null +++ b/springboot-shiro2/README.md @@ -0,0 +1,6 @@ +##springboot-shior2 + +是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换 + +springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 +引入了 abel-user-api 模块 \ No newline at end of file diff --git a/springboot-shiro2/pom.xml b/springboot-shiro2/pom.xml new file mode 100644 index 0000000..8a3a9eb --- /dev/null +++ b/springboot-shiro2/pom.xml @@ -0,0 +1,142 @@ + + + 4.0.0 + + cn.abel + abel-parent + 1.0.0-SNAPSHOT + + + cn.abel + springboot-shior2 + 1.0.0 + jar + Spring Boot + + + + cn.abel + abel-util + 1.0.0-SNAPSHOT + + + + cn.abel + abel-user-api + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-quartz + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-freemarker + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.apache.commons + commons-pool2 + + + org.apache.commons + commons-collections4 + + + + com.alibaba + fastjson + + + + com.alibaba + dubbo + + + org.slf4j + log4j-over-slf4j + + + org.apache.zookeeper + zookeeper + + + + + org.apache.shiro + shiro-spring + + + org.apache.shiro + shiro-ehcache + + + org.apache.shiro + shiro-quartz + + + org.apache.shiro + shiro-ehcache + + + net.mingsoft + shiro-freemarker-tags + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + 2.9.9.1 + + + + com.fasterxml.jackson.core + jackson-core + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java b/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java new file mode 100644 index 0000000..0f1102c --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java @@ -0,0 +1,19 @@ +package cn.abel.rest; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.context.annotation.ImportResource; + +/** + * 无数据库运行 + * + */ +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@ImportResource("classpath*:META-INF/spring/*.xml") +public class ShiroRestApplication { + + public static void main(String[] args) { + SpringApplication.run(ShiroRestApplication.class, args); + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java b/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java new file mode 100644 index 0000000..821e775 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java @@ -0,0 +1,199 @@ +package cn.abel.rest.config; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +import cn.abel.rest.constants.Constants; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis缓存配置 + * + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); + /** + * serializer + */ + private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); + + @Value("${spring.redis.database}") + private Integer database; + @Value("${spring.redis.host}") + private String host; + @Value("${spring.redis.port}") + private Integer port; + @Value("${spring.redis.password}") + private String password; + @Value("${spring.redis.lettuce.pool.max-active}") + private Integer maxActive; + @Value("${spring.redis.lettuce.pool.max-wait}") + private Integer maxWait; + @Value("${spring.redis.lettuce.pool.max-idle}") + private Integer maxIdle; + @Value("${spring.redis.lettuce.pool.min-idle}") + private Integer minIdle; + @Value("${spring.redis.lettuce.shutdown-timeout}") + private Integer timeout; + + /** + * 在使用@Cacheable时,如果不指定key,则使用这个默认的key生成器生成的key + * + * @return + */ + @Override + @Bean + public KeyGenerator keyGenerator() { + return (target, method, params) -> { + StringBuilder sb = new StringBuilder(); + sb.append(target.getClass().getName()); + sb.append(method.getName()); + for (Object obj : params) { + sb.append(obj.toString()); + } + return sb.toString(); + }; + } + + /** + * 声明缓存管理器 + */ + @Override + @Bean + public CacheManager cacheManager() { + //1. entryTtl: 定义默认的cache time-to-live. + //2. disableCachingNullValues: 禁止缓存Null对象. 视需求而定. + //3. computePrefixWith: 此处定义了cache key的前缀, 避免公司不同项目之间的key名称冲突. + //4. serializeKeysWith, serializeValuesWith: 定义key和value的序列化协议, 同时的hash key和hash value也被定义. + + // 缓存配置 + RedisCacheConfiguration cacheConfiguration = + RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues().computePrefixWith(cacheName -> Constants.REDIS_KEY_PRE.concat(":").concat(cacheName).concat(":")).entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT)); + + Map redisCacheConfigurationMap = new HashMap<>(2); + //redisCacheConfigurationMap.put(Constants.CACHE_NAME_PERMISSION, permissionCacheConfiguration); + + //初始化一个RedisCacheWriter + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()); + + RedisSerializationContext.SerializationPair valuePair = + RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER); + //RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); + RedisCacheConfiguration defaultCacheConfig = + RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(valuePair); + //设置默认过期时间是1天 + defaultCacheConfig.entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT)); + + //初始化RedisCacheManager + RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, + redisCacheConfigurationMap); + cacheManager.afterPropertiesSet(); + logger.info("RedisCacheManager config success"); + + return cacheManager; + } + + @Bean(name = "redisTemplate") + @Primary + public RedisTemplate redisTemplate() { + return getTemplate(redisConnectionFactory()); + } + + @Bean(name = "stringRedisTemplate") + public StringRedisTemplate stringRedisTemplate() { + return new StringRedisTemplate(redisConnectionFactory()); + } + + private RedisConnectionFactory redisConnectionFactory() { + return connectionFactory(maxActive, maxIdle, minIdle, maxWait, host, password, timeout, port, database); + } + + private RedisConnectionFactory connectionFactory(Integer maxActive, + Integer maxIdle, + Integer minIdle, + Integer maxWait, + String host, + String password, + Integer timeout, + Integer port, + Integer database) { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(host); + redisStandaloneConfiguration.setPort(port); + redisStandaloneConfiguration.setDatabase(database); + redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); + + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); + poolConfig.setMaxTotal(maxActive); + poolConfig.setMaxIdle(maxIdle); + poolConfig.setMinIdle(minIdle); + poolConfig.setMaxWaitMillis(maxWait); + LettuceClientConfiguration lettucePoolingConfig = LettucePoolingClientConfiguration.builder() + //.commandTimeout(Duration.ofSeconds(15)) + .poolConfig(poolConfig).shutdownTimeout(Duration.ofMillis(timeout)).build(); + LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, + lettucePoolingConfig); + connectionFactory.afterPropertiesSet(); + + return connectionFactory; + } + + private RedisTemplate getTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + template.setKeySerializer(STRING_SERIALIZER); + template.setValueSerializer(jackson2JsonRedisSerializer()); + //不能用stringSerializer,有地方使用ShiroUser做key,不能转换 + //template.setHashKeySerializer(STRING_SERIALIZER); + //template.setHashKeySerializer(jackson2JsonRedisSerializer()); + + template.afterPropertiesSet(); + + return template; + } + + private RedisSerializer jackson2JsonRedisSerializer() { + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = + new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(objectMapper); + return jackson2JsonRedisSerializer; + } + +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/constants/Constants.java b/springboot-shiro2/src/main/java/cn/abel/rest/constants/Constants.java new file mode 100644 index 0000000..07702de --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/constants/Constants.java @@ -0,0 +1,19 @@ +package cn.abel.rest.constants; + + +public interface Constants { + + /** + * 第三方登录的token。 + */ + String THIRD_PARTY_ACCESS_TOKEN_NAME = "accessToken"; + + /** 用户注册和绑定时的ip */ + String CLIENT_IP = "127.0.0.1"; + /** redis缓存 key前缀 */ + String REDIS_KEY_PRE = "abel-user"; + /** 超时时间(天) */ + long REDIS_TIMEOUT = 10L; + + +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/controller/LoginController.java b/springboot-shiro2/src/main/java/cn/abel/rest/controller/LoginController.java new file mode 100644 index 0000000..33d6b5f --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/controller/LoginController.java @@ -0,0 +1,82 @@ +package cn.abel.rest.controller; +import cn.abel.response.ResponseEntity; +import cn.abel.rest.shiro.ShiroUser; +import cn.abel.user.models.User; +import cn.abel.user.service.PermissionService; +import cn.abel.user.service.RoleService; +import cn.abel.user.service.UserService; +import com.alibaba.dubbo.config.annotation.Reference; +import com.google.common.collect.Sets; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * @author yyb + * @time 2020/3/6 + */ +@RestController +@CrossOrigin +@RequestMapping("/") +public class LoginController { + + private static final Logger logger = LoggerFactory.getLogger(LoginController.class); + + @Reference + private UserService userService; + + + /** + * @return + */ + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ResponseEntity login() { + //TODO:登录日志。 + ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal(); + user.setToken(SecurityUtils.getSubject().getSession().getId().toString()); + return ResponseEntity.ok(user); + } + + /** + * 获取当前登录人的登录信息,包括拥有的角色、权限等。 + * + * @return + */ + @GetMapping("/logininfo") + public ResponseEntity loginInfo() { + ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal(); + + Map map = new HashMap<>(); + Set permissions = Sets.newHashSet(); + //TODO 获取当前用户所有的权限和角色 + User user = userService.getById(shiroUser.getUserId().intValue()); + map.put("roleList", user.getRoles()); + map.put("permissionList", permissions); + map.put("userId", shiroUser.getUserId()); + map.put("username", shiroUser.getLoginName()); + + return ResponseEntity.ok(map); + } + + + /** + * 注销 + * @return + */ + @PostMapping("/logout") + public ResponseEntity logout() { + Subject subject = SecurityUtils.getSubject(); + subject.logout(); + return ResponseEntity.ok(); + } + + +} + + diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultErrorController.java b/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultErrorController.java new file mode 100644 index 0000000..c4a5f15 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultErrorController.java @@ -0,0 +1,59 @@ +package cn.abel.rest.exception; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; +import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.servlet.ModelAndView; + +/** + * 404 覆盖默认error处理方法(不设置则在根目录查找error页面) + * + */ +@Controller +public class DefaultErrorController extends BasicErrorController { + + public DefaultErrorController(ServerProperties serverProperties) { + super(new DefaultErrorAttributes(), serverProperties.getError()); + } + + /** + * 覆盖默认的Json响应 + */ + @Override + public ResponseEntity> error(HttpServletRequest request) { + Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); + HttpStatus status = getStatus(request); + + //输出自定义的Json格式 + Map map = new HashMap<>(2); + map.put("status", false); + map.put("msg", body.get("message")); + + return new ResponseEntity<>(map, status); + } + + /** + * 覆盖默认的HTML响应 + */ + @Override + public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { + //请求的状态 + HttpStatus status = getStatus(request); + response.setStatus(getStatus(request).value()); + + Map model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); + ModelAndView modelAndView = resolveErrorView(request, response, status, model); + //指定自定义的视图 + return (modelAndView == null ? new ModelAndView("error/error", model) : modelAndView); + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultExceptionHandler.java b/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultExceptionHandler.java new file mode 100644 index 0000000..c9f645f --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultExceptionHandler.java @@ -0,0 +1,142 @@ +package cn.abel.rest.exception; + +import cn.abel.exception.ServiceException; +import cn.abel.response.ResponseEntity; +import org.apache.shiro.authz.UnauthorizedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.ui.Model; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.context.request.NativeWebRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.ConstraintViolationException; + +/** + * 统一异常处理 + * + */ +@ControllerAdvice +public class DefaultExceptionHandler { + + /** + * logger + */ + private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionHandler.class); + + private static final String ERROR_500 = "error/500"; + private static final String ERROR_403 = "error/403"; + private static final int ARG_ERROR_CODE = 400; + + + /** + * 参数验证异常。 + * + * @param ex + * @return + */ + @ResponseBody + @ResponseStatus(HttpStatus.OK) + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException( + HttpServletRequest request, + HttpServletResponse response, + MethodArgumentNotValidException ex) { + String errMsg = null; + if (ex.getBindingResult() != null && ex.getBindingResult().hasErrors()) { + errMsg = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage(); + } + return ResponseEntity.error(ARG_ERROR_CODE, errMsg); + } + + + /** + * 参数验证异常。 + * + * @param ex + * @return + */ + @ResponseBody + @ResponseStatus(HttpStatus.OK) + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity handleConstraintViolationException( + HttpServletRequest request, + HttpServletResponse response, + ConstraintViolationException ex) { + String errMsg = ((ConstraintViolationException) ex).getConstraintViolations() + .iterator().next().getMessage(); + return ResponseEntity.error(ARG_ERROR_CODE, errMsg); + } + + + /** + * ServiceException异常 + * + * @param exception + * @return + */ + @ExceptionHandler({ServiceException.class}) + @ResponseStatus(HttpStatus.OK) + public String processServiceException(Exception exception, Model model) { + model.addAttribute("exception", exception.getMessage()); + logger.error("rpc接口调用异常。{}", exception.getMessage()); + return ERROR_500; + } + + /** + * 没有权限 异常 + *

+ * 后续根据不同的需求定制即可 + * 应用到所有@RequestMapping注解的方法,在其抛出UnauthorizedException异常时执行 + * + * @param request + * @param e + * @return + */ + @ExceptionHandler({UnauthorizedException.class}) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public String processUnauthorizedException(NativeWebRequest request, Model model, UnauthorizedException e) { + model.addAttribute("exception", e.getMessage()); + logger.error("权限异常。{}", e.getMessage()); + return ERROR_403; + } + + /** + * 运行时异常 + * + * @param exception + * @return + */ + @ExceptionHandler({RuntimeException.class}) + @ResponseStatus(HttpStatus.OK) + public String processException(RuntimeException exception, Model model) { + model.addAttribute("exception", exception.getMessage()); + logger.error("程序异常", exception); + return ERROR_500; + } + + /** + * Exception异常 + * + * @param exception + * @return + */ + @ExceptionHandler({Exception.class}) + @ResponseStatus(HttpStatus.OK) + public String processException(Exception exception, Model model) { + model.addAttribute("exception", exception.getMessage()); + logger.error("程序异常", exception); + return ERROR_500; + //logger.info("自定义异常处理-Exception"); + //ModelAndView m = new ModelAndView(); + //m.addObject("exception", exception.getMessage()); + //m.setViewName("error/500"); + //return m; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/CustomFreeMarkerView.java b/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/CustomFreeMarkerView.java new file mode 100644 index 0000000..b0d9929 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/CustomFreeMarkerView.java @@ -0,0 +1,29 @@ +package cn.abel.rest.freemarker; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.servlet.view.freemarker.FreeMarkerView; + +/** + * freemarker全局变量 + * + * @date 2018/08/12 17:06 + */ +public class CustomFreeMarkerView extends FreeMarkerView { + + private static final String CONTEXT_PATH = "base"; + + @Override + protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { + String scheme = request.getScheme(); + String serverName = request.getServerName(); + int port = request.getServerPort(); + String path = request.getContextPath(); + String basePath = scheme + "://" + serverName + ":" + port + path; + model.put(CONTEXT_PATH, basePath); + + super.exposeHelpers(model, request); + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/FreeMarkerConfig.java b/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/FreeMarkerConfig.java new file mode 100644 index 0000000..c290e63 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/freemarker/FreeMarkerConfig.java @@ -0,0 +1,38 @@ +package cn.abel.rest.freemarker; + +import javax.annotation.PostConstruct; + +import com.jagregory.shiro.freemarker.ShiroTags; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; + +/** + * freemarker配置 + * + * @date 2018/08/13 11:43 + */ +@Configuration +public class FreeMarkerConfig { + + @Autowired + freemarker.template.Configuration config; + @Autowired + FreeMarkerViewResolver resolver; + @Autowired + InternalResourceViewResolver springResolver; + + @PostConstruct + public void setSharedVariable() { + config.setNumberFormat("0.##"); + config.setDateFormat("yyyy/MM/dd"); + config.setDateTimeFormat("yyyy-MM-dd HH:mm:ss"); + + //自定义视图变量和方法 + resolver.setViewClass(CustomFreeMarkerView.class); + + //shiro标签 + config.setSharedVariable("shiro", new ShiroTags()); + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/HttpHeaderSessionManager.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/HttpHeaderSessionManager.java new file mode 100644 index 0000000..0e680aa --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/HttpHeaderSessionManager.java @@ -0,0 +1,27 @@ +package cn.abel.rest.shiro; + +import org.apache.shiro.web.servlet.ShiroHttpServletRequest; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.apache.shiro.web.util.WebUtils; +import org.springframework.util.StringUtils; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.Serializable; + +public class HttpHeaderSessionManager extends DefaultWebSessionManager { + public static final String LOGIN_TOKEN_KEY = "sid"; + private static final String REFERENCED_SESSION_ID_SOURCE = "header"; + + @Override + protected Serializable getSessionId(ServletRequest request, ServletResponse response) { + String id = WebUtils.toHttp(request).getHeader(LOGIN_TOKEN_KEY); + if (!StringUtils.isEmpty(id)) { + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id); + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); + return id; + } + return null; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/RedisSessionDao.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/RedisSessionDao.java new file mode 100644 index 0000000..742e36f --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/RedisSessionDao.java @@ -0,0 +1,99 @@ +package cn.abel.rest.shiro; + +import java.io.Serializable; + +import javax.servlet.http.HttpServletRequest; + +import cn.abel.rest.utils.ServletKit; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.session.Session; +import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 重写SessionDAO,实现session的CRUD功能 + * + * @date 2019/02/22 14:06 + */ +public class RedisSessionDao extends EnterpriseCacheSessionDAO { + + /** logger */ + private static final Logger logger = LoggerFactory.getLogger(RedisSessionDao.class); + + private Cache cache() { + Cache cache = getCacheManager().getCache(this.getClass().getName()); + return cache; + } + + /** + * 创建session,保存到数据库 + * + * @param session + * @return + */ + @Override + protected Serializable doCreate(Session session) { + Serializable sessionId = super.doCreate(session); + cache().put(sessionId.toString(), session); + return sessionId; + } + + /** + * 获取session + * + * @param sessionId + * @return + */ + @Override + protected Session doReadSession(Serializable sessionId) { + Session session = null; + HttpServletRequest request = ServletKit.getRequest(); + if (request != null) { + String uri = request.getServletPath(); + if (ServletKit.isStaticFile(uri)) { + return null; + } + session = (Session) request.getAttribute("session_" + sessionId); + } + if (session == null) { + session = super.doReadSession(sessionId); + } + if (session == null) { + session = (Session) cache().get(sessionId.toString()); + } + return session; + } + + /** + * 更新session的最后一次访问时间 + * + * @param session + */ + @Override + protected void doUpdate(Session session) { + HttpServletRequest request = ServletKit.getRequest(); + if (request != null) { + String uri = request.getServletPath(); + if (ServletKit.isStaticFile(uri)) { + return; + } + } + + super.doUpdate(session); + cache().put(session.getId().toString(), session); + + logger.debug("{}", session.getAttribute("shiroUserId")); + } + + /** + * 删除session + * + * @param session + */ + @Override + protected void doDelete(Session session) { + super.doDelete(session); + cache().remove(session.getId().toString()); + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroConfig.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroConfig.java new file mode 100644 index 0000000..690d502 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroConfig.java @@ -0,0 +1,299 @@ +package cn.abel.rest.shiro; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.Filter; + +import cn.abel.rest.shiro.ext.QuartzSessionValidationScheduler; +import cn.abel.rest.shiro.credentials.RetryLimitHashedCredentialsMatcher; +import cn.abel.rest.shiro.filter.ShiroFormAuthenticationFilter; +import cn.abel.rest.shiro.filter.ShiroLogoutFilter; +import org.apache.shiro.authc.credential.CredentialsMatcher; +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.codec.Base64; +import org.apache.shiro.mgt.RememberMeManager; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.realm.Realm; +import org.apache.shiro.session.mgt.SessionValidationScheduler; +import org.apache.shiro.session.mgt.eis.SessionDAO; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.CookieRememberMeManager; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.Cookie; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.beans.factory.config.MethodInvokingFactoryBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; + + +/** + * @date 2018/08/07 23:43 + */ +@Configuration +public class ShiroConfig { + public final static String SHIRO_REALM_NAME = "shiroRealm"; + + /** + * shiro的Web过滤器 + * + * @param securityManager + * @return + */ + @Bean(name = "shiroFilter") + public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { + ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); + bean.setSecurityManager(securityManager); + + //配置鉴权与登出的拦截器。 + Map filterMap = new LinkedHashMap<>(); + filterMap.put("authc", formAuthenticationFilter()); + filterMap.put("logout", new ShiroLogoutFilter()); + bean.setFilters(filterMap); + + //配置各路径需要使用的拦截器。 + //anon表示anonymous。 + Map filterChainDefinitionMap = new LinkedHashMap<>(); + filterChainDefinitionMap.put("/logout", "logout"); + filterChainDefinitionMap.put("/css/**", "anon"); + filterChainDefinitionMap.put("/js/**", "anon"); + filterChainDefinitionMap.put("/img/**", "anon"); + filterChainDefinitionMap.put("/font/**", "anon"); + filterChainDefinitionMap.put("/fonts/**", "anon"); + filterChainDefinitionMap.put("/images/**", "anon"); + + filterChainDefinitionMap.put("/**", "authc"); + bean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return bean; + } + + /** + * 缓存管理器 使用Ehcache实现 + * + * @return + */ + @Bean(name = "shiroRedisCacheManager") + //@ConditionalOnClass(name = {"org.apache.shiro.cache.ehcache.EhCacheManager"}) + @ConditionalOnMissingBean(name = "shiroRedisCacheManager") + public CacheManager shiroRedisCacheManager() { + //EhCacheManager cacheManager = new EhCacheManager(); + //cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); + //return cacheManager; + ShiroRedisCacheManager cacheManager = new ShiroRedisCacheManager(); + return cacheManager; + } + + /** + * realm + * + * @return + */ + @Bean + public Realm realm() { + ShiroRealm shiroRealm = new ShiroRealm(); + shiroRealm.setName(SHIRO_REALM_NAME); + shiroRealm.setCredentialsMatcher(credentialsMatcher()); + shiroRealm.setCachingEnabled(true); + + //不设置账号缓存,每次登录都实时调用用户服务的登录接口。 + shiroRealm.setAuthenticationCachingEnabled(false); + + //不设置角色权限缓存,每次登录都从权限服务实时拉取。 + shiroRealm.setAuthorizationCachingEnabled(false); + + return shiroRealm; + } + + /** + * 会话验证调度器 + * + * @return + */ + @Bean(name = "sessionValidationScheduler") + @ConditionalOnClass(name = {"org.quartz.Scheduler"}) + @ConditionalOnMissingBean(SessionValidationScheduler.class) + public SessionValidationScheduler sessionValidationScheduler(DefaultWebSessionManager sessionManager) { + QuartzSessionValidationScheduler scheduler = new QuartzSessionValidationScheduler(sessionManager); + //scheduler.setSessionValidationInterval(1800000); + //scheduler.setSessionManager(sessionManager()); + sessionManager.setSessionValidationSchedulerEnabled(true); + sessionManager.setSessionValidationInterval(1800000); + sessionManager.setSessionValidationScheduler(scheduler); + return scheduler; + } + + /** + * 会话DAO + * + * @return + */ + @Bean + public SessionDAO sessionDAO() { + RedisSessionDao redisSessionDao = new RedisSessionDao(); + redisSessionDao.setActiveSessionsCacheName("shiro-activeSessionCache"); + redisSessionDao.setSessionIdGenerator(new UuidSessionIdGenerator()); + return redisSessionDao; + } + + /** + * 会话Cookie模板 + * + * @return + */ + @Bean + public Cookie sessionIdCookie() { + SimpleCookie cookie = new SimpleCookie("sid"); + cookie.setHttpOnly(true); + cookie.setMaxAge(-1); + return cookie; + } + + /** + * rememberMe Cookie + * + * @return + */ + @Bean + public Cookie rememberMeCookie() { + SimpleCookie cookie = new SimpleCookie("rememberMe"); + cookie.setHttpOnly(true); + //30天 + cookie.setMaxAge(2592000); + return cookie; + } + + /** + * 会话管理器 + * + * @return + */ + @Bean + public DefaultWebSessionManager sessionManager() { + //SessionManager sessionManager = new SessionManager(); + HttpHeaderSessionManager sessionManager = new HttpHeaderSessionManager(); + sessionManager.setGlobalSessionTimeout(43200000); + sessionManager.setDeleteInvalidSessions(true); + //sessionManager.setSessionValidationSchedulerEnabled(true); + //sessionManager.setSessionValidationScheduler(sessionValidationScheduler(sessionManager)); + //sessionManager.setSessionValidationScheduler(sessionValidationScheduler()); + sessionManager.setSessionDAO(sessionDAO()); + sessionManager.setSessionIdCookieEnabled(false); +// sessionManager.setSessionIdCookie(sessionIdCookie()); + //去掉URL中的JSESSIONID + sessionManager.setSessionIdUrlRewritingEnabled(false); + return sessionManager; + } + + /** + * 安全管理器 + * + * @return + */ + @Bean + @DependsOn("redisTemplate") + public SecurityManager securityManager() { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + securityManager.setRealm(realm()); + securityManager.setCacheManager(shiroRedisCacheManager()); + securityManager.setSessionManager(sessionManager()); + securityManager.setRememberMeManager(rememberMeManager()); + return securityManager; + } + + /** + * rememberMe管理器 + * + * @return + */ + @Bean + public RememberMeManager rememberMeManager() { + CookieRememberMeManager manager = new CookieRememberMeManager(); + //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) + manager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag==")); + manager.setCookie(rememberMeCookie()); + return manager; + } + + /** + * 凭证匹配器 + * + * @return + */ + @Bean(name = "credentialsMatcher") + public CredentialsMatcher credentialsMatcher() { + //明文密码 + //CustomCredentialsMatcher matcher = new CustomCredentialsMatcher(); + //HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); + RetryLimitHashedCredentialsMatcher matcher = new RetryLimitHashedCredentialsMatcher(shiroRedisCacheManager()); + //matcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; + //matcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); + matcher.setStoredCredentialsHexEncoded(true); + return matcher; + } + + @Bean + public MethodInvokingFactoryBean methodInvokingFactoryBean() { + MethodInvokingFactoryBean factoryBean = new MethodInvokingFactoryBean(); + factoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); + factoryBean.setArguments(securityManager()); + return factoryBean; + } + + /** + * Shiro生命周期处理器 + * + * @return + */ + @Bean + public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + public ShiroFormAuthenticationFilter formAuthenticationFilter() { + ShiroFormAuthenticationFilter filter = new ShiroFormAuthenticationFilter(); + filter.setUsernameParam("username"); + filter.setPasswordParam("password"); + filter.setRememberMeParam("rememberMe"); + filter.setLoginUrl("/login"); + filter.setSuccessUrl("/index"); + return filter; + } + + /** + * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类, + * 并在必要时进行安全逻辑验证 * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor) + * 即可实现此功能 + * + * @return + */ + @Bean + @DependsOn({"lifecycleBeanPostProcessor"}) + public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { + DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); + advisorAutoProxyCreator.setProxyTargetClass(true); + return advisorAutoProxyCreator; + } + + /** + * 开启shiro aop注解支持. + * 使用代理方式;所以需要开启代码支持; + * 需要aspectj支持 + * + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = + new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroProperty.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroProperty.java new file mode 100644 index 0000000..fac4c38 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroProperty.java @@ -0,0 +1,55 @@ +package cn.abel.rest.shiro; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +/** + * @date 2019/02/26 14:39 + */ +@Configuration +public class ShiroProperty { + + @Value("${shiro.retryExpireTimeRedis}") + private int shiroRetryExpireTimeRedis; + + @Value("${shiro.authorizationExpireTimeRedis}") + private int shiroAuthorizationExpireTimeRedis; + + @Value("${shiro.retryMax}") + private int shiroRetryMax; + + @Value("${shiro.sessionExpireTimeRedis}") + private Integer shiroSessionExpireTimeRedis; + + public int getShiroRetryExpireTimeRedis() { + return shiroRetryExpireTimeRedis; + } + + public void setShiroRetryExpireTimeRedis(int shiroRetryExpireTimeRedis) { + this.shiroRetryExpireTimeRedis = shiroRetryExpireTimeRedis; + } + + public int getShiroAuthorizationExpireTimeRedis() { + return shiroAuthorizationExpireTimeRedis; + } + + public void setShiroAuthorizationExpireTimeRedis(int shiroAuthorizationExpireTimeRedis) { + this.shiroAuthorizationExpireTimeRedis = shiroAuthorizationExpireTimeRedis; + } + + public int getShiroRetryMax() { + return shiroRetryMax; + } + + public void setShiroRetryMax(int shiroRetryMax) { + this.shiroRetryMax = shiroRetryMax; + } + + public Integer getShiroSessionExpireTimeRedis() { + return shiroSessionExpireTimeRedis; + } + + public void setShiroSessionExpireTimeRedis(Integer shiroSessionExpireTimeRedis) { + this.shiroSessionExpireTimeRedis = shiroSessionExpireTimeRedis; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRealm.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRealm.java new file mode 100644 index 0000000..8744ee6 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRealm.java @@ -0,0 +1,145 @@ +package cn.abel.rest.shiro; + +import java.util.List; +import java.util.Random; +import java.util.Set; + +import cn.abel.exception.ServiceException; +import cn.abel.user.models.Permission; +import cn.abel.user.models.Role; +import cn.abel.user.models.User; +import cn.abel.user.service.PermissionService; +import cn.abel.user.service.RoleService; +import cn.abel.user.service.UserService; +import com.alibaba.dubbo.config.annotation.Reference; +import com.google.common.collect.Sets; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAccount; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @date 2018/08/07 23:48 + */ +@Component +public class ShiroRealm extends AuthorizingRealm { + + /** + * logger + */ + private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class); + + @Reference(check = false) + private UserService userService; + + + /** + * 登录 认证回调函数,登录时调用 + * + * @param authenticationToken + * @return + * @throws AuthenticationException + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) + throws AuthenticationException { + UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; + String username = token.getUsername(); + + Random random = new Random(); + Long userId = random.nextLong(); + + //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配 + return new SimpleAccount(new ShiroUser(userId, username, username), "", getName()); + } + + /** + * 授权 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用 + * + * @param principals + * @return + */ + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal(); + + SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); + + Set roles = Sets.newHashSet(); + Set permissions = Sets.newHashSet(); + +// try { + //TODO 此处需要获取当前用户的所有角色和权限,放入验证器 + //登录名为超级管理员账号 +// +// //获取用户所有角色 +// User user = userService.getById( shiroUser.getUserId()); +// if (CollectionUtils.isEmpty(user.getRoles())) { +// return authorizationInfo; +// } +// +// for (Role role : user.getRoles()) { +// //停用的角色不查询权限 +// roles.add(role.getName()); +// List permissionList = permissionService.getByMap(role.getId()); +// permissionList.forEach(p -> { +// permissions.add(p.getCode()); +// }); +// } +// } catch (ServiceException e) { +// logger.error(e.getMessage()); +// return authorizationInfo; +// } + + authorizationInfo.setRoles(roles); + authorizationInfo.setStringPermissions(permissions); + + return authorizationInfo; + } + + @Override + public void clearCachedAuthorizationInfo(PrincipalCollection principals) { + super.clearCachedAuthorizationInfo(principals); + clearAllCache(); + } + + @Override + public void clearCachedAuthenticationInfo(PrincipalCollection principals) { + super.clearCachedAuthenticationInfo(principals); + clearAllCache(); + } + + @Override + public void clearCache(PrincipalCollection principals) { + super.clearCache(principals); + clearAllCache(); + } + + public void clearAllCachedAuthorizationInfo() { + if (getAuthorizationCache() != null) { + getAuthorizationCache().clear(); + } + } + + public void clearAllCachedAuthenticationInfo() { + if (getAuthenticationCache() != null) { + getAuthenticationCache().clear(); + } + + } + + public void clearAllCache() { + clearAllCachedAuthenticationInfo(); + clearAllCachedAuthorizationInfo(); + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRedisCacheManager.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRedisCacheManager.java new file mode 100644 index 0000000..03b19b7 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroRedisCacheManager.java @@ -0,0 +1,126 @@ +package cn.abel.rest.shiro; + +import java.util.Collection; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import cn.abel.rest.constants.Constants; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheException; +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.subject.PrincipalCollection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundHashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; + +/** + * 实现Shiro的缓存管理器CacheManger接口,将Spring应用缓存管理器注入shiro缓存管理器,这样shiro的缓存都由Spring处理 + * + * @date 2019/02/21 18:12 + */ +@Component +public class ShiroRedisCacheManager implements CacheManager { + + private final static String CACHE_KEY_PREFIX = Constants.REDIS_KEY_PRE + ":shiro:"; + + @Autowired + private ShiroProperty shiroProperty; + + @Autowired + private RedisTemplate redisTemplate; + + /** 超时时间 */ + private long expireTime; + + @Override + public Cache getCache(String name) throws CacheException { + if ("passwordRetryCache".equals(name)) { + expireTime = shiroProperty.getShiroRetryExpireTimeRedis(); + } else { + expireTime = shiroProperty.getShiroAuthorizationExpireTimeRedis(); + } + return new ShiroRedisCache(CACHE_KEY_PREFIX + name, expireTime); + } + + /** + * 为shiro量身定做的一个redis cache,为Authorization cache做了特别优化 + */ + public class ShiroRedisCache implements Cache { + + private String cacheKey; + + // 缓存的超时时间,单位为s + private long expireTime = 3600; + + public ShiroRedisCache(String cacheKey, long expireTime) { + this.cacheKey = cacheKey; + this.expireTime = expireTime; + } + + @Override + public V get(K key) throws CacheException { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + Object k = hashKey(key); + return hash.get(k); + } + + @Override + public V put(K key, V value) throws CacheException { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + //超时时间 + Object k = hashKey(key); + hash.put((K) k, value); + hash.expire(expireTime, TimeUnit.SECONDS); + return value; + } + + @Override + public V remove(K key) throws CacheException { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + + V value = null; + try { + Object k = hashKey(key); + value = hash.get(k); + hash.delete(k); + } catch (Exception e) { + e.printStackTrace(); + } + return value; + } + + @Override + public void clear() throws CacheException { + redisTemplate.delete(cacheKey); + } + + @Override + public int size() { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + return hash.size().intValue(); + } + + @Override + public Set keys() { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + return hash.keys(); + } + + @Override + public Collection values() { + BoundHashOperations hash = redisTemplate.boundHashOps(cacheKey); + return hash.values(); + } + + protected Object hashKey(K key) { + //此处很重要,如果key是登录凭证,那么这是访问用户的授权缓存;将登录凭证转为user对象,返回user的id属性做为hash key,否则会以user对象做为hash key,这样就不好清除指定用户的缓存了 + if (key instanceof PrincipalCollection) { + PrincipalCollection pc = (PrincipalCollection) key; + ShiroUser user = (ShiroUser) pc.getPrimaryPrincipal(); + return user.getUserId(); + } + return key; + } + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroUser.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroUser.java new file mode 100644 index 0000000..ea91eab --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ShiroUser.java @@ -0,0 +1,102 @@ +package cn.abel.rest.shiro; + +import java.io.Serializable; + +import com.google.common.base.Objects; + +/** + * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息. + * + */ +public class ShiroUser implements Serializable { + + private static final long serialVersionUID = -1373760761780840081L; + + private Long userId; + + private String loginName; + + private String nickName; + + private String token; + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public ShiroUser(Long userId, String loginName, String nickName) { + this.userId = userId; + this.loginName = loginName; + this.nickName = nickName; + } + + public String getNickName() { + return nickName; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + /** + * 本函数输出将作为默认的输出. + */ + @Override + public String toString() { + return loginName; + } + + /** + * 重载hashCode,只计算loginName; + */ + @Override + public int hashCode() { + return Objects.hashCode(loginName); + } + + /** + * 重载equals,只计算loginName; + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ShiroUser other = (ShiroUser) obj; + if (loginName == null) { + if (other.loginName != null) { + return false; + } + } else if (!loginName.equals(other.loginName)) { + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/UuidSessionIdGenerator.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/UuidSessionIdGenerator.java new file mode 100644 index 0000000..53d4c59 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/UuidSessionIdGenerator.java @@ -0,0 +1,20 @@ +package cn.abel.rest.shiro; + +import java.io.Serializable; +import java.util.UUID; + +import org.apache.shiro.session.Session; +import org.apache.shiro.session.mgt.eis.SessionIdGenerator; + +/** + * 会话ID生成器 + * + * @date 2018/08/08 11:04 + */ +public class UuidSessionIdGenerator implements SessionIdGenerator { + + @Override + public Serializable generateId(Session session) { + return UUID.randomUUID().toString().replace("-", "").toUpperCase(); + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/PasswordHelper.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/PasswordHelper.java new file mode 100644 index 0000000..663c312 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/PasswordHelper.java @@ -0,0 +1,27 @@ +package cn.abel.rest.shiro.credentials; + +import org.apache.shiro.crypto.hash.SimpleHash; +import org.apache.shiro.util.ByteSource; + +/** + * 密码 + * + */ +public class PasswordHelper { + + private static String algorithmName = "md5"; + private static int hashIterations = 2; + + public void setAlgorithmName(String algorithmName) { + PasswordHelper.algorithmName = algorithmName; + } + + public void setHashIterations(int hashIterations) { + PasswordHelper.hashIterations = hashIterations; + } + + public static String encryptPassword(String userName, String password) { + return new SimpleHash(algorithmName, password, ByteSource.Util.bytes(userName), hashIterations).toHex(); + } + +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/RetryLimitHashedCredentialsMatcher.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/RetryLimitHashedCredentialsMatcher.java new file mode 100644 index 0000000..959e5e9 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/RetryLimitHashedCredentialsMatcher.java @@ -0,0 +1,118 @@ +package cn.abel.rest.shiro.credentials; + +import java.util.concurrent.atomic.AtomicInteger; +import cn.abel.rest.shiro.ShiroUser; +import cn.abel.rest.shiro.ShiroProperty; + +import cn.abel.user.service.UserService; +import com.alibaba.dubbo.config.annotation.Reference; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import javax.websocket.Session; + +/** + * 登录验证 + */ +public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { + private static final Logger logger = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class); + + @Autowired + private ShiroProperty shiroProperty; + @Reference + private UserService userService; + + private Cache passwordRetryCache; + + public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) { + passwordRetryCache = cacheManager.getCache("passwordRetryCache"); + } + + @Override + public boolean doCredentialsMatch(AuthenticationToken originToken, AuthenticationInfo info) { + ThirdPartySupportedToken token = (ThirdPartySupportedToken) originToken; + ShiroUser shiroUser = (ShiroUser) info.getPrincipals().getPrimaryPrincipal(); + + //优先使用第三方token进行登录验证。 + if (StringUtils.isNotBlank(token.getAccessToken())) { + Session session = null; +// try { + //TODO 从用户服务中通过 token 获取 session +// session = userService.getSessionByToken(token.getAccessToken()); +// } catch (ServiceException e) { +// throw new ExpiredCredentialsException(); +// } + if (session == null) { + throw new ExpiredCredentialsException(); + } + //TODO 从session 中获取用户相关信息,放入shiro 验证对象 shiroUser +// shiroUser.setUserId(session.getUser().getProfileId()); +// shiroUser.setLoginName(session.getCurrentLoginName()); +// shiroUser.setNickName(session.getUser().getNickName()); + return true; + } + + String username = token.getUsername(); + String password = String.valueOf(token.getPassword()); + + //判断该账号登录重试次数是否超过上限。 + AtomicInteger retryCount = passwordRetryCache.get(username); + if (retryCount != null && retryCount.get() >= shiroProperty.getShiroRetryMax()) { + throw new ExcessiveAttemptsException(); + } + + //TODO 没有token,则调用用户服务的登录接口重新登录 获取 session +// Login login = new Login(); +// login.setIp(Constants.CLIENT_IP); +// login.setLoginMode(2); +// login.setLoginName(username); +// login.setLoginType(3); +// login.setPassword(password); +// try { +// Session session = userService.login(login); +// if (session == null) { +// logger.error("登录失败。username={}", username); +// throw new IncorrectCredentialsException(); +// } +// if (session.getUser().getDeleteFlag() != 1) { +// logger.error("登录失败。用户已被锁定。username={}", username); +// throw new LockedAccountException(); +// } + + //登录成功,清空登录次数缓存。 + if (retryCount != null) { + passwordRetryCache.remove(username); + } + //TODO 将 session 中的用户id 信息放入 shiro 对shiroUser象中 +// shiroUser.setUserId(session.getUser().getProfileId()); +// return true; +// } catch (ServiceException e) { + //TODO 根据登录接口的异常信息判读 失败情况 +// if (e.getErrorCode() == InfoCode.USER_LOGIN_NOT_EXIST.getStatus() +// || e.getErrorCode() == InfoCode.REQUEST_PARAM_ERROR.getStatus()) { +// logger.error("登录失败,用户不存在。username={}", username); +// throw new UnknownAccountException(); +// } else if (e.getErrorCode() == InfoCode.PASSWORD_ERROR.getStatus()) { +// //密码错误缓存登录重试次数缓存。 +// if (retryCount == null) { +// retryCount = new AtomicInteger(0); +// } +// retryCount.incrementAndGet(); +// passwordRetryCache.put(username, retryCount); +// +// logger.error("登录失败,用户名或密码错误。username={}", username); +// throw new IncorrectCredentialsException(); +// } else { +// logger.error("登录失败,msg={}", e.getMessage()); +// } +// } + + return false; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/ThirdPartySupportedToken.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/ThirdPartySupportedToken.java new file mode 100644 index 0000000..79b9b48 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/credentials/ThirdPartySupportedToken.java @@ -0,0 +1,92 @@ +package cn.abel.rest.shiro.credentials; + +import org.apache.shiro.authc.UsernamePasswordToken; +import org.springframework.stereotype.Component; + +/** + * 支持第三方登录的shiro token。 + */ +public class ThirdPartySupportedToken extends UsernamePasswordToken { + private String username; + private char[] password; + private boolean rememberMe = false; + private String host; + + /** + * 第三方token。 + */ + private String accessToken; + + public ThirdPartySupportedToken( + String username, + String password, + String accessToken) { + this.username = username; + this.password = password != null ? password.toCharArray() : null; + this.accessToken = accessToken; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public void setUsername(String username) { + this.username = username; + } + + @Override + public char[] getPassword() { + return this.password; + } + + @Override + public void setPassword(char[] password) { + this.password = password; + } + + @Override + public Object getPrincipal() { + return this.getUsername(); + } + + @Override + public Object getCredentials() { + return this.getPassword(); + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public void setHost(String host) { + this.host = host; + } + + @Override + public boolean isRememberMe() { + return this.rememberMe; + } + + @Override + public void setRememberMe(boolean rememberMe) { + this.rememberMe = rememberMe; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + @Override + public void clear() { + super.clear(); + this.accessToken = null; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationJob.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationJob.java new file mode 100644 index 0000000..56ec875 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationJob.java @@ -0,0 +1,63 @@ +package cn.abel.rest.shiro.ext; + +import org.apache.shiro.session.mgt.ValidatingSessionManager; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 基于Quartz 2.* 版本的实现 + * + * @author web + */ +public class QuartzSessionValidationJob implements Job { + + /** + * Key used to store the session manager in the job data map for this job. + */ + public static final String SESSION_MANAGER_KEY = "sessionManager"; + + /**-------------------------------------------- + | I N S T A N C E V A R I A B L E S | + ============================================*/ + private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationJob.class); + + /*-------------------------------------------- + | C O N S T R U C T O R S | + ============================================*/ + + /*-------------------------------------------- + | A C C E S S O R S / M O D I F I E R S | + ============================================*/ + + /*-------------------------------------------- + | M E T H O D S | + ============================================*/ + + /** + * Called when the job is executed by quartz. This method delegates to the validateSessions() method on the + * associated session manager. + * + * @param context the Quartz job execution context for this execution. + */ + @Override + public void execute(JobExecutionContext context) throws JobExecutionException { + + JobDataMap jobDataMap = context.getMergedJobDataMap(); + ValidatingSessionManager sessionManager = (ValidatingSessionManager) jobDataMap.get(SESSION_MANAGER_KEY); + + if (log.isDebugEnabled()) { + log.debug("Executing session validation Quartz job..."); + } + + sessionManager.validateSessions(); + + if (log.isDebugEnabled()) { + log.debug("Session validation Quartz job complete."); + } + } + +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationScheduler.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationScheduler.java new file mode 100644 index 0000000..323511b --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/ext/QuartzSessionValidationScheduler.java @@ -0,0 +1,156 @@ +package cn.abel.rest.shiro.ext; + +import org.apache.shiro.session.mgt.DefaultSessionManager; +import org.apache.shiro.session.mgt.SessionValidationScheduler; +import org.apache.shiro.session.mgt.ValidatingSessionManager; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SimpleScheduleBuilder; +import org.quartz.SimpleTrigger; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import org.quartz.impl.StdSchedulerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 基于Quartz 2.* 版本的实现 + * + * @author web + */ +public class QuartzSessionValidationScheduler implements SessionValidationScheduler { + + public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = + DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL; + private static final String JOB_NAME = "SessionValidationJob"; + private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationScheduler.class); + private static final String SESSION_MANAGER_KEY = QuartzSessionValidationJob.SESSION_MANAGER_KEY; + private Scheduler scheduler; + private boolean schedulerImplicitlyCreated = false; + + private boolean enabled = false; + private ValidatingSessionManager sessionManager; + private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL; + + public QuartzSessionValidationScheduler() { + } + + public QuartzSessionValidationScheduler(ValidatingSessionManager sessionManager) { + this.sessionManager = sessionManager; + } + + protected Scheduler getScheduler() throws SchedulerException { + if (this.scheduler == null) { + this.scheduler = StdSchedulerFactory.getDefaultScheduler(); + this.schedulerImplicitlyCreated = true; + } + return this.scheduler; + } + + public void setScheduler(Scheduler scheduler) { + this.scheduler = scheduler; + } + + public void setSessionManager(ValidatingSessionManager sessionManager) { + this.sessionManager = sessionManager; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + public void setSessionValidationInterval(long sessionValidationInterval) { + this.sessionValidationInterval = sessionValidationInterval; + } + + @Override + public void enableSessionValidation() { + if (log.isDebugEnabled()) { + log.debug("Scheduling session validation job using Quartz with session validation interval of [" + this.sessionValidationInterval + "]ms..."); + } + + try { + //Quartz 2中的实现 + SimpleTrigger trigger = TriggerBuilder.newTrigger().startNow().withIdentity(JOB_NAME, + Scheduler.DEFAULT_GROUP).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInMilliseconds(sessionValidationInterval)).build(); + + JobDetail detail = JobBuilder.newJob(QuartzSessionValidationJob.class).withIdentity(JOB_NAME, + Scheduler.DEFAULT_GROUP).build(); + detail.getJobDataMap().put(SESSION_MANAGER_KEY, this.sessionManager); + Scheduler scheduler = getScheduler(); + + scheduler.scheduleJob(detail, trigger); + if (this.schedulerImplicitlyCreated) { + scheduler.start(); + if (log.isDebugEnabled()) { + log.debug("Successfully started implicitly created Quartz Scheduler instance."); + } + } + this.enabled = true; + + if (log.isDebugEnabled()) { + log.debug("Session validation job successfully scheduled with Quartz."); + } + } catch (SchedulerException e) { + if (log.isErrorEnabled()) { + log.error("Error starting the Quartz session validation job. Session validation may not occur.", e); + } + } + } + + @Override + public void disableSessionValidation() { + if (log.isDebugEnabled()) { + log.debug("Stopping Quartz session validation job..."); + } + Scheduler scheduler; + try { + scheduler = getScheduler(); + if (scheduler == null) { + if (log.isWarnEnabled()) { + log.warn("getScheduler() method returned a null Quartz scheduler, which is unexpected. Please " + + "check your configuration and/or implementation. Returning quietly since there is no " + + "validation job to remove (scheduler does not exist)."); + } + + return; + } + } catch (SchedulerException e) { + if (log.isWarnEnabled()) { + log.warn("Unable to acquire Quartz Scheduler. Ignoring and returning (already stopped?)", e); + } + return; + } + try { + scheduler.unscheduleJob(new TriggerKey("SessionValidationJob", "DEFAULT")); + if (log.isDebugEnabled()) { + log.debug("Quartz session validation job stopped successfully."); + } + } catch (SchedulerException e) { + if (log.isDebugEnabled()) { + log.debug("Could not cleanly remove SessionValidationJob from Quartz scheduler. Ignoring and " + + "stopping.", e); + } + + } + + this.enabled = false; + + if (this.schedulerImplicitlyCreated) { + try { + scheduler.shutdown(); + } catch (SchedulerException e) { + if (log.isWarnEnabled()) { + log.warn("Unable to cleanly shutdown implicitly created Quartz Scheduler instance.", e); + } + } finally { + setScheduler(null); + this.schedulerImplicitlyCreated = false; + } + } + } + +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroFormAuthenticationFilter.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroFormAuthenticationFilter.java new file mode 100644 index 0000000..2804e71 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroFormAuthenticationFilter.java @@ -0,0 +1,160 @@ +package cn.abel.rest.shiro.filter; + +import java.io.IOException; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +import cn.abel.code.InfoCode; +import cn.abel.response.ResponseEntity; +import cn.abel.rest.constants.Constants; +import cn.abel.rest.shiro.ShiroUser; +import cn.abel.rest.shiro.credentials.ThirdPartySupportedToken; +import com.alibaba.fastjson.JSON; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; + +/** + * 登录filter + * + */ +public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter { + private static final Logger logger = LoggerFactory.getLogger(ShiroFormAuthenticationFilter.class); + + @Override + public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { + //登录请求用户名和accessToken不能同时为空。 + if (isLoginRequest(request, response)) { + if (StringUtils.isBlank(getUsername(request)) + && StringUtils.isBlank(request.getParameter(Constants.THIRD_PARTY_ACCESS_TOKEN_NAME))) { + return responseDirectly((HttpServletResponse) response, + ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR)); + } + } + return super.onPreHandle(request, response, mappedValue); + } + + /** + * 当鉴权失败的时候执行的方法。 + * + * @param request + * @param response + * @return + * @throws Exception + */ + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + if (isLoginRequest(request, response)) { + if (isLoginSubmission(request, response)) { + return executeLogin(request, response); + } + //登录仅限HttpPost方式,其他任何方式是不合法的。 + return responseDirectly((HttpServletResponse) response, ResponseEntity.error(InfoCode.LOGIN_TYPE_ERROR)); + } + //调用非登录方法时认证失败的情况。 + return responseDirectly((HttpServletResponse) response, ResponseEntity.error(InfoCode.INVALID_TOKEN)); + } + + /** + * 登录验证失败后执行的方法。 + * + * @param token + * @param e + * @param request + * @param response + * @return + */ + @Override + protected boolean onLoginFailure( + AuthenticationToken token, + AuthenticationException e, + ServletRequest request, + ServletResponse response) { + HttpServletResponse resp = (HttpServletResponse) response; + if (e instanceof ExcessiveAttemptsException) { + return responseDirectly(resp, ResponseEntity.error(InfoCode.PASSWORD_ERROR_MORE_THAN)); + } else if (e instanceof UnknownAccountException) { + return responseDirectly(resp, ResponseEntity.error(InfoCode.PASSWORD_ERROR)); + } else if (e instanceof IncorrectCredentialsException) { + return responseDirectly(resp, ResponseEntity.error(InfoCode.PASSWORD_ERROR)); + } else if (e instanceof LockedAccountException) { + return responseDirectly(resp, ResponseEntity.error(InfoCode.USER_PROFILE_LOCK)); + } else if (e instanceof ExpiredCredentialsException) { + return responseDirectly(resp, ResponseEntity.error(InfoCode.INVALID_LOGIN)); + } else { + return responseDirectly(resp, ResponseEntity.error(InfoCode.SERVICE_UNAVAILABLE)); + } + } + + /** + * 登录成功后执行的方法。 + * + * @param token + * @param subject + * @param request + * @param response + * @return + * @throws Exception + */ + @Override + protected boolean onLoginSuccess( + AuthenticationToken token, + Subject subject, + ServletRequest request, + ServletResponse response) throws Exception { + ShiroUser user = (ShiroUser) subject.getPrincipal(); + user.setToken(subject.getSession().getId().toString()); + return true; + } + + /** + * 创建包含第三方accessToken的shiro token。 + * + * @param request + * @param response + * @return + */ + @Override + protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { + String username = getUsername(request); + String password = getPassword(request); + String accessToken = request.getParameter(Constants.THIRD_PARTY_ACCESS_TOKEN_NAME); + //shiro后续流程可能会用到username,所以如果用accessToken登录时赋值username为它的值。 + if (StringUtils.isBlank(username)) { + username = accessToken; + } + return new ThirdPartySupportedToken(username, password, accessToken); + } + + /** + * 直接构造HttpResponse,不再执行后续的所有方法。 + * + * @param response + * @param entity + * @return + */ + private boolean responseDirectly(HttpServletResponse response, ResponseEntity entity) { + response.reset(); + response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); + + //设置跨域信息。 + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, PUT, OPTIONS, HEAD"); + response.setHeader("Access-Control-Max-Age", "3600"); + response.setHeader("Access-Control-Allow-Headers", "*"); + try { + response.getWriter().write(JSON.toJSONString(entity)); + } catch (IOException e) { + logger.error("ResponseError ex:{}", ExceptionUtils.getStackTrace(e)); + } + return false; + } +} diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroLogoutFilter.java b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroLogoutFilter.java new file mode 100644 index 0000000..80b0d10 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/shiro/filter/ShiroLogoutFilter.java @@ -0,0 +1,26 @@ +package cn.abel.rest.shiro.filter; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.authc.LogoutFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 注销filter + * + * @date 2019/02/26 13:32 + */ +public class ShiroLogoutFilter extends LogoutFilter { + + private static final Logger logger = LoggerFactory.getLogger(ShiroLogoutFilter.class); + + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { + Subject subject = getSubject(request, response); + subject.logout(); + return true; + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/utils/ServletKit.java b/springboot-shiro2/src/main/java/cn/abel/rest/utils/ServletKit.java new file mode 100644 index 0000000..090d00c --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/utils/ServletKit.java @@ -0,0 +1,36 @@ +package cn.abel.rest.utils; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.resource.ResourceUrlProvider; + +/** + * Servlet工具类 + * + * @date 2019/02/22 14:07 + */ +public class ServletKit { + + /** + * 在任意位置获取Request + * + * @return + */ + public static HttpServletRequest getRequest() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } + + /** + * 判断请求uri是否是静态资源方法 + * + * @param uri + * @return + */ + public static boolean isStaticFile(String uri) { + ResourceUrlProvider resourceUrlProvider = SpringContextKit.getBean(ResourceUrlProvider.class); + String staticUri = resourceUrlProvider.getForLookupPath(uri); + return staticUri != null; + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/java/cn/abel/rest/utils/SpringContextKit.java b/springboot-shiro2/src/main/java/cn/abel/rest/utils/SpringContextKit.java new file mode 100644 index 0000000..7633886 --- /dev/null +++ b/springboot-shiro2/src/main/java/cn/abel/rest/utils/SpringContextKit.java @@ -0,0 +1,60 @@ +package cn.abel.rest.utils; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * 这个类是为了解决在普通类调用service的问题 + * + * @date 2018/10/24 15:16 + * @content OfflineMessageService offlineMessageService = (OfflineMessageService) SpringContextUtil + * .getBean("offlineMessageService"); + */ +@Component +public class SpringContextKit implements ApplicationContextAware { + + /** Spring应用上下文 */ + private static ApplicationContext applicationContext; + + /** 下面的这个方法上加了@Override注解,原因是继承ApplicationContextAware接口是必须实现的方法 */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextKit.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String name) throws BeansException { + return applicationContext.getBean(name); + } + + public static Object getBean(String name, Class requiredType) throws BeansException { + + return applicationContext.getBean(name, requiredType); + } + + public static T getBean(Class clazz) throws BeansException { + return applicationContext.getBean(clazz); + } + + public static boolean containsBean(String name) { + return applicationContext.containsBean(name); + } + + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return applicationContext.isSingleton(name); + } + + public static Class getType(String name) throws NoSuchBeanDefinitionException { + return applicationContext.getType(name); + } + + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return applicationContext.getAliases(name); + } +} \ No newline at end of file diff --git a/springboot-shiro2/src/main/resources/META-INF/spring/consumer.xml b/springboot-shiro2/src/main/resources/META-INF/spring/consumer.xml new file mode 100644 index 0000000..a3cf9cf --- /dev/null +++ b/springboot-shiro2/src/main/resources/META-INF/spring/consumer.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-shiro2/src/main/resources/dev/application.properties b/springboot-shiro2/src/main/resources/dev/application.properties new file mode 100644 index 0000000..b2be9c2 --- /dev/null +++ b/springboot-shiro2/src/main/resources/dev/application.properties @@ -0,0 +1,94 @@ +## tomcat\u914D\u7F6E +server.servlet.context-path=/shiro +server.port=9738 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-shiro +application.main=cn.abel.rest.ShiroRestApplication + +## LOG +logging.file=./logs/springboot-shiro.log + +## dubbo \u914D\u7F6E +dubbo.application.name=springboot-shiro +dubbo.registry.group=abel +#dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.version=1.0.0 +dubbo.protocol.port=13182 +dubbo.annotation.package=cn.abel.rest +dubbo.log.file=./logs/springboot-shiro-dubbo.log + +## spring cache +#\u7F13\u5B58\u7684\u540D\u79F0\u96C6\u5408\uFF0C\u591A\u4E2A\u91C7\u7528\u9017\u53F7\u5206\u5272 +#spring.cache.cache-names=admin,role +#\u7F13\u5B58\u7684\u7C7B\u578B\uFF0C\u5B98\u65B9\u63D0\u4F9B\u4E86\u5F88\u591A\uFF0C\u8FD9\u91CC\u6211\u4EEC\u586B\u5199redis +spring.cache.type=redis +#\u662F\u5426\u7F13\u5B58null\u6570\u636E\uFF0C\u9ED8\u8BA4\u662Ffalse +#spring.cache.redis.cache-null-values=false +#redis\u4E2D\u7F13\u5B58\u8D85\u65F6\u7684\u65F6\u95F4\uFF0C\u9ED8\u8BA460000ms +#spring.cache.redis.time-to-live=60000 +#\u7F13\u5B58\u6570\u636Ekey\u662F\u5426\u4F7F\u7528\u524D\u7F00\uFF0C\u9ED8\u8BA4\u662Ftrue +#spring.cache.redis.use-key-prefix=true + +## redis \u914D\u7F6E +# Redis\u6570\u636E\u5E93\u7D22\u5F15 +spring.redis.database=3 +# Redis\u670D\u52A1\u5668\u5730\u5740 +spring.redis.host=127.0.0.1 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3 +spring.redis.port=6379 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09 +spring.redis.password= +# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-active=100 +# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-wait=1000 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.max-idle=50 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.min-idle=0 +# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09 +spring.redis.lettuce.shutdown-timeout=0 + +## view\u914D\u7F6E +# FreeMarker\u914D\u7F6E +# \u662F\u5426\u5F00\u542F\u6A21\u677F\u7F13\u5B58 +spring.freemarker.cache=false +# \u7F16\u7801\u683C\u5F0F +spring.freemarker.charset=UTF-8 +# \u6A21\u677F\u7684\u5A92\u4F53\u7C7B\u578B\u8BBE\u7F6E +spring.freemarker.content-type=text/html +# \u524D\u7F00\u8BBE\u7F6E \u9ED8\u8BA4\u4E3A "" +spring.freemarker.prefix= +# \u540E\u7F00\u8BBE\u7F6E \u9ED8\u8BA4\u4E3A .ftl +spring.freemarker.suffix=.ftl +# +#spring.freemarker.viewClass=com.yekai.demo.admin.freemarker.CustomFreeMarkerView +# +spring.freemarker.expose-request-attributes=true +spring.freemarker.expose-session-attributes=true +# \u5F00\u542F\u5B8F\u652F\u6301 +spring.freemarker.expose-spring-macro-helpers=true +# ftl\u4E2D\u83B7\u53D6request +spring.freemarker.request-context-attribute=request + +#\u767B\u5F55\u91CD\u8BD5\u6B21\u6570 +shiro.retryMax=5 +#\u767B\u5F55\u5931\u8D25\u9501\u5B9A\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.retryExpireTimeRedis=900 +#\u6388\u6743\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.authorizationExpireTimeRedis=3600 +#session\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.sessionExpireTimeRedis=3600 + diff --git a/springboot-shiro2/src/main/resources/dev/banner.txt b/springboot-shiro2/src/main/resources/dev/banner.txt new file mode 100644 index 0000000..07d3606 --- /dev/null +++ b/springboot-shiro2/src/main/resources/dev/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# dev # +# # +######################################################## \ No newline at end of file diff --git a/springboot-shiro2/src/main/resources/dev/logback-spring.xml b/springboot-shiro2/src/main/resources/dev/logback-spring.xml new file mode 100644 index 0000000..92810cd --- /dev/null +++ b/springboot-shiro2/src/main/resources/dev/logback-spring.xml @@ -0,0 +1,41 @@ + + + springboot-shiro + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-shiro2/src/main/resources/local/application.properties b/springboot-shiro2/src/main/resources/local/application.properties new file mode 100644 index 0000000..879dfe0 --- /dev/null +++ b/springboot-shiro2/src/main/resources/local/application.properties @@ -0,0 +1,94 @@ +## tomcat\u914D\u7F6E +server.servlet.context-path=/shiro +server.port=9738 +#server.tomcat.maxHttpHeaderSize=8192 +server.tomcat.uri-encoding=UTF-8 +spring.http.encoding.charset=UTF-8 +spring.http.encoding.enabled=true +spring.http.encoding.force=true +spring.messages.encoding=UTF-8 +# tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=800 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 + +## spring \u914D\u7F6E +spring.application.name=springboot-shiro +application.main=cn.abel.rest.ShiroRestApplication + +## LOG +logging.file=./logs/springboot-shiro.log + +## dubbo \u914D\u7F6E +dubbo.application.name=springboot-shiro +dubbo.registry.group=abel +#dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.address=127.0.0.1:2181 +dubbo.registry.version=1.0.0 +dubbo.protocol.port=13182 +dubbo.annotation.package=cn.abel.rest +dubbo.log.file=./logs/springboot-shiro-dubbo.log + +## spring cache +#\u7F13\u5B58\u7684\u540D\u79F0\u96C6\u5408\uFF0C\u591A\u4E2A\u91C7\u7528\u9017\u53F7\u5206\u5272 +#spring.cache.cache-names=admin,role +#\u7F13\u5B58\u7684\u7C7B\u578B\uFF0C\u5B98\u65B9\u63D0\u4F9B\u4E86\u5F88\u591A\uFF0C\u8FD9\u91CC\u6211\u4EEC\u586B\u5199redis +spring.cache.type=redis +#\u662F\u5426\u7F13\u5B58null\u6570\u636E\uFF0C\u9ED8\u8BA4\u662Ffalse +#spring.cache.redis.cache-null-values=false +#redis\u4E2D\u7F13\u5B58\u8D85\u65F6\u7684\u65F6\u95F4\uFF0C\u9ED8\u8BA460000ms +#spring.cache.redis.time-to-live=60000 +#\u7F13\u5B58\u6570\u636Ekey\u662F\u5426\u4F7F\u7528\u524D\u7F00\uFF0C\u9ED8\u8BA4\u662Ftrue +#spring.cache.redis.use-key-prefix=true + +## redis \u914D\u7F6E +# Redis\u6570\u636E\u5E93\u7D22\u5F15 +spring.redis.database=3 +# Redis\u670D\u52A1\u5668\u5730\u5740 +spring.redis.host=127.0.0.1 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3 +spring.redis.port=6379 +# Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09 +spring.redis.password= +# \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-active=100 +# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 +spring.redis.lettuce.pool.max-wait=1000 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.max-idle=50 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 +spring.redis.lettuce.pool.min-idle=0 +# \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09 +spring.redis.lettuce.shutdown-timeout=0 + +## view\u914D\u7F6E +# FreeMarker\u914D\u7F6E +# \u662F\u5426\u5F00\u542F\u6A21\u677F\u7F13\u5B58 +spring.freemarker.cache=false +# \u7F16\u7801\u683C\u5F0F +spring.freemarker.charset=UTF-8 +# \u6A21\u677F\u7684\u5A92\u4F53\u7C7B\u578B\u8BBE\u7F6E +spring.freemarker.content-type=text/html +# \u524D\u7F00\u8BBE\u7F6E \u9ED8\u8BA4\u4E3A "" +spring.freemarker.prefix= +# \u540E\u7F00\u8BBE\u7F6E \u9ED8\u8BA4\u4E3A .ftl +spring.freemarker.suffix=.ftl +# +#spring.freemarker.viewClass=com.yekai.demo.admin.freemarker.CustomFreeMarkerView +# +spring.freemarker.expose-request-attributes=true +spring.freemarker.expose-session-attributes=true +# \u5F00\u542F\u5B8F\u652F\u6301 +spring.freemarker.expose-spring-macro-helpers=true +# ftl\u4E2D\u83B7\u53D6request +spring.freemarker.request-context-attribute=request + +#\u767B\u5F55\u91CD\u8BD5\u6B21\u6570 +shiro.retryMax=5 +#\u767B\u5F55\u5931\u8D25\u9501\u5B9A\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.retryExpireTimeRedis=900 +#\u6388\u6743\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.authorizationExpireTimeRedis=3600 +#session\u8D85\u65F6\u65F6\u95F4\uFF08\u79D2\uFF09 +shiro.sessionExpireTimeRedis=3600 + diff --git a/springboot-shiro2/src/main/resources/local/banner.txt b/springboot-shiro2/src/main/resources/local/banner.txt new file mode 100644 index 0000000..42f7c59 --- /dev/null +++ b/springboot-shiro2/src/main/resources/local/banner.txt @@ -0,0 +1,5 @@ +######################################################## +# # +# local # +# # +######################################################## \ No newline at end of file diff --git a/springboot-shiro2/src/main/resources/local/logback-spring.xml b/springboot-shiro2/src/main/resources/local/logback-spring.xml new file mode 100644 index 0000000..1787857 --- /dev/null +++ b/springboot-shiro2/src/main/resources/local/logback-spring.xml @@ -0,0 +1,41 @@ + + + springboot-shiro + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + ${LOG_FILE} + + + ${LOG_FILE}.%d{yyyy-MM-dd} + + 60 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-springCloud/config/pom.xml b/springboot-springCloud/config/pom.xml new file mode 100644 index 0000000..7ab688b --- /dev/null +++ b/springboot-springCloud/config/pom.xml @@ -0,0 +1,28 @@ + + + + springCloud + com.abel + 1.0-SNAPSHOT + + 4.0.0 + + config + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-config-server + + + org.springframework.cloud + spring-cloud-starter-eureka + + + \ No newline at end of file diff --git a/springboot-springCloud/config/src/main/java/com/abel/ConfigApplication.java b/springboot-springCloud/config/src/main/java/com/abel/ConfigApplication.java new file mode 100644 index 0000000..f67e777 --- /dev/null +++ b/springboot-springCloud/config/src/main/java/com/abel/ConfigApplication.java @@ -0,0 +1,21 @@ +package com.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.config.server.EnableConfigServer; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; + +/** + * Created by yangyibo on 2018/6/27. + * 配置模块 + */ +@SpringBootApplication +//开启配置服务器的支持 +@EnableConfigServer +//开启Eureka server 作为客户端的支持 +@EnableEurekaClient +public class ConfigApplication { + public static void main(String[] args) { + SpringApplication.run(ConfigApplication.class,args); + } +} diff --git a/springboot-springCloud/config/src/main/resources/application.yml b/springboot-springCloud/config/src/main/resources/application.yml new file mode 100644 index 0000000..d603c75 --- /dev/null +++ b/springboot-springCloud/config/src/main/resources/application.yml @@ -0,0 +1,9 @@ +spring: + cloud: + config: + server: + native: + search-locations: classpath:/config #配置其他所需的配置文件的路径 + +server: + port: 8888 diff --git a/springboot-springCloud/config/src/main/resources/bootstrap.yml b/springboot-springCloud/config/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..e1eb80b --- /dev/null +++ b/springboot-springCloud/config/src/main/resources/bootstrap.yml @@ -0,0 +1,14 @@ +spring: + application: + name: config #在Eureka server 注册的服务名为config + profiles: + active: native # 配置服务器使用本地配置(默认为git 配置) + +eureka: + instance: + non-secure-port: ${server.port:8888} #非ssl 端口,若环境变量中server.port有值,则使用环境变量的值,没有则使用8080 + metadata-map: + instanceId: ${spring.application.name}:${random.value} #配置在Eureka server 的实例id + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ #Eureka 客户端设置的 Eureka server 地址 \ No newline at end of file diff --git a/springboot-springCloud/config/src/main/resources/config/person.yml b/springboot-springCloud/config/src/main/resources/config/person.yml new file mode 100644 index 0000000..cd85094 --- /dev/null +++ b/springboot-springCloud/config/src/main/resources/config/person.yml @@ -0,0 +1,3 @@ +spring: + jpa: + database: HSQL \ No newline at end of file diff --git a/springboot-springCloud/config/src/main/resources/config/some.yml b/springboot-springCloud/config/src/main/resources/config/some.yml new file mode 100644 index 0000000..c95f232 --- /dev/null +++ b/springboot-springCloud/config/src/main/resources/config/some.yml @@ -0,0 +1,2 @@ +my: + message: Message from Development diff --git a/springboot-springCloud/config/target/classes/application.yml b/springboot-springCloud/config/target/classes/application.yml new file mode 100644 index 0000000..d603c75 --- /dev/null +++ b/springboot-springCloud/config/target/classes/application.yml @@ -0,0 +1,9 @@ +spring: + cloud: + config: + server: + native: + search-locations: classpath:/config #配置其他所需的配置文件的路径 + +server: + port: 8888 diff --git a/springboot-springCloud/config/target/classes/bootstrap.yml b/springboot-springCloud/config/target/classes/bootstrap.yml new file mode 100644 index 0000000..e1eb80b --- /dev/null +++ b/springboot-springCloud/config/target/classes/bootstrap.yml @@ -0,0 +1,14 @@ +spring: + application: + name: config #在Eureka server 注册的服务名为config + profiles: + active: native # 配置服务器使用本地配置(默认为git 配置) + +eureka: + instance: + non-secure-port: ${server.port:8888} #非ssl 端口,若环境变量中server.port有值,则使用环境变量的值,没有则使用8080 + metadata-map: + instanceId: ${spring.application.name}:${random.value} #配置在Eureka server 的实例id + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ #Eureka 客户端设置的 Eureka server 地址 \ No newline at end of file diff --git a/springboot-springCloud/config/target/classes/config/person.yml b/springboot-springCloud/config/target/classes/config/person.yml new file mode 100644 index 0000000..cd85094 --- /dev/null +++ b/springboot-springCloud/config/target/classes/config/person.yml @@ -0,0 +1,3 @@ +spring: + jpa: + database: HSQL \ No newline at end of file diff --git a/springboot-springCloud/config/target/classes/config/some.yml b/springboot-springCloud/config/target/classes/config/some.yml new file mode 100644 index 0000000..c95f232 --- /dev/null +++ b/springboot-springCloud/config/target/classes/config/some.yml @@ -0,0 +1,2 @@ +my: + message: Message from Development diff --git a/springboot-springCloud/discovery/pom.xml b/springboot-springCloud/discovery/pom.xml new file mode 100644 index 0000000..0473b75 --- /dev/null +++ b/springboot-springCloud/discovery/pom.xml @@ -0,0 +1,26 @@ + + + + springCloud + com.abel + 1.0-SNAPSHOT + ../pom.xml + + 4.0.0 + + + discovery + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-starter-eureka-server + + + \ No newline at end of file diff --git a/springboot-springCloud/discovery/src/main/java/com/abel/DiscoveryApplication.java b/springboot-springCloud/discovery/src/main/java/com/abel/DiscoveryApplication.java new file mode 100644 index 0000000..ac06d6c --- /dev/null +++ b/springboot-springCloud/discovery/src/main/java/com/abel/DiscoveryApplication.java @@ -0,0 +1,17 @@ +package com.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +/** + * Created by yangyibo on 2018/6/27. + * 服务发现 一个常规的springboot 项目,只需要通过 @EnableEurekaServer 注解开启对EurekaServer 的支持即可 + */ +@SpringBootApplication +@EnableEurekaServer +public class DiscoveryApplication { + public static void main(String[] args) { + SpringApplication.run(DiscoveryApplication.class,args); + } +} diff --git a/springboot-springCloud/discovery/src/main/resources/application.yml b/springboot-springCloud/discovery/src/main/resources/application.yml new file mode 100644 index 0000000..b2df4c4 --- /dev/null +++ b/springboot-springCloud/discovery/src/main/resources/application.yml @@ -0,0 +1,12 @@ +#云计算环境下习惯使用YAML 配置此处我们也是用YAML 配置 +server: + port: 8761 + +eureka: + instance: + #当前Eureka Server 的hostname 为 localhost + hostname: localhost + #当前服务不需要到Eureka Server 上注册 + client: + register-with-eureka: false + fetch-registry: false diff --git a/springboot-springCloud/discovery/target/classes/application.yml b/springboot-springCloud/discovery/target/classes/application.yml new file mode 100644 index 0000000..b2df4c4 --- /dev/null +++ b/springboot-springCloud/discovery/target/classes/application.yml @@ -0,0 +1,12 @@ +#云计算环境下习惯使用YAML 配置此处我们也是用YAML 配置 +server: + port: 8761 + +eureka: + instance: + #当前Eureka Server 的hostname 为 localhost + hostname: localhost + #当前服务不需要到Eureka Server 上注册 + client: + register-with-eureka: false + fetch-registry: false diff --git a/springboot-springCloud/monitor/pom.xml b/springboot-springCloud/monitor/pom.xml new file mode 100644 index 0000000..f43ea56 --- /dev/null +++ b/springboot-springCloud/monitor/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + monitor + jar + + monitor + Turbine and Hystrix Dashboard + + + springCloud + com.abel + 1.0-SNAPSHOT + ../pom.xml + + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-starter-hystrix-dashboard + + + org.springframework.cloud + spring-cloud-starter-turbine + + + + + + com.spotify + docker-maven-plugin + + ${project.name}:${project.version} + ${project.basedir}/src/main/docker + false + + + ${project.build.directory} + ${project.build.finalName}.jar + + + + + + + \ No newline at end of file diff --git a/springboot-springCloud/monitor/src/main/java/com/abel/MonitorApplication.java b/springboot-springCloud/monitor/src/main/java/com/abel/MonitorApplication.java new file mode 100644 index 0000000..364680f --- /dev/null +++ b/springboot-springCloud/monitor/src/main/java/com/abel/MonitorApplication.java @@ -0,0 +1,20 @@ +package com.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; +import org.springframework.cloud.netflix.turbine.EnableTurbine; +/** + * Created by yangyibo on 2018/6/29. + */ +@SpringBootApplication +@EnableEurekaClient +@EnableHystrixDashboard +@EnableTurbine +public class MonitorApplication { + + public static void main(String[] args) { + SpringApplication.run(MonitorApplication.class, args); + } +} diff --git a/springboot-springCloud/monitor/src/main/resources/application.yml b/springboot-springCloud/monitor/src/main/resources/application.yml new file mode 100644 index 0000000..96307f7 --- /dev/null +++ b/springboot-springCloud/monitor/src/main/resources/application.yml @@ -0,0 +1,3 @@ +server: + port: 8989 + diff --git a/springboot-springCloud/monitor/src/main/resources/bootstrap.yml b/springboot-springCloud/monitor/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..49faa9b --- /dev/null +++ b/springboot-springCloud/monitor/src/main/resources/bootstrap.yml @@ -0,0 +1,10 @@ +spring: + application: + name: monitor + +eureka: + instance: + nonSecurePort: ${server.port:8989} + client: + serviceUrl: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/monitor/target/classes/application.yml b/springboot-springCloud/monitor/target/classes/application.yml new file mode 100644 index 0000000..96307f7 --- /dev/null +++ b/springboot-springCloud/monitor/target/classes/application.yml @@ -0,0 +1,3 @@ +server: + port: 8989 + diff --git a/springboot-springCloud/monitor/target/classes/bootstrap.yml b/springboot-springCloud/monitor/target/classes/bootstrap.yml new file mode 100644 index 0000000..49faa9b --- /dev/null +++ b/springboot-springCloud/monitor/target/classes/bootstrap.yml @@ -0,0 +1,10 @@ +spring: + application: + name: monitor + +eureka: + instance: + nonSecurePort: ${server.port:8989} + client: + serviceUrl: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/person/pom.xml b/springboot-springCloud/person/pom.xml new file mode 100644 index 0000000..19928b0 --- /dev/null +++ b/springboot-springCloud/person/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + springCloud + com.abel + 1.0-SNAPSHOT + ../pom.xml + + person + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-config-client + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.hsqldb + hsqldb + + + postgresql + postgresql + 9.1-901-1.jdbc4 + + + \ No newline at end of file diff --git a/springboot-springCloud/person/src/main/java/com/abel/PersonApplication.java b/springboot-springCloud/person/src/main/java/com/abel/PersonApplication.java new file mode 100644 index 0000000..b11054e --- /dev/null +++ b/springboot-springCloud/person/src/main/java/com/abel/PersonApplication.java @@ -0,0 +1,14 @@ +package com.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Created by yangyibo on 2018/6/28. + */ +@SpringBootApplication +public class PersonApplication { + public static void main(String[] args) { + SpringApplication.run(PersonApplication.class,args); + } +} diff --git a/springboot-springCloud/person/src/main/java/com/abel/bean/Person.java b/springboot-springCloud/person/src/main/java/com/abel/bean/Person.java new file mode 100644 index 0000000..5ba2a12 --- /dev/null +++ b/springboot-springCloud/person/src/main/java/com/abel/bean/Person.java @@ -0,0 +1,45 @@ +package com.abel.bean; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * Created by yangyibo on 2018/6/28. + */ +@Entity +public class Person { + @Id + @GeneratedValue + private Long id; + + private String name; + + public Person() { + super(); + } + + public Person(String name) { + super(); + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + +} diff --git a/springboot-springCloud/person/src/main/java/com/abel/controller/PersonController.java b/springboot-springCloud/person/src/main/java/com/abel/controller/PersonController.java new file mode 100644 index 0000000..18aa081 --- /dev/null +++ b/springboot-springCloud/person/src/main/java/com/abel/controller/PersonController.java @@ -0,0 +1,29 @@ +package com.abel.controller; +import com.abel.bean.Person; +import com.abel.dao.PersonRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * Created by yangyibo on 2018/6/27. + */ + +@RestController +public class PersonController { + @Autowired + PersonRepository personRepository; + + @RequestMapping(value = "/save", method = RequestMethod.POST) + public List savePerson(@RequestBody String personName) { + Person p = new Person(personName); + personRepository.save(p); + List people = personRepository.findAll(new PageRequest(0, 10)).getContent(); + return people; + } +} \ No newline at end of file diff --git a/springboot-springCloud/person/src/main/java/com/abel/dao/PersonRepository.java b/springboot-springCloud/person/src/main/java/com/abel/dao/PersonRepository.java new file mode 100644 index 0000000..7f9def0 --- /dev/null +++ b/springboot-springCloud/person/src/main/java/com/abel/dao/PersonRepository.java @@ -0,0 +1,10 @@ +package com.abel.dao; +import com.abel.bean.Person; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * Created by yangyibo on 2018/6/28. + */ +public interface PersonRepository extends JpaRepository{ + +} diff --git a/springboot-springCloud/person/src/main/resources/application.yml b/springboot-springCloud/person/src/main/resources/application.yml new file mode 100644 index 0000000..886b4b0 --- /dev/null +++ b/springboot-springCloud/person/src/main/resources/application.yml @@ -0,0 +1,9 @@ +server: + port: 8082 + + +spring: + jpa: + hibernate: + ddl-auto: update + diff --git a/springboot-springCloud/person/src/main/resources/bootstrap.yml b/springboot-springCloud/person/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..4890014 --- /dev/null +++ b/springboot-springCloud/person/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +spring: + application: + name: person + cloud: + config: + enabled: true + discovery: + enabled: true + service-id: CONFIG #1 +eureka: + instance: + non-secure-port: ${server.port:8082} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/person/target/classes/application.yml b/springboot-springCloud/person/target/classes/application.yml new file mode 100644 index 0000000..886b4b0 --- /dev/null +++ b/springboot-springCloud/person/target/classes/application.yml @@ -0,0 +1,9 @@ +server: + port: 8082 + + +spring: + jpa: + hibernate: + ddl-auto: update + diff --git a/springboot-springCloud/person/target/classes/bootstrap.yml b/springboot-springCloud/person/target/classes/bootstrap.yml new file mode 100644 index 0000000..4890014 --- /dev/null +++ b/springboot-springCloud/person/target/classes/bootstrap.yml @@ -0,0 +1,15 @@ +spring: + application: + name: person + cloud: + config: + enabled: true + discovery: + enabled: true + service-id: CONFIG #1 +eureka: + instance: + non-secure-port: ${server.port:8082} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/pom.xml b/springboot-springCloud/pom.xml new file mode 100644 index 0000000..601c6d6 --- /dev/null +++ b/springboot-springCloud/pom.xml @@ -0,0 +1,108 @@ + + + 4.0.0 + + com.abel + springCloud + pom + 1.0-SNAPSHOT + + + config + discovery + ui + person + some + monitor + + + + UTF-8 + 1.8 + + + + + org.springframework.cloud + spring-cloud-starter-parent + Angel.SR3 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + com.spotify + docker-maven-plugin + 0.2.9 + + true + + + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + \ No newline at end of file diff --git a/springboot-springCloud/some/pom.xml b/springboot-springCloud/some/pom.xml new file mode 100644 index 0000000..703a886 --- /dev/null +++ b/springboot-springCloud/some/pom.xml @@ -0,0 +1,29 @@ + + + + springCloud + com.abel + 1.0-SNAPSHOT + + 4.0.0 + + some + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-config-client + + + org.springframework.cloud + spring-cloud-starter-eureka + + + + \ No newline at end of file diff --git a/springboot-springCloud/some/src/main/java/com/abel/SomeApplication.java b/springboot-springCloud/some/src/main/java/com/abel/SomeApplication.java new file mode 100644 index 0000000..842ab86 --- /dev/null +++ b/springboot-springCloud/some/src/main/java/com/abel/SomeApplication.java @@ -0,0 +1,27 @@ +package com.abel; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Created by yangyibo on 2018/6/28. + */ +@SpringBootApplication +@EnableDiscoveryClient +@RestController +public class SomeApplication { + @Value("${my.message}") //Value 值来自于config server + private String message; + + @RequestMapping(value = "/getsome") + public String getsome(){ + return message; + } + public static void main(String[] args) { + SpringApplication.run(SomeApplication.class, args); + } +} diff --git a/springboot-springCloud/some/src/main/resources/application.yml b/springboot-springCloud/some/src/main/resources/application.yml new file mode 100644 index 0000000..b67e63e --- /dev/null +++ b/springboot-springCloud/some/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8083 diff --git a/springboot-springCloud/some/src/main/resources/bootstrap.yml b/springboot-springCloud/some/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..28ef2cb --- /dev/null +++ b/springboot-springCloud/some/src/main/resources/bootstrap.yml @@ -0,0 +1,15 @@ +spring: + application: + name: some + cloud: + config: + enabled: true + discovery: + enabled: true + service-id: CONFIG +eureka: + instance: + non-secure-port: ${server.port:8083} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/some/target/classes/application.yml b/springboot-springCloud/some/target/classes/application.yml new file mode 100644 index 0000000..b67e63e --- /dev/null +++ b/springboot-springCloud/some/target/classes/application.yml @@ -0,0 +1,2 @@ +server: + port: 8083 diff --git a/springboot-springCloud/some/target/classes/bootstrap.yml b/springboot-springCloud/some/target/classes/bootstrap.yml new file mode 100644 index 0000000..28ef2cb --- /dev/null +++ b/springboot-springCloud/some/target/classes/bootstrap.yml @@ -0,0 +1,15 @@ +spring: + application: + name: some + cloud: + config: + enabled: true + discovery: + enabled: true + service-id: CONFIG +eureka: + instance: + non-secure-port: ${server.port:8083} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/ui/pom.xml b/springboot-springCloud/ui/pom.xml new file mode 100644 index 0000000..3a577e7 --- /dev/null +++ b/springboot-springCloud/ui/pom.xml @@ -0,0 +1,63 @@ + + + + springCloud + com.abel + 1.0-SNAPSHOT + + 4.0.0 + + ui + + + + org.springframework.cloud + spring-cloud-starter + + + org.springframework.cloud + spring-cloud-starter-hystrix + + + org.springframework.cloud + spring-cloud-starter-zuul + + + org.springframework.cloud + spring-cloud-config-client + + + org.springframework.cloud + spring-cloud-starter-eureka + + + org.springframework.cloud + spring-cloud-starter-feign + + + org.springframework.cloud + spring-cloud-starter-ribbon + + + + org.webjars + bootstrap + + + org.webjars + angularjs + 1.3.15 + + + org.webjars + angular-ui-router + 0.2.13 + + + org.webjars + jquery + + + \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/java/com/abel/UiApplication.java b/springboot-springCloud/ui/src/main/java/com/abel/UiApplication.java new file mode 100644 index 0000000..ac0e602 --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/UiApplication.java @@ -0,0 +1,22 @@ +package com.abel; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +/** + * Created by yangyibo on 2018/6/29. + */ +@SpringBootApplication +@EnableEurekaClient +@EnableFeignClients //开启fegin 客户端支持 +@EnableCircuitBreaker //开启CircuitBreaker的支持 +@EnableZuulProxy //开启网关代理支持 +public class UiApplication { + public static void main(String[] args) { + SpringApplication.run(UiApplication.class, args); + } +} diff --git a/springboot-springCloud/ui/src/main/java/com/abel/bean/Person.java b/springboot-springCloud/ui/src/main/java/com/abel/bean/Person.java new file mode 100644 index 0000000..0c17e08 --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/bean/Person.java @@ -0,0 +1,39 @@ +package com.abel.bean; + +/** + * Created by yangyibo on 2018/6/29. + */ +public class Person { + private Long id; + + private String name; + + + public Person() { + super(); + } + + public Person(String name) { + super(); + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + +} \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/java/com/abel/controller/UiController.java b/springboot-springCloud/ui/src/main/java/com/abel/controller/UiController.java new file mode 100644 index 0000000..0c361f7 --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/controller/UiController.java @@ -0,0 +1,34 @@ +package com.abel.controller; + +import com.abel.bean.Person; +import com.abel.service.PersonHystrixService; +import com.abel.service.SomeHystrixService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * Created by yangyibo on 2018/6/29. + */ +@RestController +public class UiController { + @Autowired + private SomeHystrixService someHystrixService; + + @Autowired + private PersonHystrixService personHystrixService; + + @RequestMapping("/dispatch") + public List sendMessage(@RequestBody String personName) { + return personHystrixService.save(personName); + } + + @RequestMapping(value = "/getsome",produces={MediaType.TEXT_PLAIN_VALUE}) + public String getSome(){ + return someHystrixService.getSome(); + } +} diff --git a/springboot-springCloud/ui/src/main/java/com/abel/service/PersonHystrixService.java b/springboot-springCloud/ui/src/main/java/com/abel/service/PersonHystrixService.java new file mode 100644 index 0000000..161ecc6 --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/service/PersonHystrixService.java @@ -0,0 +1,31 @@ +package com.abel.service; + +import com.abel.bean.Person; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +/** + * Created by yangyibo on 2018/6/29. + * 调用person service的断路器 + */ +@Service +public class PersonHystrixService { + + @Autowired + PersonService personService; + + @HystrixCommand(fallbackMethod = "fallbackSave") //使用HystrixCommand的fallbackMethod参数指定,调用失败的时候调用后备方法 fallbackMethod + public List save(String name) { + return personService.save(name); + } + + public List fallbackSave(String name){ + List list = new ArrayList(); + Person p = new Person(name+"没有保存成功,Person Service 故障"); + list.add(p); + return list; + } +} diff --git a/springboot-springCloud/ui/src/main/java/com/abel/service/PersonService.java b/springboot-springCloud/ui/src/main/java/com/abel/service/PersonService.java new file mode 100644 index 0000000..c5989fe --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/service/PersonService.java @@ -0,0 +1,24 @@ +package com.abel.service; + +import com.abel.bean.Person; +import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.util.List; + +/** + * Created by yangyibo on 2018/6/29. + * 使用 Feign 调用person service + * 我们只需要通过简单在接口中声明方法即可调用Person的 Rest服务 + */ +@FeignClient("person") +public interface PersonService { + @RequestMapping(method = RequestMethod.POST, value = "/save", + produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + List save(@RequestBody String name); +} diff --git a/springboot-springCloud/ui/src/main/java/com/abel/service/SomeHystrixService.java b/springboot-springCloud/ui/src/main/java/com/abel/service/SomeHystrixService.java new file mode 100644 index 0000000..6453334 --- /dev/null +++ b/springboot-springCloud/ui/src/main/java/com/abel/service/SomeHystrixService.java @@ -0,0 +1,26 @@ +package com.abel.service; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +/** + * Created by yangyibo on 2018/6/29. + * 使用ribbon 调用some service 并使用断路器 + */ +@Service +public class SomeHystrixService { + + @Autowired + RestTemplate restTemplate; // springboot 下使用ribbon ,只需注入一个 RestTemplate,springboot 已经为我们做好了配置 + + @HystrixCommand(fallbackMethod = "fallbackSome") //HystrixCommand 的参数指定,当调用失败时,使用备用方法fallbackMethod + public String getSome() { + return restTemplate.getForObject("http://some/getsome", String.class); + } + + public String fallbackSome(){ + return "some service模块故障"; + } +} diff --git a/springboot-springCloud/ui/src/main/resources/application.yml b/springboot-springCloud/ui/src/main/resources/application.yml new file mode 100644 index 0000000..b6c3bb3 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/application.yml @@ -0,0 +1,6 @@ +server: + port: 80 + + + + diff --git a/springboot-springCloud/ui/src/main/resources/bootstrap.yml b/springboot-springCloud/ui/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..ae4ed53 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/bootstrap.yml @@ -0,0 +1,10 @@ +spring: + application: + name: ui + +eureka: + instance: + non-secure-port: ${server.port:80} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/resources/static/css/application.css b/springboot-springCloud/ui/src/main/resources/static/css/application.css new file mode 100644 index 0000000..e587952 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/css/application.css @@ -0,0 +1,15 @@ +body { + padding-top: 60px; +} + +h1, h2, h3, h4, h5, h6 { + font-family: microsoft yahei; +} +p, div { + font-family: microsoft yahei; + font-size: 12px; +} + +.longtext { + word-break:break-all; +} diff --git a/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.eot b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..4a4ca86 Binary files /dev/null and b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.eot differ diff --git a/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.svg b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..e3e2dc7 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..67fa00b Binary files /dev/null and b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.ttf differ diff --git a/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.woff b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..8c54182 Binary files /dev/null and b/springboot-springCloud/ui/src/main/resources/static/fonts/glyphicons-halflings-regular.woff differ diff --git a/springboot-springCloud/ui/src/main/resources/static/index.html b/springboot-springCloud/ui/src/main/resources/static/index.html new file mode 100644 index 0000000..1af400a --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/index.html @@ -0,0 +1,36 @@ + + + + + 原生云应用 + + + + + + + + + + +

+
+
+
+
+
+ + \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/resources/static/js/app.js b/springboot-springCloud/ui/src/main/resources/static/js/app.js new file mode 100644 index 0000000..db06c5d --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/js/app.js @@ -0,0 +1,49 @@ +var uiApp = angular.module("uiApp", ["ui.router"]); + +uiApp.config(function ($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise("person"); + + $stateProvider + .state('person', { + url: '/person', + templateUrl: '/tpl/person.html', + controller: 'PersonController' + }) + .state('some',{ + url:'/some', + templateUrl: '/tpl/some.html', + controller: 'SomeController' + }); +}); + + +uiApp.controller("PersonController", function ($scope, $http) { + + $scope.people = ""; + $scope.errorMessage = ""; + + $scope.getMessageResponse = function(personName) { + $http.post('/dispatch', personName).success(function(data){ + $scope.people = data; + $scope.errorMessage = ""; + }).error(function() { + $scope.errorMessage = "错误"; + }); + } + +}); + + +uiApp.controller("SomeController", function ($scope, $http) { + $scope.str = ""; + $scope.errorMessage = ""; + +$scope.getSome = function(){ + $http.get('/getsome').success(function(data){ + $scope.str = data; + $scope.errorMessage = ""; + }).error(function() { + $scope.errorMessage = "错误"; + }); +} +}); \ No newline at end of file diff --git a/springboot-springCloud/ui/src/main/resources/static/tpl/person.html b/springboot-springCloud/ui/src/main/resources/static/tpl/person.html new file mode 100644 index 0000000..3382e34 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/tpl/person.html @@ -0,0 +1,34 @@ +
+
+
+
+

通过Person Service保存person

+
+
+
+
+
+
+

+ +

+
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
diff --git a/springboot-springCloud/ui/src/main/resources/static/tpl/some.html b/springboot-springCloud/ui/src/main/resources/static/tpl/some.html new file mode 100644 index 0000000..7e20b79 --- /dev/null +++ b/springboot-springCloud/ui/src/main/resources/static/tpl/some.html @@ -0,0 +1,27 @@ +
+
+
+
+

从 Some Service获得字符

+
+
+
+
+
+
+

+ +

+
+
+
+ +
+ +
+ +
+
+
+
+
diff --git a/springboot-springCloud/ui/target/classes/application.yml b/springboot-springCloud/ui/target/classes/application.yml new file mode 100644 index 0000000..b6c3bb3 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/application.yml @@ -0,0 +1,6 @@ +server: + port: 80 + + + + diff --git a/springboot-springCloud/ui/target/classes/bootstrap.yml b/springboot-springCloud/ui/target/classes/bootstrap.yml new file mode 100644 index 0000000..ae4ed53 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/bootstrap.yml @@ -0,0 +1,10 @@ +spring: + application: + name: ui + +eureka: + instance: + non-secure-port: ${server.port:80} + client: + service-url: + defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ \ No newline at end of file diff --git a/springboot-springCloud/ui/target/classes/static/css/application.css b/springboot-springCloud/ui/target/classes/static/css/application.css new file mode 100644 index 0000000..e587952 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/css/application.css @@ -0,0 +1,15 @@ +body { + padding-top: 60px; +} + +h1, h2, h3, h4, h5, h6 { + font-family: microsoft yahei; +} +p, div { + font-family: microsoft yahei; + font-size: 12px; +} + +.longtext { + word-break:break-all; +} diff --git a/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.eot b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..4a4ca86 Binary files /dev/null and b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.eot differ diff --git a/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.svg b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..e3e2dc7 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.ttf b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..67fa00b Binary files /dev/null and b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.ttf differ diff --git a/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.woff b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..8c54182 Binary files /dev/null and b/springboot-springCloud/ui/target/classes/static/fonts/glyphicons-halflings-regular.woff differ diff --git a/springboot-springCloud/ui/target/classes/static/index.html b/springboot-springCloud/ui/target/classes/static/index.html new file mode 100644 index 0000000..1af400a --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/index.html @@ -0,0 +1,36 @@ + + + + + 原生云应用 + + + + + + + + + + + +
+
+
+
+
+ + \ No newline at end of file diff --git a/springboot-springCloud/ui/target/classes/static/js/app.js b/springboot-springCloud/ui/target/classes/static/js/app.js new file mode 100644 index 0000000..db06c5d --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/js/app.js @@ -0,0 +1,49 @@ +var uiApp = angular.module("uiApp", ["ui.router"]); + +uiApp.config(function ($stateProvider, $urlRouterProvider) { + $urlRouterProvider.otherwise("person"); + + $stateProvider + .state('person', { + url: '/person', + templateUrl: '/tpl/person.html', + controller: 'PersonController' + }) + .state('some',{ + url:'/some', + templateUrl: '/tpl/some.html', + controller: 'SomeController' + }); +}); + + +uiApp.controller("PersonController", function ($scope, $http) { + + $scope.people = ""; + $scope.errorMessage = ""; + + $scope.getMessageResponse = function(personName) { + $http.post('/dispatch', personName).success(function(data){ + $scope.people = data; + $scope.errorMessage = ""; + }).error(function() { + $scope.errorMessage = "错误"; + }); + } + +}); + + +uiApp.controller("SomeController", function ($scope, $http) { + $scope.str = ""; + $scope.errorMessage = ""; + +$scope.getSome = function(){ + $http.get('/getsome').success(function(data){ + $scope.str = data; + $scope.errorMessage = ""; + }).error(function() { + $scope.errorMessage = "错误"; + }); +} +}); \ No newline at end of file diff --git a/springboot-springCloud/ui/target/classes/static/tpl/person.html b/springboot-springCloud/ui/target/classes/static/tpl/person.html new file mode 100644 index 0000000..3382e34 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/tpl/person.html @@ -0,0 +1,34 @@ +
+
+
+
+

通过Person Service保存person

+
+
+
+
+
+
+

+ +

+
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
diff --git a/springboot-springCloud/ui/target/classes/static/tpl/some.html b/springboot-springCloud/ui/target/classes/static/tpl/some.html new file mode 100644 index 0000000..7e20b79 --- /dev/null +++ b/springboot-springCloud/ui/target/classes/static/tpl/some.html @@ -0,0 +1,27 @@ +
+
+
+
+

从 Some Service获得字符

+
+
+
+
+
+
+

+ +

+
+
+
+ +
+ +
+ +
+
+
+
+
diff --git a/springboot-springSecurity2/pom.xml b/springboot-springSecurity2/pom.xml index 65f18a9..2d8a95a 100644 --- a/springboot-springSecurity2/pom.xml +++ b/springboot-springSecurity2/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.us - springboot-security + springboot-security2 1.0-SNAPSHOT @@ -44,7 +44,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-springSecurity2/src/main/java/com/us/example/config/WebSecurityConfig.java b/springboot-springSecurity2/src/main/java/com/us/example/config/WebSecurityConfig.java index 75a6c38..5e9b09d 100644 --- a/springboot-springSecurity2/src/main/java/com/us/example/config/WebSecurityConfig.java +++ b/springboot-springSecurity2/src/main/java/com/us/example/config/WebSecurityConfig.java @@ -2,8 +2,6 @@ import com.us.example.security.CustomUserService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; @@ -11,10 +9,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.session.SessionRegistry; -import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.web.session.HttpSessionEventPublisher; /** * Created by yangyibo on 17/1/18. @@ -26,8 +21,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserService customUserService; - @Autowired - SessionRegistry sessionRegistry; + @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { @@ -50,15 +44,12 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/**") .permitAll() .and() - .sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry); - http.httpBasic(); + .sessionManagement() + .and() + .httpBasic(); } - @Bean - public SessionRegistry getSessionRegistry(){ - SessionRegistry sessionRegistry=new SessionRegistryImpl(); - return sessionRegistry; - } + } diff --git a/springboot-springSecurity2/src/main/java/com/us/example/controller/LoginController.java b/springboot-springSecurity2/src/main/java/com/us/example/controller/LoginController.java index 278733e..bca4d70 100644 --- a/springboot-springSecurity2/src/main/java/com/us/example/controller/LoginController.java +++ b/springboot-springSecurity2/src/main/java/com/us/example/controller/LoginController.java @@ -1,59 +1,29 @@ package com.us.example.controller; import com.us.example.domain.SysUser; -import com.us.example.util.SessionUtil; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.Authentication; import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.session.SessionRegistry; -import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.RestController; /** * Created by yangyibo on 17/3/1. */ -@Controller +@RestController public class LoginController { - @Autowired - private SessionRegistry sessionRegistry; - /** - * http://localhost:8080/login - * http://localhost:8080/logout - * @param loginedUser - * @param logout - * @return - */ + @RequestMapping(value = "/login") @ResponseBody //用户名密码是用base64 加密 原文为 admin:admin 即 用户名:密码 内容是放在request.getHeader 的 "authorization" 中 - public Object login(@AuthenticationPrincipal SysUser loginedUser, @RequestParam(name = "logout", required = false) String logout,HttpServletRequest request) { + public Object login(@AuthenticationPrincipal SysUser loginedUser, @RequestParam(name = "logout", required = false) String logout) { if (logout != null) { - return "logout"; + return null; } if (loginedUser != null) { - SessionUtil.dropPreviousUser(request,sessionRegistry,loginedUser); return loginedUser; } return null; } - -// 此方法未用到 -// @RequestMapping(value="/logout", method = RequestMethod.GET) -// @ResponseBody -// public String logout (HttpServletRequest request, HttpServletResponse response) { -// Authentication auth = SecurityContextHolder.getContext().getAuthentication(); -// if (auth != null){ -// new SecurityContextLogoutHandler().logout(request, response, auth); -// } -// return "logout ok"; -// } } diff --git a/springboot-springSecurity2/src/main/java/com/us/example/domain/SysUser.java b/springboot-springSecurity2/src/main/java/com/us/example/domain/SysUser.java index 23793b8..697cf8a 100644 --- a/springboot-springSecurity2/src/main/java/com/us/example/domain/SysUser.java +++ b/springboot-springSecurity2/src/main/java/com/us/example/domain/SysUser.java @@ -97,4 +97,5 @@ public Collection getAuthorities() { public void setGrantedAuthorities(List authorities) { this.authorities = authorities; } + } diff --git a/springboot-springSecurity2/src/main/java/com/us/example/service/UserService.java b/springboot-springSecurity2/src/main/java/com/us/example/service/UserService.java index 7a75814..d8da056 100644 --- a/springboot-springSecurity2/src/main/java/com/us/example/service/UserService.java +++ b/springboot-springSecurity2/src/main/java/com/us/example/service/UserService.java @@ -2,6 +2,7 @@ import com.us.example.dao.UserDao; import com.us.example.domain.SysUser; +import com.us.example.util.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; @@ -17,7 +18,7 @@ public class UserService { public SysUser create(SysUser sysUser){ //进行加密 BCryptPasswordEncoder encoder =new BCryptPasswordEncoder(); - sysUser.setPassword(encoder.encode(sysUser.getRawPassword().trim())); + sysUser.setPassword(encoder.encode(MD5Util.encode(sysUser.getRawPassword().trim()))); userDao.create(sysUser); return sysUser; } diff --git a/springboot-springSecurity2/src/main/java/com/us/example/util/BCryptPasswordEncoderTest.java b/springboot-springSecurity2/src/main/java/com/us/example/util/BCryptPasswordEncoderTest.java index 5edb03b..0b96976 100644 --- a/springboot-springSecurity2/src/main/java/com/us/example/util/BCryptPasswordEncoderTest.java +++ b/springboot-springSecurity2/src/main/java/com/us/example/util/BCryptPasswordEncoderTest.java @@ -9,7 +9,21 @@ public class BCryptPasswordEncoderTest { public static void main(String[] args) { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); - System.out.println(encoder.encode("abel")); - System.out.println(encoder.encode("admin")); + System.out.println("encoder: " + encoder.encode("abel")); + System.out.println("encoder: " + encoder.encode("admin")); + + if (encoder.matches("abel", "$2a$10$IAz6WzJ314LH1NXq7Rf.dOYPP2uvzk08g.eAl9l4DRG4YsxavEV4W")) { + System.out.println("encoder: true"); + } + + + System.out.println("------------华丽的分割线-----------------------"); + String Md5Password = MD5Util.encode("abel"); + System.out.println("Md5Password: " + Md5Password); + System.out.println("encoder: " + encoder.encode(Md5Password)); + if (encoder.matches(Md5Password, "$2a$10$37MXEfzlbtC6QSsRTlRhIOmykMRJtO5mU8Y.yiJBjy1x4WYWFR5gG")) { + System.out.println("Md5Password: true"); + } + } } diff --git a/springboot-springSecurity2/src/main/java/com/us/example/util/MD5Util.java b/springboot-springSecurity2/src/main/java/com/us/example/util/MD5Util.java new file mode 100644 index 0000000..da620ec --- /dev/null +++ b/springboot-springSecurity2/src/main/java/com/us/example/util/MD5Util.java @@ -0,0 +1,45 @@ +package com.us.example.util; + +import java.security.MessageDigest; + +/** + * Created by yangyibo on 9/8/17. + */ +public class MD5Util { + private static final String SALT = "salt"; + + public static String encode(String password) { + password = password + SALT; + return processEncode(password); + } + + public static String processEncode(String password) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (Exception e) { + throw new RuntimeException(e); + } + char[] charArray = password.toCharArray(); + byte[] byteArray = new byte[charArray.length]; + + for (int i = 0; i < charArray.length; i++) + byteArray[i] = (byte) charArray[i]; + byte[] md5Bytes = md5.digest(byteArray); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++) { + int val = ((int) md5Bytes[i]) & 0xff; + if (val < 16) { + hexValue.append("0"); + } + + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } + + public static void main(String[] args) { + System.out.println(MD5Util.encode("abel")); + System.out.println(MD5Util.encode("admin")); + } +} diff --git a/springboot-springSecurity2/src/main/java/com/us/example/util/SessionUtil.java b/springboot-springSecurity2/src/main/java/com/us/example/util/SessionUtil.java deleted file mode 100644 index 5127ab4..0000000 --- a/springboot-springSecurity2/src/main/java/com/us/example/util/SessionUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.us.example.util; - -import com.us.example.domain.SysUser; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.session.SessionInformation; -import org.springframework.security.core.session.SessionRegistry; -import org.springframework.security.web.authentication.session.SessionAuthenticationException; - -import javax.servlet.http.HttpServletRequest; -import java.util.List; - -/** - * Created by yangyibo on 8/23/17. - */ -public class SessionUtil { - /** - * 辨别用户是否已经登录 - * - * @param request - * @param sessionRegistry - * @param loginedUser - */ - public static void deleteSameUser(HttpServletRequest request, SessionRegistry sessionRegistry, SysUser loginedUser) { - SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT"); - List sessionsInfo; - sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), true); - String currentSessionId; - if (null != sessionsInfo && sessionsInfo.size() == 0) { - sessionRegistry.registerNewSession(request.getSession().getId(), sc.getAuthentication().getPrincipal()); - sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false); - } - currentSessionId = sessionsInfo.get(0).getSessionId(); - List o = sessionRegistry.getAllPrincipals(); - for (Object principal : o) { - if (principal instanceof SysUser && (loginedUser.getUsername().equals(((SysUser) principal).getUsername()))) { - List oldSessionsInfo = sessionRegistry.getAllSessions(principal, false); - if (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) { - for (SessionInformation sessionInformation : sessionsInfo) { - //当前session失效 - sessionInformation.expireNow(); - sc.setAuthentication(null); - sessionRegistry.removeSessionInformation(currentSessionId); - throw new SessionAuthenticationException("当前用户已经在线,登录失败!!!"); - } - } - } - } - } - - /** - * 剔除前一个用户 - * - * @param request - * @param sessionRegistry - * @param loginedUser - */ - public static void dropPreviousUser(HttpServletRequest request, SessionRegistry sessionRegistry, SysUser loginedUser) { - SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT"); - List sessionsInfo; - sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), true); - String currentSessionId; - currentSessionId = sessionsInfo.get(0).getSessionId(); - List o = sessionRegistry.getAllPrincipals(); - for (Object principal : o) { - if (principal instanceof SysUser && (loginedUser.getUsername().equals(((SysUser) principal).getUsername()))) { - List oldSessionsInfo = sessionRegistry.getAllSessions(principal, false); - if (null != oldSessionsInfo && oldSessionsInfo.size() > 0 && !oldSessionsInfo.get(0).getSessionId().equals(currentSessionId)) { - for (SessionInformation sessionInformation : oldSessionsInfo) { - //发送消息通知 - //当前session失效 - sessionInformation.expireNow(); - } - } - } - } - } - - - /** - * session 失效 - * - * @param request - * @param sessionRegistry - */ - public static void expireSession(HttpServletRequest request, SysUser user, SessionRegistry sessionRegistry) { - List sessionsInfo = null; - if (null != user) { - List o = sessionRegistry.getAllPrincipals(); - for (Object principal : o) { - if (principal instanceof SysUser && (user.getUsername().equals(((SysUser) principal).getUsername()))) { - sessionsInfo = sessionRegistry.getAllSessions(principal, false); - } - } - } else if (null != request) { - SecurityContext sc = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT"); - if (null != sc.getAuthentication().getPrincipal()) { - sessionsInfo = sessionRegistry.getAllSessions(sc.getAuthentication().getPrincipal(), false); - sc.setAuthentication(null); - } - } - if (null != sessionsInfo && sessionsInfo.size() > 0) { - for (SessionInformation sessionInformation : sessionsInfo) { - //当前session失效 - sessionInformation.expireNow(); - sessionRegistry.removeSessionInformation(sessionInformation.getSessionId()); - } - } - } -} diff --git a/springboot-springSecurity2/src/main/resources/application.properties b/springboot-springSecurity2/src/main/resources/application.properties index 3033022..9db1bfa 100755 --- a/springboot-springSecurity2/src/main/resources/application.properties +++ b/springboot-springSecurity2/src/main/resources/application.properties @@ -3,7 +3,7 @@ ms.db.url=jdbc:mysql://localhost:3306/cache?characterEncoding=utf-8&useSSL=false ms.db.username=root ms.db.password=admin ms.db.maxActive=500 -server.port=8080 +server.port=8099 logging.level.org.springframework.security= INFO spring.thymeleaf.cache=false diff --git a/springboot-springSecurity3/pom.xml b/springboot-springSecurity3/pom.xml index 1b5ef59..8ef9b02 100644 --- a/springboot-springSecurity3/pom.xml +++ b/springboot-springSecurity3/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.us - springboot-security + springboot-security3 1.0-SNAPSHOT @@ -49,7 +49,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 commons-logging diff --git a/springboot-springSecurity4/pom.xml b/springboot-springSecurity4/pom.xml index 45a72ea..ef987f6 100644 --- a/springboot-springSecurity4/pom.xml +++ b/springboot-springSecurity4/pom.xml @@ -48,7 +48,7 @@ com.mchange c3p0 - 0.9.5.2 + 0.9.5.4 diff --git a/springboot-swagger-ui/pom.xml b/springboot-swagger-ui/pom.xml new file mode 100644 index 0000000..e0fc743 --- /dev/null +++ b/springboot-swagger-ui/pom.xml @@ -0,0 +1,82 @@ + + + 4.0.0 + + com.abel + springboot-swagger-ui + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.3.0.RELEASE + + + + com.abel.Application + + 1.8 + 1.8 + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + + + + mysql + mysql-connector-java + 6.0.5 + + + com.mchange + c3p0 + 0.9.5.4 + + + commons-logging + commons-logging + + + + + + + org.apache.commons + commons-lang3 + 3.4 + + + + + + io.springfox + + springfox-swagger2 + + 2.2.2 + + + + + + io.springfox + + springfox-swagger-ui + + 2.2.2 + + + + \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/Application.java b/springboot-swagger-ui/src/main/java/com/abel/example/Application.java new file mode 100644 index 0000000..33cef8b --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/Application.java @@ -0,0 +1,22 @@ +package com.abel.example; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.ComponentScan; + +import static org.springframework.boot.SpringApplication.run; + +/** + * Created by yangyibo on 17/1/17. + */ + +@ComponentScan(basePackages ="com.abel.example") +@SpringBootApplication +@EnableCaching +public class Application { + public static void main(String[] args) { + ConfigurableApplicationContext run = run(Application.class, args); + } + +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/Swagger2.java b/springboot-swagger-ui/src/main/java/com/abel/example/Swagger2.java new file mode 100644 index 0000000..37e38a9 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/Swagger2.java @@ -0,0 +1,52 @@ +package com.abel.example; + +import org.springframework.context.annotation.Bean; + +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** + * Created by yangyibo on 2018/9/7. + */ +@Configuration +@EnableSwagger2 +public class Swagger2 { + /** + * 创建API应用 + * apiInfo() 增加API相关信息 + * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现, + * 本例采用指定扫描的包路径来定义指定要建立API的目录。 + * + * @return + */ + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.abel.example.controller")) + .paths(PathSelectors.any()) + .build(); + } + + /** + * 创建该API的基本信息(这些基本信息会展现在文档页面中) + * 访问地址:http://项目实际地址/swagger-ui.html + * @return + */ + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("Spring Boot中使用Swagger2构建RESTful APIs") + .description("更多请关注https://blog.csdn.net/u012373815") + .termsOfServiceUrl("https://blog.csdn.net/u012373815") + .contact("abel") + .version("1.0") + .build(); + } +} diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/bean/User.java b/springboot-swagger-ui/src/main/java/com/abel/example/bean/User.java new file mode 100644 index 0000000..7d2431f --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/bean/User.java @@ -0,0 +1,149 @@ +package com.abel.example.bean; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +@Entity +@Table(name = "sec_user") +public class User { + @Id + @GeneratedValue + private Long id; + @Column(name = "name") + private String name; + @Column(name = "password") + private String password; + @Column(name = "username") + private String username; + @Column(name = "email") + private String email; + @Column(name = "mobilephone") + private String mobilephone; + @Column(name = "telephone") + private String telephone; + @Column(name = "user_type") + private Integer userType; + @Column(name = "create_by") + private String createBy; + @Column(name = "create_time") + private Date createTime; + @Column(name = "update_by") + private String updateBy; + @Column(name = "update_time") + private Date updateTime; + @Column(name = "disabled") + private Integer disabled; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @JsonIgnore + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getMobilephone() { + return mobilephone; + } + + public void setMobilephone(String mobilephone) { + this.mobilephone = mobilephone; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public Integer getUserType() { + return userType; + } + + public void setUserType(Integer userType) { + this.userType = userType; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Integer getDisabled() { + return disabled; + } + + public void setDisabled(Integer disabled) { + this.disabled = disabled; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/config/DBConfig.java b/springboot-swagger-ui/src/main/java/com/abel/example/config/DBConfig.java new file mode 100644 index 0000000..65207c3 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/config/DBConfig.java @@ -0,0 +1,35 @@ +package com.abel.example.config; + +import java.beans.PropertyVetoException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import com.mchange.v2.c3p0.ComboPooledDataSource; + +@Configuration +public class DBConfig { + @Autowired + private Environment env; + + + @Bean(name="dataSource") + public ComboPooledDataSource dataSource() throws PropertyVetoException { + ComboPooledDataSource dataSource = new ComboPooledDataSource(); + dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); + dataSource.setJdbcUrl(env.getProperty("ms.db.url")); + dataSource.setUser(env.getProperty("ms.db.username")); + dataSource.setPassword(env.getProperty("ms.db.password")); + dataSource.setMaxPoolSize(20); + dataSource.setMinPoolSize(5); + dataSource.setInitialPoolSize(10); + dataSource.setMaxIdleTime(300); + dataSource.setAcquireIncrement(5); + dataSource.setIdleConnectionTestPeriod(60); + + return dataSource; + } + +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/config/JpaConfig.java b/springboot-swagger-ui/src/main/java/com/abel/example/config/JpaConfig.java new file mode 100644 index 0000000..5e90ca3 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/config/JpaConfig.java @@ -0,0 +1,58 @@ +package com.abel.example.config; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableJpaRepositories("com.abel.example.dao") +@EnableTransactionManagement +@ComponentScan +public class JpaConfig { + + @Autowired + private DataSource dataSource; + + @Bean + public EntityManagerFactory entityManagerFactory() { + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + //vendorAdapter.setShowSql(true); + //vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan("com.abel.example.bean"); + factory.setDataSource(dataSource); + + + Map jpaProperties = new HashMap(); + jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); + jpaProperties.put("hibernate.jdbc.batch_size",50); + //jpaProperties.put("hibernate.show_sql",true); + + factory.setJpaPropertyMap(jpaProperties); + factory.afterPropertiesSet(); + return factory.getObject(); + } + + @Bean + public PlatformTransactionManager transactionManager() { + + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory()); + return txManager; + } +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/controller/UserController.java b/springboot-swagger-ui/src/main/java/com/abel/example/controller/UserController.java new file mode 100644 index 0000000..83c2a80 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/controller/UserController.java @@ -0,0 +1,131 @@ +package com.abel.example.controller; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +import com.abel.example.bean.User; +import io.swagger.annotations.*; +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + + +import com.abel.example.service.UserService; +import com.abel.example.util.CommonUtil; + + +@Controller +@RequestMapping(value = "/users") +@Api(value = "用户的增删改查") +public class UserController { + + @Autowired + private UserService userService; + + + /** + * 查询所有的用户 + * api :localhost:8099/users + * @return + */ + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "获取用户列表,目前没有分页") + public ResponseEntity findAll() { + return new ResponseEntity<>(userService.listUsers(), HttpStatus.OK); + } + + /** + * 通过id 查找用户 + * api :localhost:8099/users/1 + * @param id + * @return + */ + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + @ResponseBody + @ApiOperation(value = "通过id获取用户信息", notes="返回用户信息") + public ResponseEntity getUserById(@PathVariable Integer id) { + return new ResponseEntity<>(userService.getUserById(Long.valueOf(id)), HttpStatus.OK); + } + + + /** + * 通过spring data jpa 调用方法 + * api :localhost:8099/users/byname?username=xxx + * 通过用户名查找用户 + * @param request + * @return + */ + @RequestMapping(value = "/byname", method = RequestMethod.GET) + @ResponseBody + @ApiImplicitParam(paramType = "query",name= "username" ,value = "用户名",dataType = "string") + @ApiOperation(value = "通过用户名获取用户信息", notes="返回用户信息") + public ResponseEntity getUserByUserName(HttpServletRequest request) { + Map map = CommonUtil.getParameterMap(request); + String username = (String) map.get("username"); + return new ResponseEntity<>(userService.getUserByUserName(username), HttpStatus.OK); + } + + /** + * 通过spring data jpa 调用方法 + * api :localhost:8099/users/byUserNameContain?username=xxx + * 通过用户名模糊查询 + * @param request + * @return + */ + @RequestMapping(value = "/byUserNameContain", method = RequestMethod.GET) + @ResponseBody + @ApiImplicitParam(paramType = "query",name= "username" ,value = "用户名",dataType = "string") + @ApiOperation(value = "通过用户名模糊搜索用户信息", notes="返回用户信息") + public ResponseEntity getUsers(HttpServletRequest request) { + Map map = CommonUtil.getParameterMap(request); + String username = (String) map.get("username"); + return new ResponseEntity<>(userService.getByUsernameContaining(username), HttpStatus.OK); + } + + + /** + * 添加用户啊 + * api :localhost:8099/users + * + * @param user + * @return + */ + @RequestMapping(method = RequestMethod.POST) + @ResponseBody + @ApiModelProperty(value="user",notes = "用户信息的json串") + @ApiOperation(value = "新增用户", notes="返回新增的用户信息") + public ResponseEntity saveUser(@RequestBody User user) { + return new ResponseEntity<>(userService.saveUser(user), HttpStatus.OK); + } + + /** + * 修改用户信息 + * api :localhost:8099/users + * @param user + * @return + */ + @RequestMapping(method = RequestMethod.PUT) + @ResponseBody + @ApiModelProperty(value="user",notes = "修改后用户信息的json串") + @ApiOperation(value = "新增用户", notes="返回新增的用户信息") + public ResponseEntity updateUser(@RequestBody User user) { + return new ResponseEntity<>(userService.updateUser(user), HttpStatus.OK); + } + + /** + * 通过ID删除用户 + * api :localhost:8099/users/2 + * @param id + * @return + */ + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + @ResponseBody + @ApiOperation(value = "通过id删除用户信息", notes="返回删除状态1 成功 0 失败") + public ResponseEntity deleteUser(@PathVariable Integer id) { + return new ResponseEntity<>(userService.removeUser(id.longValue()), HttpStatus.OK); + } +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/dao/UserJpaDao.java b/springboot-swagger-ui/src/main/java/com/abel/example/dao/UserJpaDao.java new file mode 100644 index 0000000..9868bb9 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/dao/UserJpaDao.java @@ -0,0 +1,34 @@ +package com.abel.example.dao; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.abel.example.bean.User; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * The Interface UserJpaDao. + * + * @author abel + */ +public interface UserJpaDao extends JpaRepository { + + /** + * Find by name. + * + * @param name the name + * @return the user + */ + User findByName(String name); + + User getOne(Long id); + + List findByUsernameContaining(String username); + + User getByUsernameIs(String username); + + @Query("select s from User s where name like CONCAT('%',:name,'%')") + List findByNameLike(@Param("name") String name); +} \ No newline at end of file diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/service/UserService.java b/springboot-swagger-ui/src/main/java/com/abel/example/service/UserService.java new file mode 100644 index 0000000..9f84083 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/service/UserService.java @@ -0,0 +1,55 @@ +package com.abel.example.service; + +import java.util.List; + +import com.abel.example.bean.User; + +/** + * The Interface UserService. + */ +public interface UserService { + + /** + * Gets the user by name. + * + * @param username the user name + * @return the user by name + */ + public User getUserByUserName(String username); + + public List getByUsernameContaining(String username); + + /** + * 增加学生 + * @param user + * @return + */ + User saveUser(User user); + + /** + * 删除单个学生 + * @param id + * @return + */ + int removeUser(Long id); + + /** + * 更新学生信息 + * @param user + * @return + */ + User updateUser(User user); + + /** + * 根据id获取学生信息 + * @param id + * @return + */ + User getUserById(Long id); + + /** + * 获取学生列表 + * @return + */ + List listUsers(); +} diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/serviceImpl/UserServiceImpl.java b/springboot-swagger-ui/src/main/java/com/abel/example/serviceImpl/UserServiceImpl.java new file mode 100644 index 0000000..dbaf112 --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/serviceImpl/UserServiceImpl.java @@ -0,0 +1,64 @@ +package com.abel.example.serviceImpl; + +import com.abel.example.bean.User; +import com.abel.example.dao.UserJpaDao; +import com.abel.example.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author abel + * @ClassName UserServiceImpl + * @date 2016年11月10日 + */ +@Service +public class UserServiceImpl implements UserService { + @Autowired + private UserJpaDao userJpaDao; + + /** + * @param username + * @return + */ + @Override + public User getUserByUserName(String username) { + return userJpaDao.getByUsernameIs(username); + } + + @Override + public List getByUsernameContaining(String username) { + return userJpaDao.findByUsernameContaining(username); + } + + @Override + public User saveUser(User user) { + return userJpaDao.save(user); + } + + @Override + public int removeUser(Long id) { + try { + userJpaDao.delete(id); + }catch (Exception e) { + return 0; + } + return 1; + } + + @Override + public User updateUser(User user) { + return userJpaDao.save(user); + } + + @Override + public User getUserById(Long id) { + return userJpaDao.findOne(id); + } + + @Override + public List listUsers() { + return userJpaDao.findAll(); + } +} diff --git a/springboot-swagger-ui/src/main/java/com/abel/example/util/CommonUtil.java b/springboot-swagger-ui/src/main/java/com/abel/example/util/CommonUtil.java new file mode 100644 index 0000000..5fe5eab --- /dev/null +++ b/springboot-swagger-ui/src/main/java/com/abel/example/util/CommonUtil.java @@ -0,0 +1,47 @@ +package com.abel.example.util; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + +public class CommonUtil { + + /** + * 从request中获得参数Map,并返回可读的Map. + * + * @param request the request + * @return the parameter map + */ + public static Map getParameterMap(HttpServletRequest request) { + // 参数Map + Map properties = request.getParameterMap(); + //返回值Map + Map returnMap = new HashMap(); + Set keySet = properties.keySet(); + for(String key: keySet){ + String[] values = properties.get(key); + String value = ""; + if(values != null && (values.length==1&&StringUtils.isNotBlank(values[0]))?true:false){ + for(int i=0;i