diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..991728ccc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.idea/ +target/ +*.iml + diff --git a/1.x/README.md b/1.x/README.md new file mode 100644 index 000000000..03c818122 --- /dev/null +++ b/1.x/README.md @@ -0,0 +1,73 @@ +# Spring Boot Examples + +Demo website:http://www.ityouknow.com/ + +[Spring Cloud学习示例代码](https://github.com/ityouknow/spring-cloud-examples) + +[Spring Boot 中文索引](https://github.com/ityouknow/awesome-spring-boot) + +[参与贡献](https://github.com/ityouknow/spring-boot-examples/issues) |  [English](README_EN.md) + +**[github地址](https://github.com/ityouknow/spring-boot-examples)** + +**[码云地址](https://gitee.com/ityouknow/spring-boot-examples)** + +Spring boot使用的各种示例,以最简单、最实用为标准 + + +- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-helloWorld):spring-boot的helloWorld版本 +- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-annotation):注解版本 +- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-xml):xml配置版本 +- [spring-boot-mybatis-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-mulidatasource):springboot+mybatis多数据源最简解决方案 +- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-annotation-mulidatasource):springboot+mybatis(注解版)多数据源最简解决方案 +- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-thymeleaf):simple spring boot thymeleaf demo +- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-jpa-thymeleaf-curd):spring boot + jpa + thymeleaf 增删改查示例 +- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-rabbitmq):spring boot和rabbitmq各种消息应用案例 +- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-scheduler):spring boot和定时任务案例 +- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-web):web开发综合使用案例 +- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mail):spring boot和邮件服务 +- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mongodb):spring boot和mongodb的使用 +- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-multi-mongodb):spring boot和mongodb多数据源的使用 +- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-package-war):spring-boot打包成war包示例 +- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-shiro):springboot 整合shiro rbac示例 +- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-file-upload):使用Spring Boot 上传文件示例 +- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-fastDFS):Spring Boot 整合FastDFS示例 +- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-actuator):Spring Boot Actuator 使用示例 +- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-admin-simple):Spring Boot Admin 的使用示例 + +**[Favorites-web](https://github.com/cloudfavorites/favorites-web):云收藏(springboot实战开源项目)** + + + +参考文章: + +- [springboot(一):入门篇](http://www.ityouknow.com/springboot/2016/01/06/springboot(%E4%B8%80)-%E5%85%A5%E9%97%A8%E7%AF%87.html) +- [springboot(二):web综合开发](http://www.ityouknow.com/springboot/2016/02/03/springboot(%E4%BA%8C)-web%E7%BB%BC%E5%90%88%E5%BC%80%E5%8F%91.html) +- [springboot(三):Spring boot中Redis的使用](http://www.ityouknow.com/springboot/2016/03/06/springboot(%E4%B8%89)-Spring-Boot%E4%B8%ADRedis%E7%9A%84%E4%BD%BF%E7%94%A8.html) +- [springboot(四):thymeleaf使用详解](http://www.ityouknow.com/springboot/2016/05/01/springboot(%E5%9B%9B)-thymeleaf%E4%BD%BF%E7%94%A8%E8%AF%A6%E8%A7%A3.html) +- [springboot(五):spring data jpa的使用](http://www.ityouknow.com/springboot/2016/08/20/springboot(%E4%BA%94)-spring-data-jpa%E7%9A%84%E4%BD%BF%E7%94%A8.html) +- [springboot(六):如何优雅的使用mybatis](http://www.ityouknow.com/springboot/2016/11/06/springboot(%E5%85%AD)-%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E7%9A%84%E4%BD%BF%E7%94%A8mybatis.html) +- [springboot(七):springboot+mybatis多数据源最简解决方案](http://www.ityouknow.com/springboot/2016/11/25/springboot(%E4%B8%83)-springboot+mybatis%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E6%9C%80%E7%AE%80%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.html) +- [springboot(八):RabbitMQ详解](http://www.ityouknow.com/springboot/2016/11/30/springboot(%E5%85%AB)-RabbitMQ%E8%AF%A6%E8%A7%A3.html) +- [springboot(九):定时任务](http://www.ityouknow.com/springboot/2016/12/02/springboot(%E4%B9%9D)-%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1.html) +- [springboot(十):邮件服务](http://www.ityouknow.com/springboot/2017/05/06/springboot-mail.html) +- [springboot(十一):Spring boot中mongodb的使用](http://www.ityouknow.com/springboot/2017/05/08/springboot-mongodb.html) +- [springboot(十二):springboot如何测试打包部署](http://www.ityouknow.com/springboot/2017/05/09/springboot-deploy.html) +- [springboot(十三):springboot小技巧](http://www.ityouknow.com/springboot/2017/06/22/springboot-tips.html) +- [springboot(十四):springboot整合shiro-登录认证和权限管理](http://www.ityouknow.com/springboot/2017/06/26/springboot-shiro.html) +- [springboot(十五):springboot+jpa+thymeleaf增删改查示例](http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html) +- [springboot(十六):使用Jenkins部署Spring Boot](http://www.ityouknow.com/springboot/2017/11/11/springboot-jenkins.html) +- [springboot(十七):使用Spring Boot上传文件](http://www.ityouknow.com/springboot/2018/01/12/spring-boot-upload-file.html) +- [springboot(十八):使用Spring Boot集成FastDFS](http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html) +- [springboot(十九):使用Spring Boot Actuator监控应用](http://www.ityouknow.com/springboot/2018/02/06/spring-boot-actuator.html) +- [springboot(二十):使用spring-boot-admin对spring-boot服务进行监控](http://www.ityouknow.com/springboot/2018/02/11/spring-boot-admin.html) + +**[springboot实战:我们的第一款开源项目](http://www.ityouknow.com/springboot/2016/09/26/springboot%E5%AE%9E%E6%88%98-%E6%88%91%E4%BB%AC%E7%9A%84%E7%AC%AC%E4%B8%80%E6%AC%BE%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6.html)** + +> 如果大家想了解关于springboot的其它方面应用,也可以以[issues](https://github.com/ityouknow/spring-boot-examples/issues)的形式反馈给我,我后续来完善。 + + +关注公众号:纯洁的微笑,回复"666"进群交流 + +![](http://www.ityouknow.com/assets/images/keeppuresmile.jpg) + diff --git a/1.x/README_EN.md b/1.x/README_EN.md new file mode 100644 index 000000000..93f67e576 --- /dev/null +++ b/1.x/README_EN.md @@ -0,0 +1,33 @@ +# Spring Boot Examples + +this is ablout learn Spring Boot Examples + +Demo website:http://www.ityouknow.com/ + +[Spring Cloud example code](https://github.com/ityouknow/spring-cloud-examples) + +[Contribution](https://github.com/ityouknow/spring-boot-examples/issues) |  [中文](README.md) + +Spring Boot Examples, Use the simplest and most useful scene demo. + +- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-helloWorld):Spring Boot helloWorld +- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-annotation):Spring Boot use mybatis annotation +- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-xml):Spring Boot use mybatis xml +- [spring-boot-mybatis-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-mulidatasource):Spring Boot+mybatis+mulidatasource +- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mybatis-annotation-mulidatasource):Spring Boot+ mybatis annotation + mulidatasource +- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-thymeleaf):simple spring boot thymeleaf demo +- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-jpa-thymeleaf-curd):spring boot + jpa + thymeleaf curd demo +- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-rabbitmq): using AMQP and RabbitMQ +- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-scheduler):Timed tasks developed using Spring Boot +- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-web):Web projects developed using Spring Boot +- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mail):Mail system developed using Spring Boot +- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-mongodb):Spring Boot + Mongodb +- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-multi-mongodb):Spring Boot + multiMongodb +- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-package-war):Spring Boot package war +- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-shiro):spring boot shiro rbac demo +- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-file-upload):Spring Boot upload file demo +- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-fastDFS):Spring Boot Integrate FastDFS upload delete and so on +- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-actuator):Spring Boot Actuator demo +- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x/spring-boot-admin-simple):Spring Boot Admin demo + +**[Favorites-web](https://github.com/cloudfavorites/favorites-web):Open source projects developed using Spring Boot** diff --git a/spring-boot-actuator/pom.xml b/1.x/spring-boot-actuator/pom.xml similarity index 100% rename from spring-boot-actuator/pom.xml rename to 1.x/spring-boot-actuator/pom.xml diff --git a/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java b/1.x/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java similarity index 100% rename from spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java rename to 1.x/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java diff --git a/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java b/1.x/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java similarity index 100% rename from spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java rename to 1.x/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java diff --git a/spring-boot-actuator/src/main/resources/application.yml b/1.x/spring-boot-actuator/src/main/resources/application.yml similarity index 100% rename from spring-boot-actuator/src/main/resources/application.yml rename to 1.x/spring-boot-actuator/src/main/resources/application.yml diff --git a/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java b/1.x/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java similarity index 100% rename from spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java rename to 1.x/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java diff --git a/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java b/1.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java similarity index 100% rename from spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java rename to 1.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java diff --git a/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/1.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java similarity index 100% rename from spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java rename to 1.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java diff --git a/spring-boot-admin-simple/pom.xml b/1.x/spring-boot-admin-simple/pom.xml similarity index 100% rename from spring-boot-admin-simple/pom.xml rename to 1.x/spring-boot-admin-simple/pom.xml diff --git a/spring-boot-admin-simple/spring-boot-admin-client/pom.xml b/1.x/spring-boot-admin-simple/spring-boot-admin-client/pom.xml similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-client/pom.xml rename to 1.x/spring-boot-admin-simple/spring-boot-admin-client/pom.xml diff --git a/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java b/1.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java rename to 1.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java diff --git a/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties b/1.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties rename to 1.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties diff --git a/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java b/1.x/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java rename to 1.x/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java diff --git a/spring-boot-admin-simple/spring-boot-admin-server/pom.xml b/1.x/spring-boot-admin-simple/spring-boot-admin-server/pom.xml similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-server/pom.xml rename to 1.x/spring-boot-admin-simple/spring-boot-admin-server/pom.xml diff --git a/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java b/1.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java rename to 1.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java diff --git a/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties b/1.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties rename to 1.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties diff --git a/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java b/1.x/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java similarity index 100% rename from spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java rename to 1.x/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java diff --git a/spring-boot-fastDFS/pom.xml b/1.x/spring-boot-fastDFS/pom.xml similarity index 100% rename from spring-boot-fastDFS/pom.xml rename to 1.x/spring-boot-fastDFS/pom.xml diff --git a/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java b/1.x/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java similarity index 100% rename from spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java rename to 1.x/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java diff --git a/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/1.x/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java similarity index 100% rename from spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java rename to 1.x/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java diff --git a/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java b/1.x/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java similarity index 100% rename from spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java rename to 1.x/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java diff --git a/1.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java b/1.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java new file mode 100644 index 000000000..ce9555029 --- /dev/null +++ b/1.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java @@ -0,0 +1,104 @@ +package com.neo.fastdfs; + +import org.csource.common.NameValuePair; +import org.csource.fastdfs.*; +import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import java.io.*; + +public class FastDFSClient { + private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class); + private static TrackerClient trackerClient; + private static TrackerServer trackerServer; + private static StorageClient storageClient; + private static StorageServer storageServer; + + static { + try { + String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();; + ClientGlobal.init(filePath); + trackerClient = new TrackerClient(); + trackerServer = trackerClient.getConnection(); + storageServer = trackerClient.getStoreStorage(trackerServer); + } catch (Exception e) { + logger.error("FastDFS Client Init Fail!",e); + } + } + + public static String[] upload(FastDFSFile file) { + logger.info("File Name: " + file.getName() + "File Length:" + file.getContent().length); + + NameValuePair[] meta_list = new NameValuePair[1]; + meta_list[0] = new NameValuePair("author", file.getAuthor()); + + long startTime = System.currentTimeMillis(); + String[] uploadResults = null; + try { + storageClient = new StorageClient(trackerServer, storageServer); + uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list); + } catch (IOException e) { + logger.error("IO Exception when uploadind the file:" + file.getName(), e); + } catch (Exception e) { + logger.error("Non IO Exception when uploadind the file:" + file.getName(), e); + } + logger.info("upload_file time used:" + (System.currentTimeMillis() - startTime) + " ms"); + + if (uploadResults == null) { + logger.error("upload file fail, error code:" + storageClient.getErrorCode()); + } + String groupName = uploadResults[0]; + String remoteFileName = uploadResults[1]; + + logger.info("upload file successfully!!!" + "group_name:" + groupName + ", remoteFileName:" + " " + remoteFileName); + return uploadResults; + } + + public static FileInfo getFile(String groupName, String remoteFileName) { + try { + storageClient = new StorageClient(trackerServer, storageServer); + return storageClient.get_file_info(groupName, remoteFileName); + } catch (IOException e) { + logger.error("IO Exception: Get File from Fast DFS failed", e); + } catch (Exception e) { + logger.error("Non IO Exception: Get File from Fast DFS failed", e); + } + return null; + } + + public static InputStream downFile(String groupName, String remoteFileName) { + try { + storageClient = new StorageClient(trackerServer, storageServer); + byte[] fileByte = storageClient.download_file(groupName, remoteFileName); + InputStream ins = new ByteArrayInputStream(fileByte); + return ins; + } catch (IOException e) { + logger.error("IO Exception: Get File from Fast DFS failed", e); + } catch (Exception e) { + logger.error("Non IO Exception: Get File from Fast DFS failed", e); + } + return null; + } + + public static void deleteFile(String groupName, String remoteFileName) + throws Exception { + storageClient = new StorageClient(trackerServer, storageServer); + int i = storageClient.delete_file(groupName, remoteFileName); + logger.info("delete file successfully!!!" + i); + } + + public static StorageServer[] getStoreStorages(String groupName) + throws IOException { + return trackerClient.getStoreStorages(trackerServer, groupName); + } + + public static ServerInfo[] getFetchStorages(String groupName, + String remoteFileName) throws IOException { + return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); + } + + public static String getTrackerUrl() { + return "http://"+trackerServer.getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/"; + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java b/1.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java similarity index 100% rename from spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java rename to 1.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java diff --git a/spring-boot-fastDFS/src/main/resources/application.properties b/1.x/spring-boot-fastDFS/src/main/resources/application.properties similarity index 100% rename from spring-boot-fastDFS/src/main/resources/application.properties rename to 1.x/spring-boot-fastDFS/src/main/resources/application.properties diff --git a/spring-boot-fastDFS/src/main/resources/fdfs_client.conf b/1.x/spring-boot-fastDFS/src/main/resources/fdfs_client.conf similarity index 100% rename from spring-boot-fastDFS/src/main/resources/fdfs_client.conf rename to 1.x/spring-boot-fastDFS/src/main/resources/fdfs_client.conf diff --git a/spring-boot-fastDFS/src/main/resources/logback.xml b/1.x/spring-boot-fastDFS/src/main/resources/logback.xml similarity index 100% rename from spring-boot-fastDFS/src/main/resources/logback.xml rename to 1.x/spring-boot-fastDFS/src/main/resources/logback.xml diff --git a/spring-boot-fastDFS/src/main/resources/templates/upload.html b/1.x/spring-boot-fastDFS/src/main/resources/templates/upload.html similarity index 100% rename from spring-boot-fastDFS/src/main/resources/templates/upload.html rename to 1.x/spring-boot-fastDFS/src/main/resources/templates/upload.html diff --git a/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html b/1.x/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html similarity index 100% rename from spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html rename to 1.x/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html diff --git a/1.x/spring-boot-file-upload/pom.xml b/1.x/spring-boot-file-upload/pom.xml new file mode 100644 index 000000000..731cfa08c --- /dev/null +++ b/1.x/spring-boot-file-upload/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + com.neo + spring-boot-file-upload + jar + 1.0 + + + org.springframework.boot + spring-boot-starter-parent + 1.5.9.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/1.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java b/1.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java new file mode 100644 index 000000000..6e355e38d --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java @@ -0,0 +1,30 @@ +package com.neo; + +import org.apache.coyote.http11.AbstractHttp11Protocol; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class FileUploadWebApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(FileUploadWebApplication.class, args); + } + + //Tomcat large file upload connection reset + @Bean + public TomcatEmbeddedServletContainerFactory tomcatEmbedded() { + TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); + tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { + if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { + //-1 means unlimited + ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); + } + }); + return tomcat; + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java new file mode 100644 index 000000000..8f5caf6cc --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java @@ -0,0 +1,18 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@ControllerAdvice +public class GlobalExceptionHandler { + + //https://jira.spring.io/browse/SPR-14651 + //4.3.5 supports RedirectAttributes redirectAttributes + @ExceptionHandler(MultipartException.class) + public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { + redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); + return "redirect:/uploadStatus"; + } +} diff --git a/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java b/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java new file mode 100644 index 000000000..13d3ab467 --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java @@ -0,0 +1,54 @@ +package com.neo.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Controller +public class UploadController { + //Save the uploaded file to this folder + private static String UPLOADED_FOLDER = "E://temp//"; + + @GetMapping("/") + public String index() { + return "upload"; + } + + @PostMapping("/upload") // //new annotation since 4.3 + public String singleFileUpload(@RequestParam("file") MultipartFile file, + RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); + return "redirect:uploadStatus"; + } + + try { + // Get the file and save it somewhere + byte[] bytes = file.getBytes(); + Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); + Files.write(path, bytes); + + redirectAttributes.addFlashAttribute("message", + "You successfully uploaded '" + file.getOriginalFilename() + "'"); + + } catch (IOException e) { + e.printStackTrace(); + } + + return "redirect:/uploadStatus"; + } + + @GetMapping("/uploadStatus") + public String uploadStatus() { + return "uploadStatus"; + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-file-upload/src/main/resources/application.properties b/1.x/spring-boot-file-upload/src/main/resources/application.properties new file mode 100644 index 000000000..8ec671da4 --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/resources/application.properties @@ -0,0 +1,11 @@ +#http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties +#search multipart +spring.http.multipart.max-file-size=10MB +spring.http.multipart.max-request-size=10MB + +#spring.http.multipart.enabled=true #\u9ED8\u8BA4\u652F\u6301\u6587\u4EF6\u4E0A\u4F20. +#spring.http.multipart.file-size-threshold=0 #\u652F\u6301\u6587\u4EF6\u5199\u5165\u78C1\u76D8. +#spring.http.multipart.location= # \u4E0A\u4F20\u6587\u4EF6\u7684\u4E34\u65F6\u76EE\u5F55 +#spring.http.multipart.max-file-size=1Mb # \u6700\u5927\u652F\u6301\u6587\u4EF6\u5927\u5C0F +#spring.http.multipart.max-request-size=10Mb # \u6700\u5927\u652F\u6301\u8BF7\u6C42\u5927\u5C0F + diff --git a/1.x/spring-boot-file-upload/src/main/resources/logback.xml b/1.x/spring-boot-file-upload/src/main/resources/logback.xml new file mode 100644 index 000000000..0c0f833bc --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/resources/logback.xml @@ -0,0 +1,24 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/1.x/spring-boot-file-upload/src/main/resources/templates/from_file.html b/1.x/spring-boot-file-upload/src/main/resources/templates/from_file.html new file mode 100644 index 000000000..3f95f35e1 --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/resources/templates/from_file.html @@ -0,0 +1,51 @@ +
+
+
+ Ӹ +
+
+ + 0%
+ +
+ +
+
+
+ + + \ No newline at end of file diff --git a/1.x/spring-boot-file-upload/src/main/resources/templates/upload.html b/1.x/spring-boot-file-upload/src/main/resources/templates/upload.html new file mode 100644 index 000000000..2e93a58dd --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/resources/templates/upload.html @@ -0,0 +1,13 @@ + + + + +

Spring Boot file upload example

+ +
+

+ +
+ + + diff --git a/1.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html b/1.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html new file mode 100644 index 000000000..71fb76d3c --- /dev/null +++ b/1.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html @@ -0,0 +1,12 @@ + + + + +

Spring Boot - Upload Status

+ +
+

+

+ + + \ No newline at end of file diff --git a/1.x/spring-boot-helloWorld/pom.xml b/1.x/spring-boot-helloWorld/pom.xml new file mode 100644 index 000000000..c8280ef2e --- /dev/null +++ b/1.x/spring-boot-helloWorld/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.neo + spring-boot-helloworld + 0.0.1-SNAPSHOT + jar + + spring-boot-helloworld + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/spring-boot-package-war/src/main/java/com/neo/Application.java b/1.x/spring-boot-helloWorld/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-package-war/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-helloWorld/src/main/java/com/neo/Application.java diff --git a/1.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java b/1.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java new file mode 100644 index 000000000..7d0256b4a --- /dev/null +++ b/1.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/spring-boot-package-war/src/main/resources/application.properties b/1.x/spring-boot-helloWorld/src/main/resources/application.properties similarity index 100% rename from spring-boot-package-war/src/main/resources/application.properties rename to 1.x/spring-boot-helloWorld/src/main/resources/application.properties diff --git a/1.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java new file mode 100644 index 000000000..1faf3f2e7 --- /dev/null +++ b/1.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello word"); + } + +} diff --git a/1.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java b/1.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..d42211135 --- /dev/null +++ b/1.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,39 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/1.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java similarity index 100% rename from spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java rename to 1.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/pom.xml b/1.x/spring-boot-jpa-thymeleaf-curd/pom.xml new file mode 100644 index 000000000..caa8ecc56 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + spring-boot-jpa-thymeleaf-curd + spring-boot-jpa-thymeleaf-curd + spring-boot-jpa-thymeleaf-curd + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-devtools + true + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + \ No newline at end of file diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java new file mode 100644 index 000000000..92f4c0aec --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java @@ -0,0 +1,20 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + + +@SpringBootApplication +public class JpaThymeleafApplication extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(JpaThymeleafApplication.class); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(JpaThymeleafApplication.class, args); + } +} + diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/entity/User.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/entity/User.java similarity index 100% rename from spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/entity/User.java rename to 1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/entity/User.java diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..14821f515 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.neo.repository; + +import com.neo.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findById(long id); + + Long deleteById(Long id); +} \ No newline at end of file diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java new file mode 100644 index 000000000..be9becb4e --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java @@ -0,0 +1,20 @@ +package com.neo.service; + +import com.neo.entity.User; + +import java.util.List; + +public interface UserService { + + public List getUserList(); + + public User findUserById(long id); + + public void save(User user); + + public void edit(User user); + + public void delete(long id); + + +} diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java new file mode 100644 index 000000000..8e66fad24 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java @@ -0,0 +1,44 @@ +package com.neo.service.impl; + +import com.neo.entity.User; +import com.neo.repository.UserRepository; +import com.neo.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class UserServiceImpl implements UserService{ + + @Autowired + private UserRepository userRepository; + + @Override + public List getUserList() { + return userRepository.findAll(); + } + + @Override + public User findUserById(long id) { + return userRepository.findById(id); + } + + @Override + public void save(User user) { + userRepository.save(user); + } + + @Override + public void edit(User user) { + userRepository.save(user); + } + + @Override + public void delete(long id) { + userRepository.delete(id); + } +} + + diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..82136eb19 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,16 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +public class HelloController { + + @RequestMapping("/hello") + public String hello(Model model, @RequestParam(value="name", required=false, defaultValue="World") String name) { + model.addAttribute("name", name); + return "hello"; + } +} diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..02eef58ae --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,63 @@ +package com.neo.web; + +import com.neo.entity.User; +import com.neo.service.UserService; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.annotation.Resource; +import java.util.List; + +@Controller +public class UserController { + + @Resource + UserService userService; + + + @RequestMapping("/") + public String index() { + return "redirect:/list"; + } + + @RequestMapping("/list") + public String list(Model model) { + List users=userService.getUserList(); + model.addAttribute("users", users); + return "user/list"; + } + + @RequestMapping("/toAdd") + public String toAdd() { + return "user/userAdd"; + } + + @RequestMapping("/add") + public String add(User user) { + userService.save(user); + return "redirect:/list"; + } + + @RequestMapping("/toEdit") + public String toEdit(Model model,Long id) { + User user=userService.findUserById(id); + model.addAttribute("user", user); + return "user/userEdit"; + } + + @RequestMapping("/edit") + public String edit(User user) { + userService.edit(user); + return "redirect:/list"; + } + + + @RequestMapping("/delete") + public String delete(Long id) { + userService.delete(id); + return "redirect:/list"; + } +} diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties new file mode 100644 index 000000000..65ff9c384 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties @@ -0,0 +1,10 @@ +spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.jdbc.Driver + +spring.jpa.properties.hibernate.hbm2ddl.auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.show-sql= true + +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css new file mode 100644 index 000000000..42c79d6e4 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css @@ -0,0 +1,6760 @@ +/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + padding-right: 15px; + padding-left: 15px; + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + filter: alpha(opacity=0); + opacity: 0; + + line-break: auto; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + + line-break: auto; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/spring-boot-thymeleaf/src/main/resources/templates/hello.html b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/hello.html similarity index 100% rename from spring-boot-thymeleaf/src/main/resources/templates/hello.html rename to 1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/hello.html diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html new file mode 100644 index 000000000..4126a3de1 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html @@ -0,0 +1,43 @@ + + + + + userList + + + +
+

用户列表

+

+
+ + + + + + + + + + + + + + + + + + + + + +
#User NamePasswordAgeEditDelete
1neoOtto6editdelete
+
+
+
+ add +
+
+ + + \ No newline at end of file diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html new file mode 100644 index 000000000..0fa93c38a --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html @@ -0,0 +1,43 @@ + + + + + user + + + +
+

添加用户

+

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +       + +
+ +
+
+
+ + diff --git a/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html new file mode 100644 index 000000000..b312daa37 --- /dev/null +++ b/1.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html @@ -0,0 +1,44 @@ + + + + + user + + + +
+

修改用户

+

+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +       + Back +
+ +
+
+
+ + diff --git a/1.x/spring-boot-mail/pom.xml b/1.x/spring-boot-mail/pom.xml new file mode 100644 index 000000000..d22376fce --- /dev/null +++ b/1.x/spring-boot-mail/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + + com.neo + spring-boot-mail + 1.0.0 + jar + + spring-boot-mail + Demo project for Spring Boot and mail + + + org.springframework.boot + spring-boot-starter-parent + 1.5.3.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-mail + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + true + + + org.springframework + spring-context-support + RELEASE + + + com.sun.mail + javax.mail + RELEASE + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/spring-boot-mail/src/main/java/com/neo/Application.java b/1.x/spring-boot-mail/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mail/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mail/src/main/java/com/neo/Application.java diff --git a/1.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java b/1.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java new file mode 100644 index 000000000..a2948541c --- /dev/null +++ b/1.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java @@ -0,0 +1,16 @@ +package com.neo.service; + +/** + * Created by summer on 2017/5/4. + */ +public interface MailService { + + public void sendSimpleMail(String to, String subject, String content); + + public void sendHtmlMail(String to, String subject, String content); + + public void sendAttachmentsMail(String to, String subject, String content, String filePath); + + public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId); + +} diff --git a/1.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java b/1.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java new file mode 100644 index 000000000..9053e6fb7 --- /dev/null +++ b/1.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java @@ -0,0 +1,138 @@ +package com.neo.service.impl; + +import com.neo.service.MailService; +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.core.io.FileSystemResource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.File; + +/** + * Created by summer on 2017/5/4. + */ +@Component +public class MailServiceImpl implements MailService{ + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private JavaMailSender mailSender; + + @Value("${mail.fromMail.addr}") + private String from; + + /** + * 发送文本邮件 + * @param to + * @param subject + * @param content + */ + @Override + public void sendSimpleMail(String to, String subject, String content) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); + message.setTo(to); + message.setSubject(subject); + message.setText(content); + + try { + mailSender.send(message); + logger.info("简单邮件已经发送。"); + } catch (Exception e) { + logger.error("发送简单邮件时发生异常!", e); + } + + } + + /** + * 发送html邮件 + * @param to + * @param subject + * @param content + */ + @Override + public void sendHtmlMail(String to, String subject, String content) { + MimeMessage message = mailSender.createMimeMessage(); + + try { + //true表示需要创建一个multipart message + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + mailSender.send(message); + logger.info("html邮件发送成功"); + } catch (MessagingException e) { + logger.error("发送html邮件时发生异常!", e); + } + } + + + /** + * 发送带附件的邮件 + * @param to + * @param subject + * @param content + * @param filePath + */ + public void sendAttachmentsMail(String to, String subject, String content, String filePath){ + MimeMessage message = mailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + FileSystemResource file = new FileSystemResource(new File(filePath)); + String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); + helper.addAttachment(fileName, file); + //helper.addAttachment("test"+fileName, file); + + mailSender.send(message); + logger.info("带附件的邮件已经发送。"); + } catch (MessagingException e) { + logger.error("发送带附件的邮件时发生异常!", e); + } + } + + + /** + * 发送正文中有静态资源(图片)的邮件 + * @param to + * @param subject + * @param content + * @param rscPath + * @param rscId + */ + public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){ + MimeMessage message = mailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + FileSystemResource res = new FileSystemResource(new File(rscPath)); + helper.addInline(rscId, res); + + mailSender.send(message); + logger.info("嵌入静态资源的邮件已经发送。"); + } catch (MessagingException e) { + logger.error("发送嵌入静态资源的邮件时发生异常!", e); + } + } +} diff --git a/1.x/spring-boot-mail/src/main/resources/application.properties b/1.x/spring-boot-mail/src/main/resources/application.properties new file mode 100644 index 000000000..dcbb52168 --- /dev/null +++ b/1.x/spring-boot-mail/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.application.name=spirng-boot-mail + +spring.mail.host=smtp.163.com +spring.mail.username=xxoo@xxoo.com +spring.mail.password=xxoo +spring.mail.default-encoding=UTF-8 + +mail.fromMail.addr=xxoo@xxoo.com + diff --git a/1.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html b/1.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html new file mode 100644 index 000000000..387a4fbcd --- /dev/null +++ b/1.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html @@ -0,0 +1,11 @@ + + + + + Title + + + 您好,这是验证邮件,请点击下面的链接完成验证,
+ 激活账号 + + \ No newline at end of file diff --git a/spring-boot-mail/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mail/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mail/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mail/src/test/java/com/neo/ApplicationTests.java diff --git a/1.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java b/1.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java new file mode 100644 index 000000000..91c4bbfd2 --- /dev/null +++ b/1.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java @@ -0,0 +1,65 @@ +package com.neo.service; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + +/** + * Created by summer on 2017/5/4. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class MailServiceTest { + + @Autowired + private MailService mailService; + + @Autowired + private TemplateEngine templateEngine; + + @Test + public void testSimpleMail() throws Exception { + mailService.sendSimpleMail("ityouknow@126.com","test simple mail"," hello this is simple mail"); + } + + @Test + public void testHtmlMail() throws Exception { + String content="\n" + + "\n" + + "

hello world ! 这是一封html邮件!

\n" + + "\n" + + ""; + mailService.sendHtmlMail("ityouknow@126.com","test simple mail",content); + } + + @Test + public void sendAttachmentsMail() { + String filePath="e:\\tmp\\application.log"; + mailService.sendAttachmentsMail("ityouknow@126.com", "主题:带附件的邮件", "有附件,请查收!", filePath); + } + + + @Test + public void sendInlineResourceMail() { + String rscId = "neo006"; + String content="这是有图片的邮件:"; + String imgPath = "C:\\Users\\summer\\Pictures\\favicon.png"; + + mailService.sendInlineResourceMail("ityouknow@126.com", "主题:这是有图片的邮件", content, imgPath, rscId); + } + + + @Test + public void sendTemplateMail() { + //创建邮件正文 + Context context = new Context(); + context.setVariable("id", "006"); + String emailContent = templateEngine.process("emailTemplate", context); + + mailService.sendHtmlMail("ityouknow@126.com","主题:这是模板邮件",emailContent); + } +} diff --git a/spring-boot-mongodb/pom.xml b/1.x/spring-boot-mongodb/pom.xml similarity index 100% rename from spring-boot-mongodb/pom.xml rename to 1.x/spring-boot-mongodb/pom.xml diff --git a/spring-boot-mongodb/src/main/java/com/neo/Application.java b/1.x/spring-boot-mongodb/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mongodb/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mongodb/src/main/java/com/neo/Application.java diff --git a/spring-boot-mongodb/src/main/java/com/neo/dao/UserDao.java b/1.x/spring-boot-mongodb/src/main/java/com/neo/dao/UserDao.java similarity index 100% rename from spring-boot-mongodb/src/main/java/com/neo/dao/UserDao.java rename to 1.x/spring-boot-mongodb/src/main/java/com/neo/dao/UserDao.java diff --git a/spring-boot-mongodb/src/main/java/com/neo/dao/impl/UserDaoImpl.java b/1.x/spring-boot-mongodb/src/main/java/com/neo/dao/impl/UserDaoImpl.java similarity index 100% rename from spring-boot-mongodb/src/main/java/com/neo/dao/impl/UserDaoImpl.java rename to 1.x/spring-boot-mongodb/src/main/java/com/neo/dao/impl/UserDaoImpl.java diff --git a/spring-boot-mongodb/src/main/java/com/neo/entity/UserEntity.java b/1.x/spring-boot-mongodb/src/main/java/com/neo/entity/UserEntity.java similarity index 100% rename from spring-boot-mongodb/src/main/java/com/neo/entity/UserEntity.java rename to 1.x/spring-boot-mongodb/src/main/java/com/neo/entity/UserEntity.java diff --git a/spring-boot-mongodb/src/main/resources/application.properties b/1.x/spring-boot-mongodb/src/main/resources/application.properties similarity index 100% rename from spring-boot-mongodb/src/main/resources/application.properties rename to 1.x/spring-boot-mongodb/src/main/resources/application.properties diff --git a/spring-boot-mongodb/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mongodb/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mongodb/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mongodb/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-mongodb/src/test/java/com/neo/dao/UserDaoTest.java b/1.x/spring-boot-mongodb/src/test/java/com/neo/dao/UserDaoTest.java similarity index 100% rename from spring-boot-mongodb/src/test/java/com/neo/dao/UserDaoTest.java rename to 1.x/spring-boot-mongodb/src/test/java/com/neo/dao/UserDaoTest.java diff --git a/spring-boot-multi-mongodb/pom.xml b/1.x/spring-boot-multi-mongodb/pom.xml similarity index 100% rename from spring-boot-multi-mongodb/pom.xml rename to 1.x/spring-boot-multi-mongodb/pom.xml diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/Application.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/Application.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryMongoObject.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryMongoObject.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryMongoObject.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryMongoObject.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryRepository.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryRepository.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryRepository.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/primary/PrimaryRepository.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryMongoObject.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryMongoObject.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryMongoObject.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryMongoObject.java diff --git a/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryRepository.java b/1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryRepository.java similarity index 100% rename from spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryRepository.java rename to 1.x/spring-boot-multi-mongodb/src/main/java/com/neo/model/repository/secondary/SecondaryRepository.java diff --git a/spring-boot-multi-mongodb/src/main/resources/application.yml b/1.x/spring-boot-multi-mongodb/src/main/resources/application.yml similarity index 100% rename from spring-boot-multi-mongodb/src/main/resources/application.yml rename to 1.x/spring-boot-multi-mongodb/src/main/resources/application.yml diff --git a/spring-boot-multi-mongodb/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-multi-mongodb/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-multi-mongodb/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-multi-mongodb/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-multi-mongodb/src/test/java/com/neo/model/repository/MuliDatabaseTest.java b/1.x/spring-boot-multi-mongodb/src/test/java/com/neo/model/repository/MuliDatabaseTest.java similarity index 100% rename from spring-boot-multi-mongodb/src/test/java/com/neo/model/repository/MuliDatabaseTest.java rename to 1.x/spring-boot-multi-mongodb/src/test/java/com/neo/model/repository/MuliDatabaseTest.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/pom.xml b/1.x/spring-boot-mybatis-annotation-mulidatasource/pom.xml similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/pom.xml rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/pom.xml diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/Application.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/Application.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/entity/UserEntity.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/entity/UserEntity.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/entity/UserEntity.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/entity/UserEntity.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java diff --git a/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java similarity index 100% rename from spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java rename to 1.x/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java diff --git a/spring-boot-mybatis-annotation/pom.xml b/1.x/spring-boot-mybatis-annotation/pom.xml similarity index 100% rename from spring-boot-mybatis-annotation/pom.xml rename to 1.x/spring-boot-mybatis-annotation/pom.xml diff --git a/spring-boot-mybatis-annotation/src/main/java/com/neo/Application.java b/1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mybatis-annotation/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/Application.java diff --git a/spring-boot-mybatis-annotation/src/main/java/com/neo/entity/UserEntity.java b/1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/entity/UserEntity.java similarity index 100% rename from spring-boot-mybatis-annotation/src/main/java/com/neo/entity/UserEntity.java rename to 1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/entity/UserEntity.java diff --git a/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java b/1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java similarity index 100% rename from spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java rename to 1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java diff --git a/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java b/1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java similarity index 100% rename from spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java rename to 1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java diff --git a/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java similarity index 100% rename from spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java rename to 1.x/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java diff --git a/spring-boot-mybatis-annotation/src/main/resources/application.properties b/1.x/spring-boot-mybatis-annotation/src/main/resources/application.properties similarity index 100% rename from spring-boot-mybatis-annotation/src/main/resources/application.properties rename to 1.x/spring-boot-mybatis-annotation/src/main/resources/application.properties diff --git a/spring-boot-mybatis-annotation/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mybatis-annotation/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mybatis-annotation/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mybatis-annotation/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java b/1.x/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java similarity index 100% rename from spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java rename to 1.x/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java diff --git a/spring-boot-mybatis-annotation/users.sql b/1.x/spring-boot-mybatis-annotation/users.sql similarity index 100% rename from spring-boot-mybatis-annotation/users.sql rename to 1.x/spring-boot-mybatis-annotation/users.sql diff --git a/spring-boot-mybatis-mulidatasource/pom.xml b/1.x/spring-boot-mybatis-mulidatasource/pom.xml similarity index 100% rename from spring-boot-mybatis-mulidatasource/pom.xml rename to 1.x/spring-boot-mybatis-mulidatasource/pom.xml diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/Application.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/Application.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/entity/UserEntity.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/entity/UserEntity.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/entity/UserEntity.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/entity/UserEntity.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/web/UserController.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/java/com/neo/web/UserController.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/java/com/neo/web/UserController.java diff --git a/spring-boot-mybatis-mulidatasource/src/main/resources/application.properties b/1.x/spring-boot-mybatis-mulidatasource/src/main/resources/application.properties similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/resources/application.properties rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/resources/application.properties diff --git a/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml b/1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml diff --git a/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml b/1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml diff --git a/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mybatis-config.xml b/1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mybatis-config.xml similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mybatis-config.xml rename to 1.x/spring-boot-mybatis-mulidatasource/src/main/resources/mybatis/mybatis-config.xml diff --git a/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java diff --git a/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java similarity index 100% rename from spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java rename to 1.x/spring-boot-mybatis-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java diff --git a/spring-boot-mybatis-mulidatasource/users.sql b/1.x/spring-boot-mybatis-mulidatasource/users.sql similarity index 100% rename from spring-boot-mybatis-mulidatasource/users.sql rename to 1.x/spring-boot-mybatis-mulidatasource/users.sql diff --git a/spring-boot-mybatis-xml/pom.xml b/1.x/spring-boot-mybatis-xml/pom.xml similarity index 100% rename from spring-boot-mybatis-xml/pom.xml rename to 1.x/spring-boot-mybatis-xml/pom.xml diff --git a/spring-boot-mybatis-xml/src/main/java/com/neo/Application.java b/1.x/spring-boot-mybatis-xml/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-mybatis-xml/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-mybatis-xml/src/main/java/com/neo/Application.java diff --git a/spring-boot-mybatis-xml/src/main/java/com/neo/entity/UserEntity.java b/1.x/spring-boot-mybatis-xml/src/main/java/com/neo/entity/UserEntity.java similarity index 100% rename from spring-boot-mybatis-xml/src/main/java/com/neo/entity/UserEntity.java rename to 1.x/spring-boot-mybatis-xml/src/main/java/com/neo/entity/UserEntity.java diff --git a/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java b/1.x/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java similarity index 100% rename from spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java rename to 1.x/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java diff --git a/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java b/1.x/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java similarity index 100% rename from spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java rename to 1.x/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java diff --git a/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java similarity index 100% rename from spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java rename to 1.x/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java diff --git a/spring-boot-mybatis-xml/src/main/resources/application.properties b/1.x/spring-boot-mybatis-xml/src/main/resources/application.properties similarity index 100% rename from spring-boot-mybatis-xml/src/main/resources/application.properties rename to 1.x/spring-boot-mybatis-xml/src/main/resources/application.properties diff --git a/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml b/1.x/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml similarity index 100% rename from spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml rename to 1.x/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml diff --git a/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml b/1.x/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml similarity index 100% rename from spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml rename to 1.x/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml diff --git a/spring-boot-mybatis-xml/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-mybatis-xml/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-mybatis-xml/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-mybatis-xml/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java b/1.x/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java similarity index 100% rename from spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java rename to 1.x/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java diff --git a/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java b/1.x/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java similarity index 100% rename from spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java rename to 1.x/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java diff --git a/spring-boot-mybatis-xml/users.sql b/1.x/spring-boot-mybatis-xml/users.sql similarity index 100% rename from spring-boot-mybatis-xml/users.sql rename to 1.x/spring-boot-mybatis-xml/users.sql diff --git a/spring-boot-package-war/pom.xml b/1.x/spring-boot-package-war/pom.xml similarity index 100% rename from spring-boot-package-war/pom.xml rename to 1.x/spring-boot-package-war/pom.xml diff --git a/spring-boot-rabbitmq/src/main/java/com/neo/Application.java b/1.x/spring-boot-package-war/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-rabbitmq/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-package-war/src/main/java/com/neo/Application.java diff --git a/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java b/1.x/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java similarity index 100% rename from spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java rename to 1.x/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java diff --git a/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java b/1.x/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java similarity index 100% rename from spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java rename to 1.x/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java diff --git a/1.x/spring-boot-package-war/src/main/resources/application.properties b/1.x/spring-boot-package-war/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java b/1.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java similarity index 100% rename from spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java rename to 1.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java diff --git a/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/1.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java similarity index 100% rename from spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java rename to 1.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java diff --git a/1.x/spring-boot-rabbitmq/pom.xml b/1.x/spring-boot-rabbitmq/pom.xml new file mode 100644 index 000000000..b4de1e355 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + com.neo + spring-boot-rabbitmq + 1.0.0 + jar + + spring-boot-rabbitmq + Demo project for Spring Boot and rabbitmq + + + org.springframework.boot + spring-boot-starter-parent + 1.4.2.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/spring-boot-web/src/main/java/com/neo/Application.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-web/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-rabbitmq/src/main/java/com/neo/Application.java diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..f4eec95e4 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java @@ -0,0 +1,37 @@ +package com.neo.model; + +import java.io.Serializable; + +/** + * Created by summer on 2016/11/29. + */ +public class User implements Serializable{ + + private String name; + + private String pass; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + ", pass='" + pass + '\'' + + '}'; + } +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java new file mode 100644 index 000000000..4fe21fa9f --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java @@ -0,0 +1,49 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class FanoutRabbitConfig { + + @Bean + public Queue AMessage() { + return new Queue("fanout.A"); + } + + @Bean + public Queue BMessage() { + return new Queue("fanout.B"); + } + + @Bean + public Queue CMessage() { + return new Queue("fanout.C"); + } + + @Bean + FanoutExchange fanoutExchange() { + return new FanoutExchange("fanoutExchange"); + } + + @Bean + Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) { + return BindingBuilder.bind(AMessage).to(fanoutExchange); + } + + @Bean + Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) { + return BindingBuilder.bind(BMessage).to(fanoutExchange); + } + + @Bean + Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) { + return BindingBuilder.bind(CMessage).to(fanoutExchange); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java new file mode 100644 index 000000000..d5d649b5c --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java @@ -0,0 +1,27 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class RabbitConfig { + + @Bean + public Queue helloQueue() { + return new Queue("hello"); + } + + @Bean + public Queue neoQueue() { + return new Queue("neo"); + } + + @Bean + public Queue objectQueue() { + return new Queue("object"); + } + + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java new file mode 100644 index 000000000..7bd2a096c --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java @@ -0,0 +1,41 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class TopicRabbitConfig { + + final static String message = "topic.message"; + final static String messages = "topic.messages"; + + @Bean + public Queue queueMessage() { + return new Queue(TopicRabbitConfig.message); + } + + @Bean + public Queue queueMessages() { + return new Queue(TopicRabbitConfig.messages); + } + + @Bean + TopicExchange exchange() { + return new TopicExchange("topicExchange"); + } + + @Bean + Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) { + return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message"); + } + + @Bean + Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) { + return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#"); + } +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java new file mode 100644 index 000000000..256de2eee --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.A") +public class FanoutReceiverA { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver A : " + message); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java new file mode 100644 index 000000000..a721da684 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.B") +public class FanoutReceiverB { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver B: " + message); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java new file mode 100644 index 000000000..aceef8b08 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.C") +public class FanoutReceiverC { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver C: " + message); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java new file mode 100644 index 000000000..2fa62d39c --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class FanoutSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hi, fanout msg "; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("fanoutExchange","", context); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java new file mode 100644 index 000000000..2d59b1740 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.hello; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +@RabbitListener(queues = "hello") +public class HelloReceiver { + + @RabbitHandler + public void process(String hello) { + System.out.println("Receiver : " + hello); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java new file mode 100644 index 000000000..05fc740ac --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java @@ -0,0 +1,22 @@ +package com.neo.rabbit.hello; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class HelloSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hello " + new Date(); + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("hello", context); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java new file mode 100644 index 000000000..c352fbeb5 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "neo") +public class NeoReceiver1 { + + @RabbitHandler + public void process(String neo) { + System.out.println("Receiver 1: " + neo); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java new file mode 100644 index 000000000..d7cbdd758 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "neo") +public class NeoReceiver2 { + + @RabbitHandler + public void process(String neo) { + System.out.println("Receiver 2: " + neo); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java new file mode 100644 index 000000000..755918fb6 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class NeoSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(int i) { + String context = "spirng boot neo queue"+" ****** "+i; + System.out.println("Sender1 : " + context); + this.rabbitTemplate.convertAndSend("neo", context); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java new file mode 100644 index 000000000..e34cce647 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class NeoSender2 { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(int i) { + String context = "spirng boot neo queue"+" ****** "+i; + System.out.println("Sender2 : " + context); + this.rabbitTemplate.convertAndSend("neo", context); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java new file mode 100644 index 000000000..b97f8a026 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java @@ -0,0 +1,17 @@ +package com.neo.rabbit.object; + +import com.neo.model.User; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "object") +public class ObjectReceiver { + + @RabbitHandler + public void process(User user) { + System.out.println("Receiver object : " + user); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java new file mode 100644 index 000000000..9c7aba927 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java @@ -0,0 +1,21 @@ +package com.neo.rabbit.object; + +import com.neo.model.User; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class ObjectSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(User user) { + System.out.println("Sender object: " + user.toString()); + this.rabbitTemplate.convertAndSend("object", user); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java new file mode 100644 index 000000000..14523941a --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "topic.message") +public class TopicReceiver { + + @RabbitHandler + public void process(String message) { + System.out.println("Topic Receiver1 : " + message); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java new file mode 100644 index 000000000..9ea81d7fe --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "topic.messages") +public class TopicReceiver2 { + + @RabbitHandler + public void process(String message) { + System.out.println("Topic Receiver2 : " + message); + } + +} diff --git a/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java new file mode 100644 index 000000000..8f17c34e3 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java @@ -0,0 +1,33 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class TopicSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hi, i am message all"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.1", context); + } + + public void send1() { + String context = "hi, i am message 1"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.message", context); + } + + public void send2() { + String context = "hi, i am messages 2"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.messages", context); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/main/resources/application.properties b/1.x/spring-boot-rabbitmq/src/main/resources/application.properties new file mode 100644 index 000000000..da5cc5ed0 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.application.name=spirng-boot-rabbitmq-example + +spring.rabbitmq.host=192.168.0.86 +spring.rabbitmq.port=5672 +spring.rabbitmq.username=admin +spring.rabbitmq.password=123456 diff --git a/spring-boot-rabbitmq/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-rabbitmq/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-rabbitmq/src/test/java/com/neo/ApplicationTests.java diff --git a/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java new file mode 100644 index 000000000..d9ee0afd9 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java @@ -0,0 +1,24 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.fanout.FanoutSender; +import com.neo.rabbit.topic.TopicSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class FanoutTest { + + @Autowired + private FanoutSender sender; + + @Test + public void fanoutSender() throws Exception { + sender.send(); + } + + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java new file mode 100644 index 000000000..f790b0452 --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java @@ -0,0 +1,23 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.hello.HelloSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTest { + + @Autowired + private HelloSender helloSender; + + @Test + public void hello() throws Exception { + helloSender.send(); + } + + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java new file mode 100644 index 000000000..08c701cfd --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java @@ -0,0 +1,35 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.many.NeoSender; +import com.neo.rabbit.many.NeoSender2; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ManyTest { + @Autowired + private NeoSender neoSender; + + @Autowired + private NeoSender2 neoSender2; + + @Test + public void oneToMany() throws Exception { + for (int i=0;i<100;i++){ + neoSender.send(i); + } + } + + @Test + public void manyToMany() throws Exception { + for (int i=0;i<100;i++){ + neoSender.send(i); + neoSender2.send(i); + } + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java new file mode 100644 index 000000000..e36daf7ed --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java @@ -0,0 +1,26 @@ +package com.neo.rabbitmq; + +import com.neo.model.User; +import com.neo.rabbit.object.ObjectSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ObjectTest { + + @Autowired + private ObjectSender sender; + + @Test + public void sendOject() throws Exception { + User user=new User(); + user.setName("neo"); + user.setPass("123456"); + sender.send(user); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java new file mode 100644 index 000000000..d69a5b85e --- /dev/null +++ b/1.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java @@ -0,0 +1,32 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.topic.TopicSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TopicTest { + + @Autowired + private TopicSender sender; + + @Test + public void topic() throws Exception { + sender.send(); + } + + @Test + public void topic1() throws Exception { + sender.send1(); + } + + @Test + public void topic2() throws Exception { + sender.send2(); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-scheduler/pom.xml b/1.x/spring-boot-scheduler/pom.xml new file mode 100644 index 000000000..b3d18365d --- /dev/null +++ b/1.x/spring-boot-scheduler/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.neo + spring-boot-scheduler + 1.0.0 + jar + + spring-boot-scheduler + Demo project for Spring Boot and scheduler + + + org.springframework.boot + spring-boot-starter-parent + 1.4.2.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/spring-boot-scheduler/src/main/java/com/neo/Application.java b/1.x/spring-boot-scheduler/src/main/java/com/neo/Application.java similarity index 100% rename from spring-boot-scheduler/src/main/java/com/neo/Application.java rename to 1.x/spring-boot-scheduler/src/main/java/com/neo/Application.java diff --git a/1.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java b/1.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java new file mode 100644 index 000000000..7b59c9f2b --- /dev/null +++ b/1.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java @@ -0,0 +1,23 @@ +package com.neo.task; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by summer on 2016/12/1. + */ + +@Component +public class Scheduler2Task { + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + @Scheduled(fixedRate = 6000) + public void reportCurrentTime() { + System.out.println("现在时间:" + dateFormat.format(new Date())); + } + +} diff --git a/1.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java b/1.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java new file mode 100644 index 000000000..69885e3cc --- /dev/null +++ b/1.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java @@ -0,0 +1,22 @@ +package com.neo.task; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * Created by summer on 2016/12/1. + */ + +@Component +public class SchedulerTask { + + private int count=0; + + @Scheduled(cron="*/6 * * * * ?") + private void process(){ + System.out.println("this is scheduler task runing "+(count++)); + } + +} diff --git a/1.x/spring-boot-scheduler/src/main/resources/application.properties b/1.x/spring-boot-scheduler/src/main/resources/application.properties new file mode 100644 index 000000000..8978a46f1 --- /dev/null +++ b/1.x/spring-boot-scheduler/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=spirng-boot-scheduler + diff --git a/spring-boot-scheduler/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-scheduler/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-scheduler/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-scheduler/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-shiro/pom.xml b/1.x/spring-boot-shiro/pom.xml similarity index 98% rename from spring-boot-shiro/pom.xml rename to 1.x/spring-boot-shiro/pom.xml index 3d357ea56..0307f6d44 100644 --- a/spring-boot-shiro/pom.xml +++ b/1.x/spring-boot-shiro/pom.xml @@ -45,7 +45,7 @@ org.apache.shiro shiro-spring - 1.4.0 + 1.7.2 mysql diff --git a/spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java b/1.x/spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java diff --git a/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java b/1.x/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java diff --git a/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java b/1.x/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java diff --git a/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java b/1.x/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java b/1.x/spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java b/1.x/spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java b/1.x/spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java diff --git a/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java b/1.x/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java diff --git a/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java b/1.x/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java diff --git a/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java b/1.x/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/web/HomeController.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java diff --git a/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java b/1.x/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java similarity index 100% rename from spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java rename to 1.x/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java diff --git a/spring-boot-shiro/src/main/resources/application.yml b/1.x/spring-boot-shiro/src/main/resources/application.yml similarity index 100% rename from spring-boot-shiro/src/main/resources/application.yml rename to 1.x/spring-boot-shiro/src/main/resources/application.yml diff --git a/spring-boot-shiro/src/main/resources/database/import.sql b/1.x/spring-boot-shiro/src/main/resources/database/import.sql similarity index 100% rename from spring-boot-shiro/src/main/resources/database/import.sql rename to 1.x/spring-boot-shiro/src/main/resources/database/import.sql diff --git a/spring-boot-shiro/src/main/resources/templates/403.html b/1.x/spring-boot-shiro/src/main/resources/templates/403.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/403.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/403.html diff --git a/spring-boot-shiro/src/main/resources/templates/index.html b/1.x/spring-boot-shiro/src/main/resources/templates/index.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/index.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/index.html diff --git a/spring-boot-shiro/src/main/resources/templates/login.html b/1.x/spring-boot-shiro/src/main/resources/templates/login.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/login.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/login.html diff --git a/spring-boot-shiro/src/main/resources/templates/userInfo.html b/1.x/spring-boot-shiro/src/main/resources/templates/userInfo.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/userInfo.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/userInfo.html diff --git a/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html b/1.x/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/userInfoAdd.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html diff --git a/spring-boot-shiro/src/main/resources/templates/userInfoDel.html b/1.x/spring-boot-shiro/src/main/resources/templates/userInfoDel.html similarity index 100% rename from spring-boot-shiro/src/main/resources/templates/userInfoDel.html rename to 1.x/spring-boot-shiro/src/main/resources/templates/userInfoDel.html diff --git a/spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java b/1.x/spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java similarity index 100% rename from spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java rename to 1.x/spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java diff --git a/spring-boot-thymeleaf/pom.xml b/1.x/spring-boot-thymeleaf/pom.xml similarity index 100% rename from spring-boot-thymeleaf/pom.xml rename to 1.x/spring-boot-thymeleaf/pom.xml diff --git a/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/HelloController.java b/1.x/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/HelloController.java similarity index 100% rename from spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/HelloController.java rename to 1.x/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/HelloController.java diff --git a/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/ThymeleafApplication.java b/1.x/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/ThymeleafApplication.java similarity index 100% rename from spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/ThymeleafApplication.java rename to 1.x/spring-boot-thymeleaf/src/main/java/com/neo/thymeleaf/ThymeleafApplication.java diff --git a/spring-boot-thymeleaf/src/main/resources/application.properties b/1.x/spring-boot-thymeleaf/src/main/resources/application.properties similarity index 100% rename from spring-boot-thymeleaf/src/main/resources/application.properties rename to 1.x/spring-boot-thymeleaf/src/main/resources/application.properties diff --git a/1.x/spring-boot-thymeleaf/src/main/resources/templates/hello.html b/1.x/spring-boot-thymeleaf/src/main/resources/templates/hello.html new file mode 100644 index 000000000..bd1f7817e --- /dev/null +++ b/1.x/spring-boot-thymeleaf/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + + Hello Thymeleaf! + + +

+ + \ No newline at end of file diff --git a/1.x/spring-boot-web/pom.xml b/1.x/spring-boot-web/pom.xml new file mode 100644 index 000000000..ebeec70a0 --- /dev/null +++ b/1.x/spring-boot-web/pom.xml @@ -0,0 +1,90 @@ + + + 4.0.0 + + com.neo + spring-boot-web + 0.0.1-SNAPSHOT + jar + + spring-boot-web + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.6.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-devtools + true + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.webjars.bower + jquery + 2.0.3 + + + org.webjars.bower + bootstrap + 3.0.3 + + + org.springframework.boot + spring-boot-starter-redis + + + org.springframework.session + spring-session-data-redis + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/1.x/spring-boot-web/src/main/java/com/neo/Application.java b/1.x/spring-boot-web/src/main/java/com/neo/Application.java new file mode 100644 index 000000000..6cda50c81 --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/Application.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/1.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java b/1.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java new file mode 100644 index 000000000..cbf7177fd --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java @@ -0,0 +1,60 @@ +package com.neo; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.catalina.filters.RemoteIpFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebConfiguration { + @Bean + public RemoteIpFilter remoteIpFilter() { + return new RemoteIpFilter(); + } + + @Bean + public FilterRegistrationBean testFilterRegistration() { + + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new MyFilter()); + registration.addUrlPatterns("/*"); + registration.addInitParameter("paramName", "paramValue"); + registration.setName("MyFilter"); + registration.setOrder(1); + return registration; + } + + public class MyFilter implements Filter { + @Override + public void destroy() { + // TODO Auto-generated method stub + } + + @Override + public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain) + throws IOException, ServletException { + // TODO Auto-generated method stub + HttpServletRequest request = (HttpServletRequest) srequest; + System.out.println("this is MyFilter,url :"+request.getRequestURI()); + filterChain.doFilter(srequest, sresponse); + } + + @Override + public void init(FilterConfig arg0) throws ServletException { + // TODO Auto-generated method stub + } + } +} + + + diff --git a/spring-boot-web/src/main/java/com/neo/config/RedisConfig.java b/1.x/spring-boot-web/src/main/java/com/neo/config/RedisConfig.java similarity index 100% rename from spring-boot-web/src/main/java/com/neo/config/RedisConfig.java rename to 1.x/spring-boot-web/src/main/java/com/neo/config/RedisConfig.java diff --git a/spring-boot-web/src/main/java/com/neo/config/SessionConfig.java b/1.x/spring-boot-web/src/main/java/com/neo/config/SessionConfig.java similarity index 100% rename from spring-boot-web/src/main/java/com/neo/config/SessionConfig.java rename to 1.x/spring-boot-web/src/main/java/com/neo/config/SessionConfig.java diff --git a/spring-boot-web/src/main/java/com/neo/domain/User.java b/1.x/spring-boot-web/src/main/java/com/neo/domain/User.java similarity index 100% rename from spring-boot-web/src/main/java/com/neo/domain/User.java rename to 1.x/spring-boot-web/src/main/java/com/neo/domain/User.java diff --git a/spring-boot-web/src/main/java/com/neo/domain/UserRepository.java b/1.x/spring-boot-web/src/main/java/com/neo/domain/UserRepository.java similarity index 100% rename from spring-boot-web/src/main/java/com/neo/domain/UserRepository.java rename to 1.x/spring-boot-web/src/main/java/com/neo/domain/UserRepository.java diff --git a/1.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java b/1.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java new file mode 100644 index 000000000..ab337bfbd --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java @@ -0,0 +1,26 @@ +package com.neo.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class NeoProperties { + + @Value("${com.neo.title}") + private String title; + @Value("${com.neo.description}") + private String description; + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/1.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java b/1.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..5fd95a062 --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,30 @@ +package com.neo.web; + +import java.util.Locale; +import java.util.UUID; + +import javax.servlet.http.HttpSession; + +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/hello") + public String hello(Locale locale, Model model) { + return "hello world"; + } + + @RequestMapping("/uid") + String uid(HttpSession session) { + UUID uid = (UUID) session.getAttribute("uid"); + if (uid == null) { + uid = UUID.randomUUID(); + } + session.setAttribute("uid", uid); + return session.getId(); + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java b/1.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java new file mode 100644 index 000000000..c384bd1d8 --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java @@ -0,0 +1,26 @@ +package com.neo.web; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ThymeleafController { + + @RequestMapping("/hi") + public String hello(Locale locale, Model model) { + model.addAttribute("greeting", "Hello!"); + + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); + String formattedDate = dateFormat.format(date); + model.addAttribute("currentTime", formattedDate); + + return "hello"; + } + +} \ No newline at end of file diff --git a/1.x/spring-boot-web/src/main/java/com/neo/web/UserController.java b/1.x/spring-boot-web/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..983617cce --- /dev/null +++ b/1.x/spring-boot-web/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,34 @@ +package com.neo.web; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.neo.domain.User; +import com.neo.domain.UserRepository; + +@RestController +public class UserController { + + @Autowired + private UserRepository userRepository; + + @RequestMapping("/getUser") + @Cacheable(value="user-key") + public User getUser() { + User user=userRepository.findByUserName("aa"); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return user; + } + + @RequestMapping("/getUsers") + @Cacheable(value="key-Users") + public List getUsers() { + List users=userRepository.findAll(); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return users; + } +} \ No newline at end of file diff --git a/1.x/spring-boot-web/src/main/resources/application.properties b/1.x/spring-boot-web/src/main/resources/application.properties new file mode 100644 index 000000000..16fed3698 --- /dev/null +++ b/1.x/spring-boot-web/src/main/resources/application.properties @@ -0,0 +1,32 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/test +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.jdbc.Driver + +spring.jpa.properties.hibernate.hbm2ddl.auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.show-sql= true + +com.neo.title=\u7eaf\u6d01\u7684\u5fae\u7b11 +com.neo.description=\u5206\u4eab\u751f\u6d3b\u548c\u6280\u672f + +# REDIS (RedisProperties) +# Redis\u6570\u636e\u5e93\u7d22\u5f15\uff08\u9ed8\u8ba4\u4e3a0\uff09 +spring.redis.database=0 +# Redis\u670d\u52a1\u5668\u5730\u5740 +spring.redis.host=192.168.0.71 +# 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.pool.max-active=8 +# \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.pool.max-wait=-1 +# \u8fde\u63a5\u6c60\u4e2d\u7684\u6700\u5927\u7a7a\u95f2\u8fde\u63a5 +spring.redis.pool.max-idle=8 +# \u8fde\u63a5\u6c60\u4e2d\u7684\u6700\u5c0f\u7a7a\u95f2\u8fde\u63a5 +spring.redis.pool.min-idle=0 +# \u8fde\u63a5\u8d85\u65f6\u65f6\u95f4\uff08\u6beb\u79d2\uff09 +spring.redis.timeout=0 + diff --git a/1.x/spring-boot-web/src/main/resources/static/css/starter.css b/1.x/spring-boot-web/src/main/resources/static/css/starter.css new file mode 100644 index 000000000..e2fc60cd4 --- /dev/null +++ b/1.x/spring-boot-web/src/main/resources/static/css/starter.css @@ -0,0 +1,8 @@ +body { + padding-top: 50px; +} + +.starter-template { + padding: 40px 15px; + text-align: center; +} \ No newline at end of file diff --git a/1.x/spring-boot-web/src/main/resources/static/images/favicon.png b/1.x/spring-boot-web/src/main/resources/static/images/favicon.png new file mode 100644 index 000000000..890ef0630 Binary files /dev/null and b/1.x/spring-boot-web/src/main/resources/static/images/favicon.png differ diff --git a/1.x/spring-boot-web/src/main/resources/templates/hello.html b/1.x/spring-boot-web/src/main/resources/templates/hello.html new file mode 100644 index 000000000..c417054af --- /dev/null +++ b/1.x/spring-boot-web/src/main/resources/templates/hello.html @@ -0,0 +1,18 @@ + + + + +

(navbar)
+ +
+
+

Spring MVC / Thymeleaf / Bootstrap

+

(greeting)

+

The current time is (time)

+
+
+ + + + + diff --git a/1.x/spring-boot-web/src/main/resources/templates/layout.html b/1.x/spring-boot-web/src/main/resources/templates/layout.html new file mode 100644 index 000000000..422fbb71e --- /dev/null +++ b/1.x/spring-boot-web/src/main/resources/templates/layout.html @@ -0,0 +1,54 @@ + + + + + + + + + + (title) + + + + + + + + +
+
+

Spring MVC/Thymeleaf/Bootstrap

+

(greeting)

+
+
+ + + + + diff --git a/spring-boot-web/src/test/java/com/neo/ApplicationTests.java b/1.x/spring-boot-web/src/test/java/com/neo/ApplicationTests.java similarity index 100% rename from spring-boot-web/src/test/java/com/neo/ApplicationTests.java rename to 1.x/spring-boot-web/src/test/java/com/neo/ApplicationTests.java diff --git a/spring-boot-web/src/test/java/com/neo/domain/UserRepositoryTests.java b/1.x/spring-boot-web/src/test/java/com/neo/domain/UserRepositoryTests.java similarity index 100% rename from spring-boot-web/src/test/java/com/neo/domain/UserRepositoryTests.java rename to 1.x/spring-boot-web/src/test/java/com/neo/domain/UserRepositoryTests.java diff --git a/spring-boot-web/src/test/java/com/neo/util/TestRedis.java b/1.x/spring-boot-web/src/test/java/com/neo/util/TestRedis.java similarity index 100% rename from spring-boot-web/src/test/java/com/neo/util/TestRedis.java rename to 1.x/spring-boot-web/src/test/java/com/neo/util/TestRedis.java diff --git a/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java b/1.x/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java similarity index 100% rename from spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java rename to 1.x/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java diff --git a/1.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java b/1.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java new file mode 100644 index 000000000..ae0b39960 --- /dev/null +++ b/1.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java @@ -0,0 +1,40 @@ +package com.neo.web; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.neo.Application; +import com.neo.util.NeoProperties; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ProPertiesTest { + + + @Autowired + private NeoProperties neoProperties; + + + @Test + public void getHello() throws Exception { + System.out.println(neoProperties.getTitle()); + Assert.assertEquals(neoProperties.getTitle(), "纯洁的微笑"); + Assert.assertEquals(neoProperties.getDescription(), "分享生活和技术"); + } + + + @Test + public void testMap() throws Exception { + Map orderMinTime=new HashMap(); + long xx=orderMinTime.get("123"); + } + +} \ No newline at end of file diff --git a/2.x/README.md b/2.x/README.md new file mode 100644 index 000000000..5d86202fd --- /dev/null +++ b/2.x/README.md @@ -0,0 +1,118 @@ +Spring Boot 学习示例 +========================= + +![Spring Boot 2.0](https://img.shields.io/badge/Spring%20Boot-2.0-brightgreen.svg) +![Mysql 5.6](https://img.shields.io/badge/Mysql-5.6-blue.svg) +![JDK 1.8](https://img.shields.io/badge/JDK-1.8-brightgreen.svg) +![Maven](https://img.shields.io/badge/Maven-3.5.0-yellowgreen.svg) +![license](https://img.shields.io/badge/license-MPL--2.0-blue.svg) + +Spring Boot 使用的各种示例,以最简单、最实用为标准,此开源项目中的每个示例都以最小依赖,最简单为标准,帮助初学者快速掌握 Spring Boot 各组件的使用。 + +[Spring Boot 中文索引](https://github.com/ityouknow/awesome-spring-boot)  |   [Spring Cloud学习示例代码](https://github.com/ityouknow/spring-cloud-examples)  |   [Spring Boot 精品课程](https://github.com/ityouknow/spring-boot-leaning) + +[English](README_EN.md)  |   [Github地址](https://github.com/ityouknow/spring-boot-examples)  |   [码云地址](https://gitee.com/ityouknow/spring-boot-examples)  |   [Spring Boot 1.0](https://github.com/ityouknow/spring-boot-examples/tree/Spring-Boot-1.0) + +--- + +推荐程序员都关注的一个漫画公众号 + +![](http://www.ityouknow.com/assets/images/cartoon.jpg) + +关注后,回复:**java** 获取超过 10万 人领取的 Java 知识体系/面试必看资料。 + + + +## Spring Boot 2.0 + +**[Spring Boot 2.0 最全使用教程](https://github.com/ityouknow/spring-boot-leaning)** + +**[Favorites-web](https://github.com/cloudfavorites/favorites-web):云收藏(Spring Boot 2.0 实战开源项目)** + +**示例代码** + +- [spring-boot-hello](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-hello):Spring Boot 2.0 Hello World 示例 +- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-banner):Spring Boot 定制 Banner 示例 +- [spring-boot-docker](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-docker):使用 Docker 部署 Spring Boot 示例 +- [dockercompose-springboot-mysql-nginx](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/dockercompose-springboot-mysql-nginx) :Docker Compose + Spring Boot + Nginx + Mysql 示例 +- [spring-boot-commandLineRunner](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-commandLineRunner) :Spring Boot 使用 commandLineRunner 实现项目启动时资源初始化示例 +- [spring-boot-web-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-web-thymeleaf) :Spring Boot 使用 thymeleaf 实现布局、验参、增删改查示例 +- [spring-boot-memcache-spymemcached](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-memcache-spymemcached) :Spring Boot 使用 spymemcached 集成 memcache 示例 +- [spring-boot-webflux](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-webflux) :Spring Boot webflux 示例 +- [spring-boot-elasticsearch](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-elasticsearch) :Spring Boot elasticsearch 示例 +- [spring-boot-swagger](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-swagger) :Spring Boot swagger2 示例 +- [spring-boot-mybatis-plus](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis-plus) :Spring Boot 集成 MyBatis Plus 示例 + +**参考文章** + +- [Spring Boot 2(一):【重磅】Spring Boot 2.0权威发布](http://www.ityouknow.com/springboot/2018/03/01/spring-boot-2.0.html) +- [Spring Boot 2(二):Spring Boot 2.0尝鲜-动态 Banner](http://www.ityouknow.com/springboot/2018/03/03/spring-boot-banner.html) +- [Spring Boot 2(三):Spring Boot 开源软件都有哪些?](http://www.ityouknow.com/springboot/2018/03/05/spring-boot-open-source.html) +- [Spring Boot 2(四):使用 Docker 部署 Spring Boot](http://www.ityouknow.com/springboot/2018/03/19/spring-boot-docker.html) +- [Spring Boot 2(五):Docker Compose + Spring Boot + Nginx + Mysql 实践](http://www.ityouknow.com/springboot/2018/03/28/dockercompose-springboot-mysql-nginx.html) +- [Spring Boot 2(六):使用 Docker 部署 Spring Boot 开源软件云收藏](http://www.ityouknow.com/springboot/2018/04/02/docker-favorites.html) +- [Spring Boot 2(七):Spring Boot 如何解决项目启动时初始化资源](http://www.ityouknow.com/springboot/2018/05/03/spring-boot-commandLineRunner.html) +- [Spring Boot 2(八):Spring Boot 集成 Memcached](http://www.ityouknow.com/springboot/2018/09/01/spring-boot-memcached.html) +- [Spring Boot 2 (九):【重磅】Spring Boot 2.1.0 权威发布](http://www.ityouknow.com/springboot/2018/11/03/spring-boot-2.1.html) +- [Spring Boot/Cloud 研发团队介绍](http://www.ityouknow.com/springboot/2019/01/03/spring-pivotal.html) +- [Spring Boot 2 (十):Spring Boot 中的响应式编程和 WebFlux 入门](http://www.ityouknow.com/springboot/2019/02/12/spring-boot-webflux.html) + + +## 下方示例已经全部升级到 2.X + +**示例代码** + +- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-helloWorld):Spring Boot 的 hello World 版本 +- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-web):Spring Boot Web 开发综合示例 +- [spring-boot-redis](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-redis):Spring Boot 集成 Redis 示例 +- [spring-boot-jpa](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-jpa):Spring Boot 使用 Jpa 各种示例 +- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation):注解版本 +- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-xml):Xml 配置版本 +- [spring-boot-mybatis-xml-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource):Spring Boot + Mybatis (Xml 版) 多数据源最简解决方案 +- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource):Spring Boot + Mybatis(注解版)多数据源最简解决方案 +- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-thymeleaf):Spring Boot 使用 Thymeleaf 详细示例 +- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-jpa-thymeleaf-curd):Spring Boot + Jpa + Thymeleaf 增删改查示例 +- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-rabbitmq):Spring Boot 和 Rabbitmq 各种消息应用案例 +- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-scheduler):Spring Boot 和定时任务案例 +- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mail):Spring Boot 和邮件服务 +- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mongodb/spring-boot-mongodb):Spring Boot 和 Mongodb 的使用 +- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mongodb/spring-boot-multi-mongodb):Spring Boot 和 Mongodb 多数据源的使用 +- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-package-war): Spring Boot 打包成 War 包示例 +- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-shiro):Spring Boot 整合 Shiro Rbac 示例 +- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-file-upload):使用 Spring Boot 上传文件示例 +- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-fastDFS):Spring Boot 整合 FastDFS 示例 +- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-actuator):Spring Boot Actuator 使用示例 +- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-admin-simple):Spring Boot Admin 的使用示例 + +**参考文章** + +- [Spring Boot(一):入门篇](http://www.ityouknow.com/springboot/2016/01/06/spring-boot-quick-start.html) +- [Spring Boot(二):Web 综合开发](http://www.ityouknow.com/springboot/2016/02/03/spring-boot-web.html) +- [Spring Boot(三):Spring Boot 中 Redis 的使用](http://www.ityouknow.com/springboot/2016/03/06/spring-boot-redis.html) +- [Spring Boot(四):Thymeleaf 使用详解](http://www.ityouknow.com/springboot/2016/05/01/spring-boot-thymeleaf.html) +- [Spring Boot(五):Spring Data Jpa 的使用](http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html) +- [Spring Boot(六):如何优雅的使用 Mybatis](http://www.ityouknow.com/springboot/2016/11/06/spring-boot-mybatis.html) +- [Spring Boot(七):Spring Boot + Mybatis 多数据源最简解决方案](http://www.ityouknow.com/springboot/2016/11/25/spring-boot-multi-mybatis.html) +- [Spring Boot(八):RabbitMQ 详解](http://www.ityouknow.com/springboot/2016/11/30/spring-boot-rabbitMQ.html) +- [Spring Boot(九):定时任务](http://www.ityouknow.com/springboot/2016/12/02/spring-boot-scheduler.html) +- [Spring Boot(十):邮件服务](http://www.ityouknow.com/springboot/2017/05/06/spring-boot-mail.html) +- [Spring Boot(十一):Spring Boot 中 Mongodb 的使用](http://www.ityouknow.com/springboot/2017/05/08/spring-boot-mongodb.html) +- [Spring Boot(十二):Spring Boot 如何测试打包部署](http://www.ityouknow.com/springboot/2017/05/09/spring-boot-deploy.html) +- [Spring Boot(十三):Spring Boot 小技巧](http://www.ityouknow.com/springboot/2017/06/22/spring-boot-tips.html) +- [Spring Boot(十四):Spring Boot 整合 Shiro-登录认证和权限管理](http://www.ityouknow.com/springboot/2017/06/26/spring-boot-shiro.html) +- [Spring Boot(十五):Spring Boot + Jpa + Thymeleaf 增删改查示例](http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html) +- [Spring Boot(十六):使用 Jenkins 部署 Spring Boot](http://www.ityouknow.com/springboot/2017/11/11/spring-boot-jenkins.html) +- [Spring Boot(十七):使用 Spring Boot 上传文件](http://www.ityouknow.com/springboot/2018/01/12/spring-boot-upload-file.html) +- [Spring Boot(十八):使用 Spring Boot 集成 FastDFS](http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html) +- [Spring Boot(十九):使用 Spring Boot Actuator 监控应用](http://www.ityouknow.com/springboot/2018/02/06/spring-boot-actuator.html) +- [Spring Boot(二十):使用 spring-boot-admin 对 Spring Boot 服务进行监控](http://www.ityouknow.com/springboot/2018/02/11/spring-boot-admin.html) + +**[Spring Boot 实战:我们的第一款开源项目](http://www.ityouknow.com/springboot/2016/09/26/spring-boot-opensource-favorites.html)** + +--- + +> 如果大家想了解关于 Spring Boot 的其它方面应用,也可以以[issues](https://github.com/ityouknow/spring-boot-examples/issues)的形式反馈给我,我后续来完善。 + +关注公众号:纯洁的微笑,回复"666"进群交流 + +![](http://www.ityouknow.com/assets/images/keeppuresmile_430.jpg) \ No newline at end of file diff --git a/2.x/README_EN.md b/2.x/README_EN.md new file mode 100644 index 000000000..2868c31f5 --- /dev/null +++ b/2.x/README_EN.md @@ -0,0 +1,54 @@ +# Spring Boot Examples + +This tutorial is about learning Spring Boot via examples. + +[Spring Cloud Example Code](https://github.com/ityouknow/spring-cloud-examples)  |   [中文](README.md) + +Spring Boot examples, using the simplest and the most useful scene demos. + +--- + +## Spring Boot 2.X + + +**[Favorites-web](https://github.com/cloudfavorites/favorites-web):Open source projects developed using Spring Boot 2.X** + +- [spring-boot-hello](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-hello):Spring Boot 2.0 Hello World Demo +- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-banner):Spring Boot Customized Banner +- [spring-boot-docker](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-docker):Spring Boot with Docker +- [dockercompose-springboot-mysql-nginx](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/dockercompose-springboot-mysql-nginx) :Docker Compose + Spring Boot + Nginx + Mysql example +- [spring-boot-commandLineRunner](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-commandLineRunner) :Example of resource initialization at project startup using Spring Boot and commandLineRunner +- [spring-boot-web-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-web-thymeleaf) :Spring Boot uses thymeleaf to implement layout, check parameters and CURD +- [spring-boot-memcache-spymemcached](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-memcache-spymemcached) :Spring Boot uses spymemcached to memcache +- [spring-boot-webflux](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-webflux) :Spring Boot webflux demo +- [spring-boot-elasticsearch](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-elasticsearch) :Spring Boot elasticsearch demo +- [spring-boot-swagger](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-swagger) :Spring Boot swagger2 demo +- [spring-boot-mybatis-plus](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis-plus) :Spring Boot MyBatis Plus demo + + +--- + +## Spring Boot (Already upgraded to 2.x) + +- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-helloWorld):Spring Boot helloWorld +- [spring-boot-redis](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-redis):Spring Boot Redis Demo +- [spring-boot-jpa](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-jpa):Spring Boot Jpa Demo +- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation):Spring Boot use mybatis annotation +- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-xml):Spring Boot use mybatis xml +- [spring-boot-mybatis-xml-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource):Spring Boot+mybatis+mulidatasource +- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource):Spring Boot+ mybatis annotation + mulidatasource +- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-thymeleaf):Spring Boot Thymeleaf Demo +- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-jpa-thymeleaf-curd):spring boot + jpa + thymeleaf curd demo +- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-rabbitmq): using AMQP and RabbitMQ +- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-scheduler):Timed tasks developed using Spring Boot +- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-web):Web projects developed using Spring Boot +- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mail):Mail system developed using Spring Boot +- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mongodb/spring-boot-mongodb):Spring Boot + Mongodb +- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-mongodb/spring-boot-multi-mongodb):Spring Boot + multiMongodb +- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-package-war):Spring Boot package war +- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-shiro):spring boot shiro rbac demo +- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-file-upload):Spring Boot upload file demo +- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-fastDFS):Spring Boot Integrate FastDFS upload delete and so on +- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-actuator):Spring Boot Actuator demo +- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-admin-simple):Spring Boot Admin demo +- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x/spring-boot-banner):Spring Boot Cumtom Banner diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/Dockerfile b/2.x/dockercompose-springboot-mysql-nginx/app/Dockerfile new file mode 100644 index 000000000..6ae65e4e7 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/Dockerfile @@ -0,0 +1 @@ +FROM maven:3.5-jdk-8 \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/pom.xml b/2.x/dockercompose-springboot-mysql-nginx/app/pom.xml new file mode 100644 index 000000000..1dc59f64b --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.neo + dockercompose-springboot-mysql-nginx + 1.0 + jar + + dockercompose-springboot-mysql-nginx + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + compile + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/ComposeApplication.java b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/ComposeApplication.java new file mode 100644 index 000000000..9c2646d0a --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/ComposeApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ComposeApplication { + + public static void main(String[] args) { + SpringApplication.run(ComposeApplication.class, args); + } +} diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java new file mode 100644 index 000000000..583be103f --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java @@ -0,0 +1,31 @@ +package com.neo.controller; + +import com.neo.entity.Visitor; +import com.neo.repository.VisitorRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +@RestController +public class VisitorController { + + @Autowired + private VisitorRepository repository; + + @RequestMapping("/") + public String index(HttpServletRequest request) { + String ip=request.getRemoteAddr(); + Visitor visitor=repository.findByIp(ip); + if(visitor==null){ + visitor=new Visitor(); + visitor.setIp(ip); + visitor.setTimes(1); + }else { + visitor.setTimes(visitor.getTimes()+1); + } + repository.save(visitor); + return "I have been seen ip "+visitor.getIp()+" "+visitor.getTimes()+" times."; + } +} \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java new file mode 100644 index 000000000..43cfa34b0 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java @@ -0,0 +1,41 @@ +package com.neo.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Visitor { + @Id + @GeneratedValue + private long id; + @Column(nullable = false) + private long times; + @Column(nullable = false) + private String ip; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getTimes() { + return times; + } + + public void setTimes(long times) { + this.times = times; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } +} diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/repository/VisitorRepository.java b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/repository/VisitorRepository.java new file mode 100644 index 000000000..7395c3962 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/repository/VisitorRepository.java @@ -0,0 +1,8 @@ +package com.neo.repository; + +import com.neo.entity.Visitor; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VisitorRepository extends JpaRepository { + Visitor findByIp(String ip); +} diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties new file mode 100644 index 000000000..25126f01f --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/test +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties new file mode 100644 index 000000000..eacae6203 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties @@ -0,0 +1,4 @@ +spring.datasource.url=jdbc:mysql://mysql:3306/test +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.jdbc.Driver \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties new file mode 100644 index 000000000..242edfd64 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.jpa.properties.hibernate.hbm2ddl.auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.show-sql=true + +spring.profiles.active=dev \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/app/src/test/java/com/neo/ComposeApplicationTests.java b/2.x/dockercompose-springboot-mysql-nginx/app/src/test/java/com/neo/ComposeApplicationTests.java new file mode 100644 index 000000000..b0f9edf6a --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/app/src/test/java/com/neo/ComposeApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ComposeApplicationTests { + + @Test + public void contextLoads() { + System.out.println("Hello Spring Boot Docker Compose!"); + } + +} diff --git a/2.x/dockercompose-springboot-mysql-nginx/docker-compose.yaml b/2.x/dockercompose-springboot-mysql-nginx/docker-compose.yaml new file mode 100644 index 000000000..028978f5b --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/docker-compose.yaml @@ -0,0 +1,36 @@ +version: '3' +services: + nginx: + container_name: v-nginx + image: nginx:1.13 + restart: always + ports: + - 80:80 + - 443:443 + volumes: + - ./nginx/conf.d:/etc/nginx/conf.d + + mysql: + container_name: v-mysql + image: mysql/mysql-server:5.7 + environment: + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: root + MYSQL_ROOT_HOST: '%' + ports: + - "3306:3306" + restart: always + + app: + restart: always + build: ./app + working_dir: /app + volumes: + - ./app:/app + - ~/.m2:/root/.m2 + expose: + - "8080" + depends_on: + - nginx + - mysql + command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker \ No newline at end of file diff --git a/2.x/dockercompose-springboot-mysql-nginx/nginx/conf.d/app.conf b/2.x/dockercompose-springboot-mysql-nginx/nginx/conf.d/app.conf new file mode 100644 index 000000000..486051450 --- /dev/null +++ b/2.x/dockercompose-springboot-mysql-nginx/nginx/conf.d/app.conf @@ -0,0 +1,20 @@ +server { + listen 80; + charset utf-8; + access_log off; + + location / { + proxy_pass http://app:8080; + proxy_set_header Host $host:$server_port; + proxy_set_header X-Forwarded-Host $server_name; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + location /static { + access_log off; + expires 30d; + + alias /app/static; + } +} diff --git a/2.x/pom.xml b/2.x/pom.xml new file mode 100644 index 000000000..dd4658e00 --- /dev/null +++ b/2.x/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.example + spring-boot-examples + pom + 2.0.0 + + + dockercompose-springboot-mysql-nginx/app + spring-boot-actuator + spring-boot-admin-simple + spring-boot-banner + spring-boot-commandLineRunner + spring-boot-docker + spring-boot-elasticsearch + spring-boot-file-upload + spring-boot-hello + spring-boot-helloWorld + spring-boot-jpa/spring-boot-jpa + spring-boot-jpa/spring-boot-multi-Jpa + spring-boot-jpa-thymeleaf-curd + spring-boot-mail + spring-boot-memcache-spymemcached + spring-boot-mongodb/spring-boot-mongodb + spring-boot-mongodb/spring-boot-multi-mongodb + spring-boot-mybatis/spring-boot-mybatis-annotation + spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource + spring-boot-mybatis/spring-boot-mybatis-xml + spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource + spring-boot-mybatis-plus + spring-boot-package + spring-boot-package-war + spring-boot-rabbitmq + spring-boot-redis + spring-boot-scheduler + spring-boot-shiro + spring-boot-swagger + spring-boot-thymeleaf/spring-boot-thymeleaf + spring-boot-thymeleaf/spring-boot-thymeleaf-layout + spring-boot-web + spring-boot-web-thymeleaf + spring-boot-webflux + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-actuator/pom.xml b/2.x/spring-boot-actuator/pom.xml new file mode 100644 index 000000000..770a97118 --- /dev/null +++ b/2.x/spring-boot-actuator/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + com.neo + spring-boot-actuator + 1.0.0-SNAPSHOT + jar + + spring-boot-actuator + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + 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-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + diff --git a/2.x/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java b/2.x/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java new file mode 100644 index 000000000..66b22076b --- /dev/null +++ b/2.x/spring-boot-actuator/src/main/java/com/neo/ActuatorApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ActuatorApplication { + + public static void main(String[] args) { + SpringApplication.run(ActuatorApplication.class, args); + } +} diff --git a/2.x/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java b/2.x/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java new file mode 100644 index 000000000..5e93f0dda --- /dev/null +++ b/2.x/spring-boot-actuator/src/main/java/com/neo/controller/HelloController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-actuator/src/main/resources/application.properties b/2.x/spring-boot-actuator/src/main/resources/application.properties new file mode 100644 index 000000000..4157eba14 --- /dev/null +++ b/2.x/spring-boot-actuator/src/main/resources/application.properties @@ -0,0 +1,9 @@ +info.app.name=spring-boot-actuator +info.app.version= 1.0.0 +info.app.test=test + +management.endpoints.web.exposure.include=* +management.endpoint.health.show-details=always +#management.endpoints.web.base-path=/manage + +management.endpoint.shutdown.enabled=true diff --git a/2.x/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java b/2.x/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java new file mode 100644 index 000000000..e122032a2 --- /dev/null +++ b/2.x/spring-boot-actuator/src/test/java/com/neo/ActuatorApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ActuatorApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello word"); + } + +} diff --git a/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java b/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..149543930 --- /dev/null +++ b/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,36 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..d8b01a50d --- /dev/null +++ b/2.x/spring-boot-actuator/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,34 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-admin-simple/pom.xml b/2.x/spring-boot-admin-simple/pom.xml new file mode 100644 index 000000000..b75244055 --- /dev/null +++ b/2.x/spring-boot-admin-simple/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + com.neo + spring-boot-admin-simple + 1.0.0.BUILD-SNAPSHOT + + + spring-boot-admin-server + spring-boot-admin-client + + + pom + Spring boot admin + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + Edgware.SR1 + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-client/pom.xml b/2.x/spring-boot-admin-simple/spring-boot-admin-client/pom.xml new file mode 100644 index 000000000..3f456f43b --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-client/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.neo + spring-boot-admin-simple + 1.0.0.BUILD-SNAPSHOT + + spring-boot-admin-client + jar + + + + de.codecentric + spring-boot-admin-starter-client + 2.1.0 + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java new file mode 100644 index 000000000..9494e5efe --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/java/com/neo/AdminClientApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AdminClientApplication { + + public static void main(String[] args) { + SpringApplication.run(AdminClientApplication.class, args); + } +} diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties new file mode 100644 index 000000000..a9ef7959b --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/main/resources/application.properties @@ -0,0 +1,5 @@ +server.port=8001 + +spring.application.name=Admin Client +spring.boot.admin.client.url=http://localhost:8000 +management.endpoints.web.exposure.include=* \ No newline at end of file diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java new file mode 100644 index 000000000..ad4141adf --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-client/src/test/java/com/neo/AdminClientApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class AdminClientApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-server/pom.xml b/2.x/spring-boot-admin-simple/spring-boot-admin-server/pom.xml new file mode 100644 index 000000000..23881f472 --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-server/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.neo + spring-boot-admin-simple + 1.0.0.BUILD-SNAPSHOT + + spring-boot-admin-server + jar + + + + de.codecentric + spring-boot-admin-starter-server + 2.1.0 + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java new file mode 100644 index 000000000..b939267cd --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/java/com/neo/AdminServerApplication.java @@ -0,0 +1,16 @@ +package com.neo; + +import de.codecentric.boot.admin.server.config.EnableAdminServer; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableAutoConfiguration +@EnableAdminServer +public class AdminServerApplication { + + public static void main(String[] args) { + SpringApplication.run(AdminServerApplication.class, args); + } +} diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties new file mode 100644 index 000000000..4e7c8e915 --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8000 + diff --git a/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java new file mode 100644 index 000000000..6179c4d40 --- /dev/null +++ b/2.x/spring-boot-admin-simple/spring-boot-admin-server/src/test/java/com/neo/AdminServerApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class AdminServerApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-banner/pom.xml b/2.x/spring-boot-banner/pom.xml new file mode 100644 index 000000000..763b87317 --- /dev/null +++ b/2.x/spring-boot-banner/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.example + spring-boot-banner + 2.0.0 + jar + + Spring Boot banner + A very useful project to demonstrate animated gif support in Spring Boot 2 + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-banner/src/main/java/com/neo/banner/BannerApplication.java b/2.x/spring-boot-banner/src/main/java/com/neo/banner/BannerApplication.java new file mode 100644 index 000000000..4e7bc12db --- /dev/null +++ b/2.x/spring-boot-banner/src/main/java/com/neo/banner/BannerApplication.java @@ -0,0 +1,12 @@ +package com.neo.banner; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BannerApplication { + + public static void main(String[] args) { + SpringApplication.run(BannerApplication.class, args); + } +} diff --git a/2.x/spring-boot-banner/src/main/resources/application.properties b/2.x/spring-boot-banner/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-banner/src/main/resources/banner.gif b/2.x/spring-boot-banner/src/main/resources/banner.gif new file mode 100644 index 000000000..73f318282 Binary files /dev/null and b/2.x/spring-boot-banner/src/main/resources/banner.gif differ diff --git a/2.x/spring-boot-banner/src/main/resources/banner.txt b/2.x/spring-boot-banner/src/main/resources/banner.txt new file mode 100644 index 000000000..79bcf7576 --- /dev/null +++ b/2.x/spring-boot-banner/src/main/resources/banner.txt @@ -0,0 +1,6 @@ +.__ .__ .__ .__ .___ +| |__ ____ | | | | ____ __ _ _____________| | __| _/ +| | \_/ __ \| | | | / _ \ \ \/ \/ / _ \_ __ \ | / __ | +| Y \ ___/| |_| |_( <_> ) \ ( <_> ) | \/ |__/ /_/ | +|___| /\___ >____/____/\____/ \/\_/ \____/|__| |____/\____ | + \/ \/ \/ \ No newline at end of file diff --git a/2.x/spring-boot-commandLineRunner/pom.xml b/2.x/spring-boot-commandLineRunner/pom.xml new file mode 100644 index 000000000..3dd6ee720 --- /dev/null +++ b/2.x/spring-boot-commandLineRunner/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + + com.example + spring-boot-commandLineRunner + 2.0.0 + jar + + Spring Boot banner + Spring Boot and commandLineRunner demo + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/CommandLineRunnerApplication.java b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/CommandLineRunnerApplication.java new file mode 100644 index 000000000..d1f685efa --- /dev/null +++ b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/CommandLineRunnerApplication.java @@ -0,0 +1,15 @@ +package com.neo; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CommandLineRunnerApplication { + + public static void main(String[] args) { + System.out.println("The service to start."); + SpringApplication.run(CommandLineRunnerApplication.class, args); + System.out.println("The service has started."); + } +} diff --git a/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner1.java b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner1.java new file mode 100644 index 000000000..ea92d0d13 --- /dev/null +++ b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner1.java @@ -0,0 +1,15 @@ +package com.neo.runner; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@Order(1) +public class OrderRunner1 implements CommandLineRunner { + + @Override + public void run(String... args) throws Exception { + System.out.println("The OrderRunner1 start to initialize ..."); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner2.java b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner2.java new file mode 100644 index 000000000..7265d82b1 --- /dev/null +++ b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/OrderRunner2.java @@ -0,0 +1,15 @@ +package com.neo.runner; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@Order(2) +public class OrderRunner2 implements CommandLineRunner { + + @Override + public void run(String... args) throws Exception { + System.out.println("The OrderRunner2 start to initialize ..."); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/Runner.java b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/Runner.java new file mode 100644 index 000000000..647605d8e --- /dev/null +++ b/2.x/spring-boot-commandLineRunner/src/main/java/com/neo/runner/Runner.java @@ -0,0 +1,13 @@ +package com.neo.runner; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +@Component +public class Runner implements CommandLineRunner { + + @Override + public void run(String... args) throws Exception { + System.out.println("The Runner start to initialize ..."); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-commandLineRunner/src/main/resources/application.properties b/2.x/spring-boot-commandLineRunner/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-docker/pom.xml b/2.x/spring-boot-docker/pom.xml new file mode 100644 index 000000000..17946da0c --- /dev/null +++ b/2.x/spring-boot-docker/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.neo + spring-boot-docker + 1.0 + jar + + spring-boot-docker + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + UTF-8 + 1.8 + springboot + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + com.spotify + docker-maven-plugin + 1.0.0 + + ${docker.image.prefix}/${project.artifactId} + src/main/docker + + + / + ${project.build.directory} + ${project.build.finalName}.jar + + + + + + + + + + diff --git a/2.x/spring-boot-docker/src/main/docker/Dockerfile b/2.x/spring-boot-docker/src/main/docker/Dockerfile new file mode 100644 index 000000000..be52a4852 --- /dev/null +++ b/2.x/spring-boot-docker/src/main/docker/Dockerfile @@ -0,0 +1,4 @@ +FROM openjdk:8-jdk-alpine +VOLUME /tmp +ADD spring-boot-docker-1.0.jar app.jar +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/2.x/spring-boot-docker/src/main/java/com/neo/DockerApplication.java b/2.x/spring-boot-docker/src/main/java/com/neo/DockerApplication.java new file mode 100644 index 000000000..d3a027626 --- /dev/null +++ b/2.x/spring-boot-docker/src/main/java/com/neo/DockerApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DockerApplication { + + public static void main(String[] args) { + SpringApplication.run(DockerApplication.class, args); + } +} diff --git a/2.x/spring-boot-docker/src/main/java/com/neo/controller/DockerController.java b/2.x/spring-boot-docker/src/main/java/com/neo/controller/DockerController.java new file mode 100644 index 000000000..8b6ba6760 --- /dev/null +++ b/2.x/spring-boot-docker/src/main/java/com/neo/controller/DockerController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DockerController { + + @RequestMapping("/") + public String index() { + return "Hello Docker!"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-docker/src/main/resources/application.properties b/2.x/spring-boot-docker/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java b/2.x/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java new file mode 100644 index 000000000..b08b68913 --- /dev/null +++ b/2.x/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class DockerApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello docker"); + } + +} diff --git a/2.x/spring-boot-elasticsearch/pom.xml b/2.x/spring-boot-elasticsearch/pom.xml new file mode 100644 index 000000000..939098a08 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + com.neo + spring-boot-elasticsearch + 1.0 + jar + + spring-boot-elasticsearch + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-elasticsearch + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-elasticsearch/src/main/java/com/neo/ElasticsearchApplication.java b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/ElasticsearchApplication.java new file mode 100644 index 000000000..e16db52a3 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/ElasticsearchApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ElasticsearchApplication { + + public static void main(String[] args) { + SpringApplication.run(ElasticsearchApplication.class, args); + } +} diff --git a/2.x/spring-boot-elasticsearch/src/main/java/com/neo/model/Customer.java b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/model/Customer.java new file mode 100644 index 000000000..e71076db0 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/model/Customer.java @@ -0,0 +1,71 @@ + +package com.neo.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; + +@Document(indexName = "customer", type = "customer", shards = 1, replicas = 0, refreshInterval = "-1") +public class Customer { + + //Id注解加上后,在Elasticsearch里相应于该列就是主键了,在查询时就可以直接用主键查询 + @Id + private String id; + + private String userName; + + private String address; + + private int age; + + public Customer() { + } + + public Customer(String userName, String address, int age) { + this.userName = userName; + this.address = address; + this.age = age; + } + + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getAddress() { + return address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public void setAddress(String address) { + this.address = address; + } + + @Override + public String toString() { + return "Customer{" + + "id='" + id + '\'' + + ", userName='" + userName + '\'' + + ", address='" + address + '\'' + + ", age=" + age + + '}'; + } +} diff --git a/2.x/spring-boot-elasticsearch/src/main/java/com/neo/repository/CustomerRepository.java b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/repository/CustomerRepository.java new file mode 100644 index 000000000..fec24b4d4 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/repository/CustomerRepository.java @@ -0,0 +1,19 @@ + +package com.neo.repository; + +import com.neo.model.Customer; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +import java.util.List; + + +public interface CustomerRepository extends ElasticsearchRepository { + public List findByAddress(String address); + public Customer findByUserName(String userName); + public int deleteByUserName(String userName); + public Page findByAddress(String address, Pageable pageable); + + +} diff --git a/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/CustomersInterface.java b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/CustomersInterface.java new file mode 100644 index 000000000..ad36175a9 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/CustomersInterface.java @@ -0,0 +1,12 @@ +package com.neo.service; + +import com.neo.model.Customer; + +import java.util.List; + +public interface CustomersInterface { + + public List searchCity(Integer pageNumber, Integer pageSize, String searchContent); + + +} diff --git a/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/impl/CustomersInterfaceImpl.java b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/impl/CustomersInterfaceImpl.java new file mode 100644 index 000000000..742a52b1d --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/java/com/neo/service/impl/CustomersInterfaceImpl.java @@ -0,0 +1,50 @@ +package com.neo.service.impl; + +import com.neo.model.Customer; +import com.neo.repository.CustomerRepository; +import com.neo.service.CustomersInterface; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; +import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; + +import java.util.List; + +public class CustomersInterfaceImpl implements CustomersInterface { + + Logger logger= LoggerFactory.getLogger(this.getClass()); + @Autowired + private CustomerRepository customerRepository; + + @Override + public List searchCity(Integer pageNumber, Integer pageSize, String searchContent) { +/* // 分页参数 + Pageable pageable = new PageRequest(pageNumber, pageSize); + + // Function Score Query + FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() + .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("cityname", searchContent)), + ScoreFunctionBuilders.weightFactorFunction(1000)) + .add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("description", searchContent)), + ScoreFunctionBuilders.weightFactorFunction(100)); + + // 创建搜索 DSL 查询 + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withPageable(pageable) + .withQuery(functionScoreQueryBuilder).build(); + + logger.info("\n searchCity(): searchContent [" + searchContent + "] \n DSL = \n " + searchQuery.getQuery().toString()); + + Page searchPageResults = customerRepository.search(searchQuery); + return searchPageResults.getContent(); + */ + return null; + } +} diff --git a/2.x/spring-boot-elasticsearch/src/main/resources/application.properties b/2.x/spring-boot-elasticsearch/src/main/resources/application.properties new file mode 100644 index 000000000..6b48fb388 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.data.elasticsearch.cluster-name=es-mongodb +spring.data.elasticsearch.cluster-nodes=192.168.0.53:9300 \ No newline at end of file diff --git a/2.x/spring-boot-elasticsearch/src/test/java/com/neo/ElasticsearchApplicationTests.java b/2.x/spring-boot-elasticsearch/src/test/java/com/neo/ElasticsearchApplicationTests.java new file mode 100644 index 000000000..4a07e8e84 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/test/java/com/neo/ElasticsearchApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ElasticsearchApplicationTests { + + @Test + public void contextLoads() { + System.out.println("Spring Boot Test"); + } + +} diff --git a/2.x/spring-boot-elasticsearch/src/test/java/com/neo/repository/CustomerRepositoryTest.java b/2.x/spring-boot-elasticsearch/src/test/java/com/neo/repository/CustomerRepositoryTest.java new file mode 100644 index 000000000..a9e3c4286 --- /dev/null +++ b/2.x/spring-boot-elasticsearch/src/test/java/com/neo/repository/CustomerRepositoryTest.java @@ -0,0 +1,135 @@ +package com.neo.repository; + +import com.neo.model.Customer; +import org.elasticsearch.action.search.SearchResponse; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.aggregations.Aggregation; +import org.elasticsearch.search.aggregations.AggregationBuilders; +import org.elasticsearch.search.aggregations.Aggregations; +import org.elasticsearch.search.aggregations.metrics.sum.InternalSum; +import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.ResultsExtractor; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; +import java.util.Map; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class CustomerRepositoryTest { + @Autowired + private CustomerRepository repository; + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + + @Test + public void saveCustomers() { + repository.save(new Customer("Alice", "北京",13)); + repository.save(new Customer("Bob", "北京",23)); + repository.save(new Customer("neo", "西安",30)); + repository.save(new Customer("summer", "烟台",22)); + } + + @Test + public void fetchAllCustomers() { + System.out.println("Customers found with findAll():"); + System.out.println("-------------------------------"); + Iterable iterable=repository.findAll(); + for (Customer customer :iterable) { + System.out.println(customer); + } + } + + @Test + public void deleteCustomers() { + repository.deleteAll(); +// repository.deleteByUserName("neo"); + } + + @Test + public void updateCustomers() { + Customer customer= repository.findByUserName("summer"); + System.out.println(customer); + customer.setAddress("北京市海淀区西直门"); + repository.save(customer); + Customer xcustomer=repository.findByUserName("summer"); + System.out.println(xcustomer); + } + + @Test + public void fetchIndividualCustomers() { + System.out.println("Customer found with findByUserName('summer'):"); + System.out.println("--------------------------------"); + System.out.println(repository.findByUserName("summer")); + System.out.println("--------------------------------"); + System.out.println("Customers found with findByAddress(\"北京\"):"); + String q="北京"; + for (Customer customer : repository.findByAddress(q)) { + System.out.println(customer); + } + } + + @Test + public void fetchPageCustomers() { + System.out.println("Customers found with fetchPageCustomers:"); + System.out.println("-------------------------------"); + Sort sort = new Sort(Sort.Direction.DESC, "address.keyword"); + Pageable pageable = PageRequest.of(0, 10, sort); + Page customers=repository.findByAddress("北京", pageable); + System.out.println("Page customers "+customers.getContent().toString()); + } + + @Test + public void fetchPage2Customers() { + System.out.println("Customers found with fetchPageCustomers:"); + System.out.println("-------------------------------"); + QueryBuilder customerQuery = QueryBuilders.boolQuery() + .must(QueryBuilders.matchQuery("address", "北京")); + Page page = repository.search(customerQuery, PageRequest.of(0, 10)); + System.out.println("Page customers "+page.getContent().toString()); + page = repository.search(customerQuery, PageRequest.of(1, 10)); + System.out.println("Page customers "+page.getContent().toString()); + } + + @Test + public void fetchAggregation() { + System.out.println("Customers found with fetchAggregation:"); + System.out.println("-------------------------------"); + + QueryBuilder customerQuery = QueryBuilders.boolQuery() + .must(QueryBuilders.matchQuery("address", "北京")); + + SumAggregationBuilder sumBuilder = AggregationBuilders.sum("sumAge").field("age"); + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(customerQuery) + .addAggregation(sumBuilder) + .build(); + + Aggregations aggregations = elasticsearchTemplate.query(searchQuery, new ResultsExtractor() { + @Override + public Aggregations extract(SearchResponse response) { + return response.getAggregations(); + } + }); + + //转换成map集合 + Map aggregationMap = aggregations.asMap(); + //获得对应的聚合函数的聚合子类,该聚合子类也是个map集合,里面的value就是桶Bucket,我们要获得Bucket + InternalSum sumAge = (InternalSum) aggregationMap.get("sumAge"); + System.out.println("sum age is "+sumAge.getValue()); + } + +} diff --git a/2.x/spring-boot-fastDFS/pom.xml b/2.x/spring-boot-fastDFS/pom.xml new file mode 100644 index 000000000..73c12c74e --- /dev/null +++ b/2.x/spring-boot-fastDFS/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + com.neo + spring-boot-fastDFS + jar + 1.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + true + + + org.csource + fastdfs-client-java + 1.27-SNAPSHOT + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java b/2.x/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java new file mode 100644 index 000000000..197c98205 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/java/com/neo/FastDFSApplication.java @@ -0,0 +1,30 @@ +package com.neo; + +import org.apache.coyote.http11.AbstractHttp11Protocol; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class FastDFSApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(FastDFSApplication.class, args); + } + + //Tomcat large file upload connection reset + @Bean + public TomcatServletWebServerFactory tomcatEmbedded() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { + if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { + //-1 means unlimited + ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); + } + }); + return tomcat; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java new file mode 100644 index 000000000..fd6e17c23 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/GlobalExceptionHandler.java @@ -0,0 +1,20 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@ControllerAdvice +public class GlobalExceptionHandler { + + //https://jira.spring.io/browse/SPR-14651 + //4.3.5 supports RedirectAttributes redirectAttributes + @ExceptionHandler(MultipartException.class) + public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { + + redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); + return "redirect:/uploadStatus"; + + } +} diff --git a/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java b/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java new file mode 100644 index 000000000..4dd3bf286 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/java/com/neo/controller/UploadController.java @@ -0,0 +1,80 @@ +package com.neo.controller; + +import com.neo.fastdfs.FastDFSClient; +import com.neo.fastdfs.FastDFSFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.io.IOException; +import java.io.InputStream; + +@Controller +public class UploadController { + private static Logger logger = LoggerFactory.getLogger(UploadController.class); + + @GetMapping("/") + public String index() { + return "upload"; + } + + @PostMapping("/upload") //new annotation since 4.3 + public String singleFileUpload(@RequestParam("file") MultipartFile file, + RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); + return "redirect:uploadStatus"; + } + try { + // Get the file and save it somewhere + String path=saveFile(file); + redirectAttributes.addFlashAttribute("message", + "You successfully uploaded '" + file.getOriginalFilename() + "'"); + redirectAttributes.addFlashAttribute("path", + "file path url '" + path + "'"); + } catch (Exception e) { + logger.error("upload file failed",e); + } + return "redirect:/uploadStatus"; + } + + @GetMapping("/uploadStatus") + public String uploadStatus() { + return "uploadStatus"; + } + + /** + * @param multipartFile + * @return + * @throws IOException + */ + public String saveFile(MultipartFile multipartFile) throws IOException { + String[] fileAbsolutePath={}; + String fileName=multipartFile.getOriginalFilename(); + String ext = fileName.substring(fileName.lastIndexOf(".") + 1); + byte[] file_buff = null; + InputStream inputStream=multipartFile.getInputStream(); + if(inputStream!=null){ + int len1 = inputStream.available(); + file_buff = new byte[len1]; + inputStream.read(file_buff); + } + inputStream.close(); + FastDFSFile file = new FastDFSFile(fileName, file_buff, ext); + try { + fileAbsolutePath = FastDFSClient.upload(file); //upload to fastdfs + } catch (Exception e) { + logger.error("upload file Exception!",e); + } + if (fileAbsolutePath==null) { + logger.error("upload file failed,please upload again!"); + } + String path=FastDFSClient.getTrackerUrl()+fileAbsolutePath[0]+ "/"+fileAbsolutePath[1]; + return path; + } +} \ No newline at end of file diff --git a/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java b/2.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java similarity index 100% rename from spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java rename to 2.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSClient.java diff --git a/2.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java b/2.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java new file mode 100644 index 000000000..adee175bc --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/java/com/neo/fastdfs/FastDFSFile.java @@ -0,0 +1,70 @@ +package com.neo.fastdfs; + +public class FastDFSFile { + private String name; + + private byte[] content; + + private String ext; + + private String md5; + + private String author; + + public FastDFSFile(String name, byte[] content, String ext, String height, + String width, String author) { + super(); + this.name = name; + this.content = content; + this.ext = ext; + this.author = author; + } + + public FastDFSFile(String name, byte[] content, String ext) { + super(); + this.name = name; + this.content = content; + this.ext = ext; + + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + public String getExt() { + return ext; + } + + public void setExt(String ext) { + this.ext = ext; + } + + public String getMd5() { + return md5; + } + + public void setMd5(String md5) { + this.md5 = md5; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-fastDFS/src/main/resources/application.properties b/2.x/spring-boot-fastDFS/src/main/resources/application.properties new file mode 100644 index 000000000..cd48cf526 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/resources/application.properties @@ -0,0 +1,5 @@ +#http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties +#search multipart +spring.servlet.http.multipart.max-file-size=10MB +spring.servlet.http.multipart.max-request-size=10MB + diff --git a/2.x/spring-boot-fastDFS/src/main/resources/fdfs_client.conf b/2.x/spring-boot-fastDFS/src/main/resources/fdfs_client.conf new file mode 100644 index 000000000..95cb59cc7 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/resources/fdfs_client.conf @@ -0,0 +1,9 @@ +connect_timeout = 60 +network_timeout = 60 +charset = UTF-8 +http.tracker_http_port = 8080 +http.anti_steal_token = no +http.secret_key = 123456 + +tracker_server = 192.168.53.85:22122 +tracker_server = 192.168.53.86:22122 diff --git a/2.x/spring-boot-fastDFS/src/main/resources/logback.xml b/2.x/spring-boot-fastDFS/src/main/resources/logback.xml new file mode 100644 index 000000000..0c0f833bc --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/resources/logback.xml @@ -0,0 +1,24 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-fastDFS/src/main/resources/templates/upload.html b/2.x/spring-boot-fastDFS/src/main/resources/templates/upload.html new file mode 100644 index 000000000..2e93a58dd --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/resources/templates/upload.html @@ -0,0 +1,13 @@ + + + + +

Spring Boot file upload example

+ +
+

+ +
+ + + diff --git a/2.x/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html b/2.x/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html new file mode 100644 index 000000000..bcdab68f3 --- /dev/null +++ b/2.x/spring-boot-fastDFS/src/main/resources/templates/uploadStatus.html @@ -0,0 +1,16 @@ + + + + +

Spring Boot - Upload Status

+ +
+

+

+ +
+

+

+ + + \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/pom.xml b/2.x/spring-boot-file-upload/pom.xml new file mode 100644 index 000000000..af0bb9aae --- /dev/null +++ b/2.x/spring-boot-file-upload/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + com.neo + spring-boot-file-upload + jar + 1.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java b/2.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java new file mode 100644 index 000000000..059ae73fc --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java @@ -0,0 +1,30 @@ +package com.neo; + +import org.apache.coyote.http11.AbstractHttp11Protocol; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class FileUploadWebApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(FileUploadWebApplication.class, args); + } + + //Tomcat large file upload connection reset + @Bean + public TomcatServletWebServerFactory tomcatEmbedded() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); + tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { + if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { + //-1 means unlimited + ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); + } + }); + return tomcat; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java new file mode 100644 index 000000000..8f5caf6cc --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java @@ -0,0 +1,18 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.multipart.MultipartException; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@ControllerAdvice +public class GlobalExceptionHandler { + + //https://jira.spring.io/browse/SPR-14651 + //4.3.5 supports RedirectAttributes redirectAttributes + @ExceptionHandler(MultipartException.class) + public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { + redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); + return "redirect:/uploadStatus"; + } +} diff --git a/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java b/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java new file mode 100644 index 000000000..f72b2026a --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java @@ -0,0 +1,58 @@ +package com.neo.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Controller +public class UploadController { + //Save the uploaded file to this folder + private static String UPLOADED_FOLDER = "E://temp//"; + + @GetMapping("/") + public String index() { + return "upload"; + } + + @PostMapping("/upload") // //new annotation since 4.3 + public String singleFileUpload(@RequestParam("file") MultipartFile file, + RedirectAttributes redirectAttributes) { + if (file.isEmpty()) { + redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); + return "redirect:uploadStatus"; + } + + try { + // Get the file and save it somewhere + byte[] bytes = file.getBytes(); + Path dir = Paths.get(UPLOADED_FOLDER); + Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); + // Create parent dir if not exists + if(!Files.exists(dir)) { + Files.createDirectories(dir); + } + Files.write(path, bytes); + redirectAttributes.addFlashAttribute("message", + "You successfully uploaded '" + file.getOriginalFilename() + "'"); + + } catch (IOException e) { + redirectAttributes.addFlashAttribute("message", "Server throw IOException"); + e.printStackTrace(); + } + return "redirect:/uploadStatus"; + } + + @GetMapping("/uploadStatus") + public String uploadStatus() { + return "uploadStatus"; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/src/main/resources/application.properties b/2.x/spring-boot-file-upload/src/main/resources/application.properties new file mode 100644 index 000000000..61a7fd433 --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/resources/application.properties @@ -0,0 +1,4 @@ +#http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties +#search multipart +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/src/main/resources/logback.xml b/2.x/spring-boot-file-upload/src/main/resources/logback.xml new file mode 100644 index 000000000..0c0f833bc --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/resources/logback.xml @@ -0,0 +1,24 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/src/main/resources/templates/from_file.html b/2.x/spring-boot-file-upload/src/main/resources/templates/from_file.html new file mode 100644 index 000000000..3f95f35e1 --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/resources/templates/from_file.html @@ -0,0 +1,51 @@ +
+
+
+ Ӹ +
+
+ + 0%
+ +
+ +
+
+
+ + + \ No newline at end of file diff --git a/2.x/spring-boot-file-upload/src/main/resources/templates/upload.html b/2.x/spring-boot-file-upload/src/main/resources/templates/upload.html new file mode 100644 index 000000000..2e93a58dd --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/resources/templates/upload.html @@ -0,0 +1,13 @@ + + + + +

Spring Boot file upload example

+ +
+

+ +
+ + + diff --git a/2.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html b/2.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html new file mode 100644 index 000000000..71fb76d3c --- /dev/null +++ b/2.x/spring-boot-file-upload/src/main/resources/templates/uploadStatus.html @@ -0,0 +1,12 @@ + + + + +

Spring Boot - Upload Status

+ +
+

+

+ + + \ No newline at end of file diff --git a/2.x/spring-boot-hello/pom.xml b/2.x/spring-boot-hello/pom.xml new file mode 100644 index 000000000..eba435698 --- /dev/null +++ b/2.x/spring-boot-hello/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + com.neo + spring-boot-hello + 1.0 + jar + + spring-boot-hello + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-hello/src/main/java/com/neo/HelloApplication.java b/2.x/spring-boot-hello/src/main/java/com/neo/HelloApplication.java new file mode 100644 index 000000000..fc7cea256 --- /dev/null +++ b/2.x/spring-boot-hello/src/main/java/com/neo/HelloApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HelloApplication { + + public static void main(String[] args) { + SpringApplication.run(HelloApplication.class, args); + } +} diff --git a/2.x/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java b/2.x/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java new file mode 100644 index 000000000..2c1c06de1 --- /dev/null +++ b/2.x/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/") + public String index() { + return "Hello Spring Boot 2.0!"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-hello/src/main/resources/application.properties b/2.x/spring-boot-hello/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java b/2.x/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java new file mode 100644 index 000000000..09ba4ff06 --- /dev/null +++ b/2.x/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloApplicationTests { + + @Test + public void contextLoads() { + System.out.println("Hello Spring Boot 2.0!"); + } + +} diff --git a/2.x/spring-boot-helloWorld/pom.xml b/2.x/spring-boot-helloWorld/pom.xml new file mode 100644 index 000000000..460a54832 --- /dev/null +++ b/2.x/spring-boot-helloWorld/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.neo + spring-boot-helloworld + 1.0.0-SNAPSHOT + jar + + spring-boot-helloworld + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/2.x/spring-boot-helloWorld/src/main/java/com/neo/Application.java b/2.x/spring-boot-helloWorld/src/main/java/com/neo/Application.java new file mode 100644 index 000000000..6cda50c81 --- /dev/null +++ b/2.x/spring-boot-helloWorld/src/main/java/com/neo/Application.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/2.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java b/2.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java new file mode 100644 index 000000000..7d0256b4a --- /dev/null +++ b/2.x/spring-boot-helloWorld/src/main/java/com/neo/controller/HelloWorldController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-helloWorld/src/main/resources/application.properties b/2.x/spring-boot-helloWorld/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java b/2.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java new file mode 100644 index 000000000..1faf3f2e7 --- /dev/null +++ b/2.x/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello word"); + } + +} diff --git a/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java b/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..d42211135 --- /dev/null +++ b/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,39 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..7abaf5818 --- /dev/null +++ b/2.x/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,37 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/pom.xml b/2.x/spring-boot-jpa-thymeleaf-curd/pom.xml new file mode 100644 index 000000000..a642bcec9 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + spring-boot-jpa-thymeleaf-curd + spring-boot-jpa-thymeleaf-curd + spring-boot-jpa-thymeleaf-curd + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-devtools + true + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java new file mode 100644 index 000000000..20dc3f130 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java @@ -0,0 +1,20 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + + +@SpringBootApplication +public class JpaThymeleafApplication extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(JpaThymeleafApplication.class); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(JpaThymeleafApplication.class, args); + } +} + diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..4aa977176 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java @@ -0,0 +1,55 @@ +package com.neo.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class User { + @Id + @GeneratedValue + private long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String password; + @Column(nullable = false) + private int age; + + public long getId() { + return id; + } + + public User setId(long id) { + this.id = id; + return this; + } + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public String getPassword() { + return password; + } + + public User setPassword(String password) { + this.password = password; + return this; + } + + public int getAge() { + return age; + } + + public User setAge(int age) { + this.age = age; + return this; + } +} diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..f6a00c8c3 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findById(long id); + + void deleteById(Long id); +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java new file mode 100644 index 000000000..ba82b95f2 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java @@ -0,0 +1,20 @@ +package com.neo.service; + +import com.neo.model.User; + +import java.util.List; + +public interface UserService { + + public List getUserList(); + + public User findUserById(long id); + + public void save(User user); + + public void edit(User user); + + public void delete(long id); + + +} diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java new file mode 100644 index 000000000..a8a956174 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java @@ -0,0 +1,43 @@ +package com.neo.service.impl; + +import com.neo.model.User; +import com.neo.repository.UserRepository; +import com.neo.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class UserServiceImpl implements UserService{ + + @Autowired + private UserRepository userRepository; + + @Override + public List getUserList() { + return userRepository.findAll(); + } + + @Override + public User findUserById(long id) { + return userRepository.findById(id); + } + + @Override + public void save(User user) { + userRepository.save(user); + } + + @Override + public void edit(User user) { + userRepository.save(user); + } + + @Override + public void delete(long id) { + userRepository.deleteById(id); + } +} + + diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..82136eb19 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,16 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +public class HelloController { + + @RequestMapping("/hello") + public String hello(Model model, @RequestParam(value="name", required=false, defaultValue="World") String name) { + model.addAttribute("name", name); + return "hello"; + } +} diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..b6992aac4 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,61 @@ +package com.neo.web; + +import com.neo.model.User; +import com.neo.service.UserService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.annotation.Resource; +import java.util.List; + +@Controller +public class UserController { + + @Resource + UserService userService; + + + @RequestMapping("/") + public String index() { + return "redirect:/list"; + } + + @RequestMapping("/list") + public String list(Model model) { + List users=userService.getUserList(); + model.addAttribute("users", users); + return "user/list"; + } + + @RequestMapping("/toAdd") + public String toAdd() { + return "user/userAdd"; + } + + @RequestMapping("/add") + public String add(User user) { + userService.save(user); + return "redirect:/list"; + } + + @RequestMapping("/toEdit") + public String toEdit(Model model,Long id) { + User user=userService.findUserById(id); + model.addAttribute("user", user); + return "user/userEdit"; + } + + @RequestMapping("/edit") + public String edit(User user) { + userService.edit(user); + return "redirect:/list"; + } + + + @RequestMapping("/delete") + public String delete(Long id) { + userService.delete(id); + return "redirect:/list"; + } +} diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties new file mode 100644 index 000000000..59008fe5d --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties @@ -0,0 +1,10 @@ +spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.show-sql= true + +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css new file mode 100644 index 000000000..42c79d6e4 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/static/css/bootstrap.css @@ -0,0 +1,6760 @@ +/*! + * Bootstrap v3.3.6 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + padding-right: 15px; + padding-left: 15px; + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + filter: alpha(opacity=0); + opacity: 0; + + line-break: auto; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + + line-break: auto; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/hello.html b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/hello.html new file mode 100644 index 000000000..bd1f7817e --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + + Hello Thymeleaf! + + +

+ + \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html new file mode 100644 index 000000000..4126a3de1 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/list.html @@ -0,0 +1,43 @@ + + + + + userList + + + +
+

用户列表

+

+
+ + + + + + + + + + + + + + + + + + + + + +
#User NamePasswordAgeEditDelete
1neoOtto6editdelete
+
+
+
+ add +
+
+ + + \ No newline at end of file diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html new file mode 100644 index 000000000..0fa93c38a --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userAdd.html @@ -0,0 +1,43 @@ + + + + + user + + + +
+

添加用户

+

+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +       + +
+ +
+
+
+ + diff --git a/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html new file mode 100644 index 000000000..b312daa37 --- /dev/null +++ b/2.x/spring-boot-jpa-thymeleaf-curd/src/main/resources/templates/user/userEdit.html @@ -0,0 +1,44 @@ + + + + + user + + + +
+

修改用户

+

+
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +       + Back +
+ +
+
+
+ + diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/pom.xml b/2.x/spring-boot-jpa/spring-boot-jpa/pom.xml new file mode 100644 index 000000000..b42ead5ee --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.neo + spring-boot-Jpa + 1.0.0 + jar + + spring-boot-Jpa + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java new file mode 100644 index 000000000..a1b5532be --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java @@ -0,0 +1,13 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; + +@SpringBootApplication +public class JpaApplication { + + public static void main(String[] args) { + SpringApplication.run(JpaApplication.class, args); + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java new file mode 100644 index 000000000..883ea20c6 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java @@ -0,0 +1,59 @@ +package com.neo.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Address { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false) + private Long userId; + private String province; + private String city; + private String street; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..7ec1e8bad --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java @@ -0,0 +1,87 @@ +package com.neo.model; + + + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +import java.io.Serializable; + +@Entity +public class User { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true) + private String email; + @Column(nullable = true, unique = true) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + } + + public User(String userName, String passWord, String email, String nickName, String regTime) { + this.userName = userName; + this.passWord = passWord; + this.email = email; + this.nickName = nickName; + this.regTime = regTime; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java new file mode 100644 index 000000000..4f3c67da8 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java @@ -0,0 +1,102 @@ +package com.neo.model; + + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import javax.persistence.*; +import java.io.Serializable; + +@Entity +public class UserDetail { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true) + private Long userId; + private Integer age; + private String realName; + private String status; + private String hobby; + private String introduction; + private String lastLoginIp; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getHobby() { + return hobby; + } + + public void setHobby(String hobby) { + this.hobby = hobby; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public String getLastLoginIp() { + return lastLoginIp; + } + + public void setLastLoginIp(String lastLoginIp) { + this.lastLoginIp = lastLoginIp; + } + + @Override + public String toString() { + return "UserDetail{" + + "id=" + id + + ", userId=" + userId + + ", age=" + age + + ", realName='" + realName + '\'' + + ", status='" + status + '\'' + + ", hobby='" + hobby + '\'' + + ", introduction='" + introduction + '\'' + + ", lastLoginIp='" + lastLoginIp + '\'' + + '}'; + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java new file mode 100644 index 000000000..5a5ae5eb3 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java @@ -0,0 +1,8 @@ +package com.neo.model; + +public interface UserInfo { + String getUserName(); + String getEmail(); + String getHobby(); + String getIntroduction(); +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java new file mode 100644 index 000000000..0f7a49714 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java @@ -0,0 +1,65 @@ +package com.neo.param; + + +import com.neo.model.Address; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import javax.persistence.*; + +public class UserDetailParam { + private String userId; + private Integer minAge; + private Integer maxAge; + private String realName; + private String introduction; + private String city; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Integer getMinAge() { + return minAge; + } + + public void setMinAge(Integer minAge) { + this.minAge = minAge; + } + + public Integer getMaxAge() { + return maxAge; + } + + public void setMaxAge(Integer maxAge) { + this.maxAge = maxAge; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java new file mode 100644 index 000000000..3bba02753 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java @@ -0,0 +1,7 @@ +package com.neo.repository; + +import com.neo.model.Address; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AddressRepository extends JpaRepository { +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java new file mode 100644 index 000000000..e133b0564 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java @@ -0,0 +1,20 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.model.UserDetail; +import com.neo.model.UserInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + + +public interface UserDetailRepository extends JpaSpecificationExecutor,JpaRepository { + + UserDetail findByHobby(String hobby); + + @Query("select u.userName as userName, u.email as email, d.introduction as introduction , d.hobby as hobby from User u , UserDetail d " + + "where u.id=d.userId and d.hobby = ?1 ") + List findUserInfo(String hobby); +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..8318068a5 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,40 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + + +public interface UserRepository extends JpaRepository { + + User findByUserName(String userName); + + User findByUserNameOrEmail(String username, String email); + + @Transactional(timeout = 10) + @Modifying + @Query("update User set userName = ?1 where id = ?2") + int modifyById(String userName, Long id); + + @Transactional + @Modifying + @Query("delete from User where id = ?1") + void deleteById(Long id); + + @Query("select u from User u where u.email = ?1") + User findByEmail(String email); + + @Query("select u from User u") + Page findALL(Pageable pageable); + + Page findByNickName(String nickName, Pageable pageable); + + Slice findByNickNameAndEmail(String nickName, String email,Pageable pageable); + + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java new file mode 100644 index 000000000..a5d14ead7 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java @@ -0,0 +1,10 @@ +package com.neo.service; + +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface UserDetailService { + public Page findByCondition(UserDetailParam detailParam, Pageable pageable); +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java new file mode 100644 index 000000000..18eaba979 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java @@ -0,0 +1,48 @@ +package com.neo.service; + +import com.mysql.cj.util.StringUtils; +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import com.neo.repository.UserDetailRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.persistence.criteria.Predicate; +import java.util.ArrayList; +import java.util.List; + +@Service +public class UserDetailServiceImpl implements UserDetailService{ + + @Resource + private UserDetailRepository userDetailRepository; + + @Override + public Page findByCondition(UserDetailParam detailParam, Pageable pageable){ + + return userDetailRepository.findAll((root, query, cb) -> { + List predicates = new ArrayList(); + //equal 示例 + if (!StringUtils.isNullOrEmpty(detailParam.getIntroduction())){ + predicates.add(cb.equal(root.get("introduction"),detailParam.getIntroduction())); + } + //like 示例 + if (!StringUtils.isNullOrEmpty(detailParam.getRealName())){ + predicates.add(cb.like(root.get("realName"),"%"+detailParam.getRealName()+"%")); + } + //between 示例 + if (detailParam.getMinAge()!=null && detailParam.getMaxAge()!=null) { + Predicate agePredicate = cb.between(root.get("age"), detailParam.getMinAge(), detailParam.getMaxAge()); + predicates.add(agePredicate); + } + //greaterThan 大于等于示例 + if (detailParam.getMinAge()!=null){ + predicates.add(cb.greaterThan(root.get("age"),detailParam.getMinAge())); + } + return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); + }, pageable); + + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties new file mode 100644 index 000000000..b0b5ebe9a --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties @@ -0,0 +1,11 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +#sql\u8F93\u51FA +spring.jpa.show-sql=true +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java new file mode 100644 index 000000000..4fe4fdbe0 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class JpaApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java new file mode 100644 index 000000000..751b7d351 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java @@ -0,0 +1,40 @@ +package com.neo.repository; + +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import com.neo.service.UserDetailService; +import com.neo.service.UserDetailServiceImpl; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class JpaSpecificationTests { + + @Resource + private UserDetailService userDetailService; + + @Test + public void testFindByCondition() { + int page=0,size=10; + Sort sort = new Sort(Sort.Direction.DESC, "id"); + Pageable pageable = PageRequest.of(page, size, sort); + UserDetailParam param=new UserDetailParam(); + param.setIntroduction("程序员"); + param.setMinAge(10); + param.setMaxAge(30); + Page page1=userDetailService.findByCondition(param,pageable); + for (UserDetail userDetail:page1){ + System.out.println("userDetail: "+userDetail.toString()); + } + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java new file mode 100644 index 000000000..679efb18a --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java @@ -0,0 +1,59 @@ +package com.neo.repository; + +import com.neo.model.Address; +import com.neo.model.User; +import com.neo.model.UserDetail; +import com.neo.model.UserInfo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserDetailRepositoryTests { + + @Resource + private AddressRepository addressRepository; + @Resource + private UserDetailRepository userDetailRepository; + + @Test + public void testSaveAddress() { + Address address=new Address(); + address.setUserId(1L); + address.setCity("北京"); + address.setProvince("北京"); + address.setStreet("分钟寺"); + addressRepository.save(address); + } + + @Test + public void testSaveUserDetail() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + UserDetail userDetail=new UserDetail(); + userDetail.setUserId(3L); + userDetail.setHobby("吃鸡游戏"); + userDetail.setAge(28); + userDetail.setIntroduction("一个爱玩的人"); + userDetailRepository.save(userDetail); + } + + @Test + public void testUserInfo() { + List userInfos=userDetailRepository.findUserInfo("钓鱼"); + for (UserInfo userInfo:userInfos){ + System.out.println("userInfo: "+userInfo.getUserName()+"-"+userInfo.getEmail()+"-"+userInfo.getHobby()+"-"+userInfo.getIntroduction()); + } + } +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java new file mode 100644 index 000000000..c689ce573 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java @@ -0,0 +1,71 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + + @Resource + private UserRepository userRepository; + + @Test + public void testSave() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userRepository.save(new User("aa", "aa123456","aa@126.com", "aa", formattedDate)); + userRepository.save(new User("bb", "bb123456","bb@126.com", "bb", formattedDate)); + userRepository.save(new User("cc", "cc123456","cc@126.com", "cc", formattedDate)); + +// Assert.assertEquals(3, userRepository.findAll().size()); +// Assert.assertEquals("bb", userRepository.findByUserNameOrEmail("bb", "bb@126.com").getNickName()); +// userRepository.delete(userRepository.findByUserName("aa")); + } + + + @Test + public void testBaseQuery() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + User user=new User("ff", "ff123456","ff@126.com", "ff", formattedDate); + userRepository.findAll(); + userRepository.findById(3L); + userRepository.save(user); + user.setId(2L); + userRepository.delete(user); + userRepository.count(); + userRepository.existsById(3L); + } + + @Test + public void testCustomSql() { + userRepository.modifyById("neo",3L); + userRepository.deleteById(3L); + userRepository.findByEmail("ff@126.com"); + } + + + @Test + public void testPageQuery() { + int page=1,size=2; + Sort sort = new Sort(Sort.Direction.DESC, "id"); + Pageable pageable = PageRequest.of(page, size, sort); + userRepository.findALL(pageable); + userRepository.findByNickName("aa", pageable); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml new file mode 100644 index 000000000..78e5e2e04 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.neo + spring-boot-multi-Jpa + 1.0 + jar + + spring-boot-multi-Jpa + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java new file mode 100644 index 000000000..2a9a26b17 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultiJpaApplication { + + public static void main(String[] args) { + SpringApplication.run(MultiJpaApplication.class, args); + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java new file mode 100644 index 000000000..09f2b757d --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java @@ -0,0 +1,41 @@ +package com.neo.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import javax.sql.DataSource; +import java.util.Map; + +@Configuration +public class DataSourceConfig { + + @Autowired + private JpaProperties jpaProperties; + @Autowired + private HibernateProperties hibernateProperties; + + @Bean(name = "primaryDataSource") + @Primary + @ConfigurationProperties("spring.datasource.primary") + public DataSource firstDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "secondaryDataSource") + @ConfigurationProperties("spring.datasource.secondary") + public DataSource secondDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "vendorProperties") + public Map getVendorProperties() { + return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java new file mode 100644 index 000000000..588cf91b7 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java @@ -0,0 +1,59 @@ +package com.neo.config; + +import java.util.Map; + +import javax.persistence.EntityManager; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef="entityManagerFactoryPrimary", + transactionManagerRef="transactionManagerPrimary", + basePackages= { "com.neo.repository.test1" })//设置dao(repo)所在位置 +public class PrimaryConfig { + + @Autowired + @Qualifier("primaryDataSource") + private DataSource primaryDataSource; + + @Autowired + @Qualifier("vendorProperties") + private Map vendorProperties; + + @Bean(name = "entityManagerFactoryPrimary") + @Primary + public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) { + return builder + .dataSource(primaryDataSource) + .properties(vendorProperties) + .packages("com.neo.model") //设置实体类所在位置 + .persistenceUnit("primaryPersistenceUnit") + .build(); + } + + @Bean(name = "entityManagerPrimary") + @Primary + public EntityManager entityManager(EntityManagerFactoryBuilder builder) { + return entityManagerFactoryPrimary(builder).getObject().createEntityManager(); + } + + @Bean(name = "transactionManagerPrimary") + @Primary + PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) { + return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject()); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java new file mode 100644 index 000000000..241f4764b --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java @@ -0,0 +1,54 @@ +package com.neo.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +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.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.persistence.EntityManager; +import javax.sql.DataSource; +import java.util.Map; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef="entityManagerFactorySecondary", + transactionManagerRef="transactionManagerSecondary", + basePackages= { "com.neo.repository.test2" }) +public class SecondaryConfig { + + @Autowired + @Qualifier("secondaryDataSource") + private DataSource secondaryDataSource; + + @Autowired + @Qualifier("vendorProperties") + private Map vendorProperties; + + @Bean(name = "entityManagerFactorySecondary") + public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) { + return builder + .dataSource(secondaryDataSource) + .properties(vendorProperties) + .packages("com.neo.model") + .persistenceUnit("secondaryPersistenceUnit") + .build(); + } + + @Bean(name = "entityManagerSecondary") + public EntityManager entityManager(EntityManagerFactoryBuilder builder) { + return entityManagerFactorySecondary(builder).getObject().createEntityManager(); + } + + @Bean(name = "transactionManagerSecondary") + PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) { + return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject()); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..f4cb974df --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java @@ -0,0 +1,86 @@ +package com.neo.model; + + + +import javax.persistence.*; + +import java.io.Serializable; + +@Entity +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true) + private String email; + @Column(nullable = true, unique = true) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + } + + public User(String userName, String passWord, String email, String nickName, String regTime) { + this.userName = userName; + this.passWord = passWord; + this.email = email; + this.nickName = nickName; + this.regTime = regTime; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } +} diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java new file mode 100644 index 000000000..feecceab6 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java @@ -0,0 +1,10 @@ +package com.neo.repository.test1; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserTest1Repository extends JpaRepository { + User findById(long id); + User findByUserName(String userName); + User findByUserNameOrEmail(String username, String email); +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java new file mode 100644 index 000000000..45f8c24fd --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java @@ -0,0 +1,11 @@ +package com.neo.repository.test2; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface UserTest2Repository extends JpaRepository { + User findById(long id); + User findByUserName(String userName); + User findByUserNameOrEmail(String username, String email); +} \ No newline at end of file diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties new file mode 100644 index 000000000..cab7dd706 --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties @@ -0,0 +1,16 @@ +spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.primary.username=root +spring.datasource.primary.password=root +spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.secondary.username=root +spring.datasource.secondary.password=root +spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver + +#sql\u8F93\u51FA +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java new file mode 100644 index 000000000..c87999ccd --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MultiJpaApplicationTests { + + @Test + public void contextLoads() { + System.out.println("Hello MultiJpa!"); + } + +} diff --git a/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java new file mode 100644 index 000000000..693986f5d --- /dev/null +++ b/2.x/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java @@ -0,0 +1,58 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.repository.test1.UserTest1Repository; +import com.neo.repository.test2.UserTest2Repository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + @Resource + private UserTest1Repository userTest1Repository; + @Resource + private UserTest2Repository userTest2Repository; + + @Test + public void testSave() throws Exception { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userTest1Repository.save(new User("aa", "aa123456","aa@126.com", "aa", formattedDate)); + userTest1Repository.save(new User("bb", "bb123456","bb@126.com", "bb", formattedDate)); + userTest2Repository.save(new User("cc", "cc123456","cc@126.com", "cc", formattedDate)); + } + + + @Test + public void testDelete() throws Exception { + userTest1Repository.deleteAll(); + userTest2Repository.deleteAll(); + } + + @Test + public void testBaseQuery() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + User user=new User("ff", "ff123456","ff@126.com", "ff", formattedDate); + userTest1Repository.findAll(); + userTest2Repository.findById(3l); + userTest2Repository.save(user); + user.setId(2l); + userTest1Repository.delete(user); + userTest1Repository.count(); + userTest2Repository.findById(3l); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-mail/pom.xml b/2.x/spring-boot-mail/pom.xml new file mode 100644 index 000000000..142d89224 --- /dev/null +++ b/2.x/spring-boot-mail/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.neo + spring-boot-mail + 1.0.0 + jar + + spring-boot-mail + Demo project for Spring Boot and mail + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-mail + + + org.springframework + spring-context-support + RELEASE + + + com.sun.mail + javax.mail + RELEASE + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/2.x/spring-boot-mail/src/main/java/com/neo/MailApplication.java b/2.x/spring-boot-mail/src/main/java/com/neo/MailApplication.java new file mode 100644 index 000000000..c0aee4155 --- /dev/null +++ b/2.x/spring-boot-mail/src/main/java/com/neo/MailApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MailApplication { + + public static void main(String[] args) { + SpringApplication.run(MailApplication.class, args); + } +} diff --git a/2.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java b/2.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java new file mode 100644 index 000000000..41df35605 --- /dev/null +++ b/2.x/spring-boot-mail/src/main/java/com/neo/service/MailService.java @@ -0,0 +1,16 @@ +package com.neo.service; + +/** + * Created by summer on 2017/5/4. + */ +public interface MailService { + + void sendSimpleMail(String to, String subject, String content); + + void sendHtmlMail(String to, String subject, String content); + + void sendAttachmentsMail(String to, String subject, String content, String filePath); + + void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId); + +} diff --git a/2.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java b/2.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java new file mode 100644 index 000000000..ee161e54a --- /dev/null +++ b/2.x/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java @@ -0,0 +1,140 @@ +package com.neo.service.impl; + +import com.neo.service.MailService; +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.core.io.FileSystemResource; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import java.io.File; + +/** + * Created by summer on 2017/5/4. + */ +@Component +public class MailServiceImpl implements MailService{ + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private JavaMailSender mailSender; + + @Value("${mail.fromMail.addr}") + private String from; + + /** + * 发送文本邮件 + * @param to + * @param subject + * @param content + */ + @Override + public void sendSimpleMail(String to, String subject, String content) { + SimpleMailMessage message = new SimpleMailMessage(); + message.setFrom(from); + message.setTo(to); + message.setSubject(subject); + message.setText(content); + + try { + mailSender.send(message); + logger.info("简单邮件已经发送。"); + } catch (Exception e) { + logger.error("发送简单邮件时发生异常!", e); + } + + } + + /** + * 发送html邮件 + * @param to + * @param subject + * @param content + */ + @Override + public void sendHtmlMail(String to, String subject, String content) { + MimeMessage message = mailSender.createMimeMessage(); + + try { + //true表示需要创建一个multipart message + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + mailSender.send(message); + logger.info("html邮件发送成功"); + } catch (MessagingException e) { + logger.error("发送html邮件时发生异常!", e); + } + } + + + /** + * 发送带附件的邮件 + * @param to + * @param subject + * @param content + * @param filePath + */ + @Override + public void sendAttachmentsMail(String to, String subject, String content, String filePath){ + MimeMessage message = mailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + FileSystemResource file = new FileSystemResource(new File(filePath)); + String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); + helper.addAttachment(fileName, file); + //helper.addAttachment("test"+fileName, file); + + mailSender.send(message); + logger.info("带附件的邮件已经发送。"); + } catch (MessagingException e) { + logger.error("发送带附件的邮件时发生异常!", e); + } + } + + + /** + * 发送正文中有静态资源(图片)的邮件 + * @param to + * @param subject + * @param content + * @param rscPath + * @param rscId + */ + @Override + public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){ + MimeMessage message = mailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(message, true); + helper.setFrom(from); + helper.setTo(to); + helper.setSubject(subject); + helper.setText(content, true); + + FileSystemResource res = new FileSystemResource(new File(rscPath)); + helper.addInline(rscId, res); + + mailSender.send(message); + logger.info("嵌入静态资源的邮件已经发送。"); + } catch (MessagingException e) { + logger.error("发送嵌入静态资源的邮件时发生异常!", e); + } + } +} diff --git a/2.x/spring-boot-mail/src/main/resources/application.properties b/2.x/spring-boot-mail/src/main/resources/application.properties new file mode 100644 index 000000000..dcbb52168 --- /dev/null +++ b/2.x/spring-boot-mail/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.application.name=spirng-boot-mail + +spring.mail.host=smtp.163.com +spring.mail.username=xxoo@xxoo.com +spring.mail.password=xxoo +spring.mail.default-encoding=UTF-8 + +mail.fromMail.addr=xxoo@xxoo.com + diff --git a/2.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html b/2.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html new file mode 100644 index 000000000..387a4fbcd --- /dev/null +++ b/2.x/spring-boot-mail/src/main/resources/templates/emailTemplate.html @@ -0,0 +1,11 @@ + + + + + Title + + + 您好,这是验证邮件,请点击下面的链接完成验证,
+ 激活账号 + + \ No newline at end of file diff --git a/2.x/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java b/2.x/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java new file mode 100644 index 000000000..7a9e7a09b --- /dev/null +++ b/2.x/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MailApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java b/2.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java new file mode 100644 index 000000000..91c4bbfd2 --- /dev/null +++ b/2.x/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java @@ -0,0 +1,65 @@ +package com.neo.service; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + +/** + * Created by summer on 2017/5/4. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class MailServiceTest { + + @Autowired + private MailService mailService; + + @Autowired + private TemplateEngine templateEngine; + + @Test + public void testSimpleMail() throws Exception { + mailService.sendSimpleMail("ityouknow@126.com","test simple mail"," hello this is simple mail"); + } + + @Test + public void testHtmlMail() throws Exception { + String content="\n" + + "\n" + + "

hello world ! 这是一封html邮件!

\n" + + "\n" + + ""; + mailService.sendHtmlMail("ityouknow@126.com","test simple mail",content); + } + + @Test + public void sendAttachmentsMail() { + String filePath="e:\\tmp\\application.log"; + mailService.sendAttachmentsMail("ityouknow@126.com", "主题:带附件的邮件", "有附件,请查收!", filePath); + } + + + @Test + public void sendInlineResourceMail() { + String rscId = "neo006"; + String content="这是有图片的邮件:"; + String imgPath = "C:\\Users\\summer\\Pictures\\favicon.png"; + + mailService.sendInlineResourceMail("ityouknow@126.com", "主题:这是有图片的邮件", content, imgPath, rscId); + } + + + @Test + public void sendTemplateMail() { + //创建邮件正文 + Context context = new Context(); + context.setVariable("id", "006"); + String emailContent = templateEngine.process("emailTemplate", context); + + mailService.sendHtmlMail("ityouknow@126.com","主题:这是模板邮件",emailContent); + } +} diff --git a/2.x/spring-boot-memcache-spymemcached/pom.xml b/2.x/spring-boot-memcache-spymemcached/pom.xml new file mode 100644 index 000000000..307afdb75 --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + com.neo + spring-boot-memcache-spymemcached + 1.0.0 + jar + + spring-boot-memcache-spymemcached + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.0.4.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + net.spy + spymemcached + 2.12.2 + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/MemcacheApplication.java b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/MemcacheApplication.java new file mode 100644 index 000000000..434519a5b --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/MemcacheApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MemcacheApplication { + + public static void main(String[] args) { + SpringApplication.run(MemcacheApplication.class, args); + } +} diff --git a/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcacheSource.java b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcacheSource.java new file mode 100644 index 000000000..e3e421ac8 --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcacheSource.java @@ -0,0 +1,29 @@ +package com.neo.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "memcache") +public class MemcacheSource { + + private String ip; + + private int port; + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java new file mode 100644 index 000000000..e1175b654 --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java @@ -0,0 +1,35 @@ +package com.neo.config; + +import net.spy.memcached.MemcachedClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.io.IOException; +import java.net.InetSocketAddress; + +@Component +public class MemcachedRunner implements CommandLineRunner { + protected Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + private MemcacheSource memcacheSource; + + private MemcachedClient client = null; + + @Override + public void run(String... args) throws Exception { + try { + client = new MemcachedClient(new InetSocketAddress(memcacheSource.getIp(),memcacheSource.getPort())); + } catch (IOException e) { + logger.error("inint MemcachedClient failed ",e); + } + } + + public MemcachedClient getClient() { + return client; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-memcache-spymemcached/src/main/resources/application.properties b/2.x/spring-boot-memcache-spymemcached/src/main/resources/application.properties new file mode 100644 index 000000000..4d0269621 --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/main/resources/application.properties @@ -0,0 +1,2 @@ +memcache.ip=192.168.0.161 +memcache.port=11211 \ No newline at end of file diff --git a/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/MemcacheApplicationTests.java b/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/MemcacheApplicationTests.java new file mode 100644 index 000000000..d2a66dc4d --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/MemcacheApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MemcacheApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java b/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java new file mode 100644 index 000000000..ceaef2205 --- /dev/null +++ b/2.x/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java @@ -0,0 +1,26 @@ +package com.neo; + +import com.neo.config.MemcachedRunner; +import net.spy.memcached.MemcachedClient; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RepositoryTests { + + @Resource + private MemcachedRunner memcachedRunner; + + @Test + public void testSetGet() { + MemcachedClient memcachedClient = memcachedRunner.getClient(); + memcachedClient.set("testkey",1000,"666666"); + System.out.println("*********** "+memcachedClient.get("testkey").toString()); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/pom.xml b/2.x/spring-boot-mongodb/spring-boot-mongodb/pom.xml new file mode 100644 index 000000000..e1ef7d580 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + com.neo + spring-boot-mongodb + 1.0.0 + jar + + spring-boot-mongodb + Demo project for Spring Boot and mongodb + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java new file mode 100644 index 000000000..b8c63d563 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MongoDBApplication { + + public static void main(String[] args) { + SpringApplication.run(MongoDBApplication.class, args); + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..c15340ae7 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java @@ -0,0 +1,46 @@ +package com.neo.model; + +import java.io.Serializable; + +/** + * Created by summer on 2017/5/5. + */ +public class User implements Serializable { + private static final long serialVersionUID = -3258839839160856613L; + private Long id; + private String userName; + private String passWord; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + @Override + public String toString() { + return "UserEntity{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", passWord='" + passWord + '\'' + + '}'; + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..e1a3d4134 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,18 @@ +package com.neo.repository; + +import com.neo.model.User; + +/** + * Created by summer on 2017/5/5. + */ +public interface UserRepository { + + public void saveUser(User user); + + public User findUserByUserName(String userName); + + public long updateUser(User user); + + public void deleteUserById(Long id); + +} diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java new file mode 100644 index 000000000..8c96f5a42 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java @@ -0,0 +1,70 @@ +package com.neo.repository.impl; + +import com.mongodb.client.result.UpdateResult; +import com.neo.repository.UserRepository; +import com.neo.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +/** + * Created by summer on 2017/5/5. + */ +@Component +public class UserRepositoryImpl implements UserRepository { + + @Autowired + private MongoTemplate mongoTemplate; + + /** + * 创建对象 + * @param user + */ + @Override + public void saveUser(User user) { + mongoTemplate.save(user); + } + + /** + * 根据用户名查询对象 + * @param userName + * @return + */ + @Override + public User findUserByUserName(String userName) { + Query query=new Query(Criteria.where("userName").is(userName)); + User user = mongoTemplate.findOne(query , User.class); + return user; + } + + /** + * 更新对象 + * @param user + */ + @Override + public long updateUser(User user) { + Query query=new Query(Criteria.where("id").is(user.getId())); + Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord()); + //更新查询返回结果集的第一条 + UpdateResult result =mongoTemplate.updateFirst(query,update,User.class); + //更新查询返回结果集的所有 + // mongoTemplate.updateMulti(query,update,UserEntity.class); + if(result!=null) + return result.getMatchedCount(); + else + return 0; + } + + /** + * 删除对象 + * @param id + */ + @Override + public void deleteUserById(Long id) { + Query query=new Query(Criteria.where("id").is(id)); + mongoTemplate.remove(query,User.class); + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties new file mode 100644 index 000000000..32e5ca921 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.application.name=spring-boot-mongodb + +spring.data.mongodb.uri=mongodb://192.168.0.75:20000/test + + diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java new file mode 100644 index 000000000..cd30276df --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MongoDBApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java new file mode 100644 index 000000000..cb6372f02 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java @@ -0,0 +1,49 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Created by summer on 2017/5/5. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTest { + + @Autowired + private UserRepository userDao; + + @Test + public void testSaveUser() throws Exception { + User user=new User(); + user.setId(2l); + user.setUserName("小明"); + user.setPassWord("fffooo123"); + userDao.saveUser(user); + } + + @Test + public void findUserByUserName(){ + User user= userDao.findUserByUserName("小明"); + System.out.println("user is "+user); + } + + @Test + public void updateUser(){ + User user=new User(); + user.setId(2l); + user.setUserName("天空"); + user.setPassWord("fffxxxx"); + userDao.updateUser(user); + } + + @Test + public void deleteUserById(){ + userDao.deleteUserById(1l); + } + +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml new file mode 100644 index 000000000..e38f5ba0c --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.neo + spring-boot-multi-mongodb + 1.0.0 + jar + + spring-boot-multi-mongodb + Demo project for Spring Boot and multi mongodb + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java new file mode 100644 index 000000000..e33c97dae --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultiMongodbApplication { + + public static void main(String[] args) { + SpringApplication.run(MultiMongodbApplication.class, args); + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java new file mode 100644 index 000000000..5d4a2f5bb --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java @@ -0,0 +1,46 @@ +package com.neo.config; + +import com.mongodb.MongoClient; +import com.mongodb.MongoClientURI; +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoDbFactory; + +@Configuration +public class MultipleMongoConfig { + + @Autowired + private MultipleMongoProperties mongoProperties; + + @Primary + @Bean(name = "primaryMongoTemplate") + public MongoTemplate primaryMongoTemplate() throws Exception { + return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary())); + } + + @Bean + @Qualifier("secondaryMongoTemplate") + public MongoTemplate secondaryMongoTemplate() throws Exception { + return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary())); + } + + @Bean + @Primary + public MongoDbFactory primaryFactory(MongoProperties mongo) throws Exception { + MongoClient client = new MongoClient(new MongoClientURI(mongoProperties.getPrimary().getUri())); + return new SimpleMongoDbFactory(client, mongoProperties.getPrimary().getDatabase()); + } + + @Bean + public MongoDbFactory secondaryFactory(MongoProperties mongo) throws Exception { + MongoClient client = new MongoClient(new MongoClientURI(mongoProperties.getSecondary().getUri())); + return new SimpleMongoDbFactory(client, mongoProperties.getSecondary().getDatabase()); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java new file mode 100644 index 000000000..7920d185d --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java @@ -0,0 +1,23 @@ +package com.neo.config; + +import com.mongodb.MongoClient; +import com.mongodb.MongoClientURI; +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + + +@Configuration +@EnableConfigurationProperties(MultipleMongoProperties.class) +@EnableMongoRepositories(basePackages = "com.neo.repository.primary", + mongoTemplateRef = "primaryMongoTemplate") +public class PrimaryMongoConfig { +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java new file mode 100644 index 000000000..c50e2282f --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java @@ -0,0 +1,24 @@ +package com.neo.config; + +import com.mongodb.MongoClient; +import com.mongodb.MongoClientURI; +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.MongoDbFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoDbFactory; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + + +@Configuration +@EnableConfigurationProperties(MultipleMongoProperties.class) +@EnableMongoRepositories(basePackages = "com.neo.repository.secondary", + mongoTemplateRef = "secondaryMongoTemplate") +public class SecondaryMongoConfig { + +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java new file mode 100644 index 000000000..5bf4ff66a --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java @@ -0,0 +1,27 @@ +package com.neo.config.props; + +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "mongodb") +public class MultipleMongoProperties { + + private MongoProperties primary = new MongoProperties(); + private MongoProperties secondary = new MongoProperties(); + + public MongoProperties getPrimary() { + return primary; + } + + public void setPrimary(MongoProperties primary) { + this.primary = primary; + } + + public MongoProperties getSecondary() { + return secondary; + } + + public void setSecondary(MongoProperties secondary) { + this.secondary = secondary; + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..b5cd0a861 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java @@ -0,0 +1,49 @@ +package com.neo.model; + +import java.io.Serializable; + + +public class User implements Serializable { + private static final long serialVersionUID = -3258839839160856613L; + private String id; + private String userName; + private String passWord; + + public User(String userName, String passWord) { + this.userName = userName; + this.passWord = passWord; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + @Override + public String toString() { + return "User{" + + "id='" + id + '\'' + + ", userName='" + userName + '\'' + + ", passWord='" + passWord + '\'' + + '}'; + } +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java new file mode 100644 index 000000000..50877eb1c --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java @@ -0,0 +1,10 @@ +package com.neo.repository.primary; + +import com.neo.model.User; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author neo + */ +public interface PrimaryRepository extends MongoRepository { +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java new file mode 100644 index 000000000..11df9153a --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java @@ -0,0 +1,10 @@ +package com.neo.repository.secondary; + +import com.neo.model.User; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author neo + */ +public interface SecondaryRepository extends MongoRepository { +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties new file mode 100644 index 000000000..d4287a17a --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=spring-boot-multi-mongodb + +mongodb.primary.uri=mongodb://192.168.0.75:20000 +mongodb.primary.database=primary +mongodb.secondary.uri=mongodb://192.168.0.75:20000 +mongodb.secondary.database=secondary + + diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java new file mode 100644 index 000000000..8f59e588d --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MultiMongodbApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java new file mode 100644 index 000000000..42bf1b447 --- /dev/null +++ b/2.x/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java @@ -0,0 +1,45 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.repository.primary.PrimaryRepository; +import com.neo.repository.secondary.SecondaryRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MuliDatabaseTest { + + @Autowired + private PrimaryRepository primaryRepository; + + @Autowired + private SecondaryRepository secondaryRepository; + + @Test + public void TestSave() { + System.out.println("************************************************************"); + System.out.println("测试开始"); + System.out.println("************************************************************"); + this.primaryRepository.save(new User("小张", "123456")); + this.secondaryRepository.save(new User("小王", "654321")); + List primaries = this.primaryRepository.findAll(); + for (User primary : primaries) { + System.out.println(primary.toString()); + } + List secondaries = this.secondaryRepository.findAll(); + for (User secondary : secondaries) { + System.out.println(secondary.toString()); + } + System.out.println("************************************************************"); + System.out.println("测试完成"); + System.out.println("************************************************************"); + } + +} diff --git a/2.x/spring-boot-mybatis-plus/pom.xml b/2.x/spring-boot-mybatis-plus/pom.xml new file mode 100644 index 000000000..6f088774e --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.example + spring-boot-mybatis-plus + 1.0.0 + jar + + Spring Boot MyBatis Plus + Spring Boot 2 Demo + + + org.springframework.boot + spring-boot-starter-parent + 2.1.4.RELEASE + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.projectlombok + lombok + true + + + com.baomidou + mybatis-plus-boot-starter + 3.1.1 + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/MyBatisPlusApplication.java b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/MyBatisPlusApplication.java new file mode 100644 index 000000000..8cadbf0c6 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/MyBatisPlusApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MyBatisPlusApplication { + + public static void main(String[] args) { + SpringApplication.run(MyBatisPlusApplication.class, args); + } +} diff --git a/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/config/MybatisPlusConfig.java b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/config/MybatisPlusConfig.java new file mode 100644 index 000000000..914ffbbab --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/config/MybatisPlusConfig.java @@ -0,0 +1,19 @@ +package com.neo.config; + +import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@MapperScan("com.neo.mapper") +public class MybatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public PaginationInterceptor paginationInterceptor() { + return new PaginationInterceptor(); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/mapper/UserMapper.java b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/mapper/UserMapper.java new file mode 100644 index 000000000..227c33c92 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/mapper/UserMapper.java @@ -0,0 +1,8 @@ +package com.neo.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.neo.model.User; + +public interface UserMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..0cf4eccd0 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/java/com/neo/model/User.java @@ -0,0 +1,11 @@ +package com.neo.model; + +import lombok.Data; + +@Data +public class User { + private Long id; + private String name; + private Integer age; + private String email; +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis-plus/src/main/resources/application.yml b/2.x/spring-boot-mybatis-plus/src/main/resources/application.yml new file mode 100644 index 000000000..46530ce41 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/resources/application.yml @@ -0,0 +1,14 @@ +# DataSource Config +spring: + datasource: + driver-class-name: org.h2.Driver + schema: classpath:db/schema-h2.sql + data: classpath:db/data-h2.sql + url: jdbc:h2:mem:test + username: root + password: test + +# Logger Config +logging: + level: + com.neo: debug diff --git a/2.x/spring-boot-mybatis-plus/src/main/resources/db/data-h2.sql b/2.x/spring-boot-mybatis-plus/src/main/resources/db/data-h2.sql new file mode 100644 index 000000000..7e97dbde4 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/resources/db/data-h2.sql @@ -0,0 +1,8 @@ +DELETE FROM user; + +INSERT INTO user (id, name, age, email) VALUES +(1, 'neo', 18, 'smile1@ityouknow.com'), +(2, 'keep', 36, 'smile@ityouknow.com'), +(3, 'pure', 28, 'smile@ityouknow.com'), +(4, 'smile', 21, 'smile@ityouknow.com'), +(5, 'it', 24, 'smile@ityouknow.com'); \ No newline at end of file diff --git a/2.x/spring-boot-mybatis-plus/src/main/resources/db/schema-h2.sql b/2.x/spring-boot-mybatis-plus/src/main/resources/db/schema-h2.sql new file mode 100644 index 000000000..baa5a6160 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/main/resources/db/schema-h2.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS user; + +CREATE TABLE user +( + id BIGINT(20) NOT NULL COMMENT '主键ID', + name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', + age INT(11) NULL DEFAULT NULL COMMENT '年龄', + email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusApplicationTests.java b/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusApplicationTests.java new file mode 100644 index 000000000..1eaf2857a --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MyBatisPlusApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusTest.java b/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusTest.java new file mode 100644 index 000000000..d68233528 --- /dev/null +++ b/2.x/spring-boot-mybatis-plus/src/test/java/com/neo/MyBatisPlusTest.java @@ -0,0 +1,102 @@ +package com.neo; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.neo.mapper.UserMapper; +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MyBatisPlusTest { + + @Autowired + private UserMapper userMapper; + + + @Test + public void testSelectOne() { + User user = userMapper.selectById(1L); + System.out.println(user); + } + + @Test + public void testInsert() { + User user = new User(); + user.setName("微笑"); + user.setAge(3); + user.setEmail("neo@tooool.org"); + assertThat(userMapper.insert(user)).isGreaterThan(0); + // 成功直接拿会写的 ID + assertThat(user.getId()).isNotNull(); + } + + @Test + public void testDelete() { + assertThat(userMapper.deleteById(3L)).isGreaterThan(0); + assertThat(userMapper.delete(new QueryWrapper() + .lambda().eq(User::getName, "smile"))).isGreaterThan(0); + } + + @Test + public void testUpdate() { + User user = userMapper.selectById(2); + assertThat(user.getAge()).isEqualTo(36); + assertThat(user.getName()).isEqualTo("keep"); + + userMapper.update( + null, + Wrappers.lambdaUpdate().set(User::getEmail, "123@123").eq(User::getId, 2) + ); + assertThat(userMapper.selectById(2).getEmail()).isEqualTo("123@123"); + } + + @Test + public void testSelect() { + List userList = userMapper.selectList(null); + Assert.assertEquals(5, userList.size()); + userList.forEach(System.out::println); + } + + @Test + public void testSelectCondition() { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.select("max(id) as id"); + List userList = userMapper.selectList(wrapper); + userList.forEach(System.out::println); + } + + @Test + public void testPage() { + System.out.println("----- baseMapper 自带分页 ------"); + Page page = new Page<>(1, 2); + IPage userIPage = userMapper.selectPage(page, new QueryWrapper() + .gt("age", 6)); + assertThat(page).isSameAs(userIPage); + System.out.println("总条数 ------> " + userIPage.getTotal()); + System.out.println("当前页数 ------> " + userIPage.getCurrent()); + System.out.println("当前每页显示数 ------> " + userIPage.getSize()); + print(userIPage.getRecords()); + System.out.println("----- baseMapper 自带分页 ------"); + } + + private void print(List list) { + if (!CollectionUtils.isEmpty(list)) { + list.forEach(System.out::println); + } + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml new file mode 100644 index 000000000..fc8412fd3 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-annotation-mulidatasource + 1.0.0 + jar + + spring-boot-mybatis-annotation-mulidatasource + Demo project for Spring Boot and mybatis with annotation + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java new file mode 100644 index 000000000..a77fe795e --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MAMApplication { + + public static void main(String[] args) { + SpringApplication.run(MAMApplication.class, args); + } +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java new file mode 100644 index 000000000..2db7d6533 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java @@ -0,0 +1,51 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate") +public class DataSource1Config { + + @Bean(name = "test1DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test1") + @Primary + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test1SqlSessionFactory") + @Primary + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + return bean.getObject(); + } + + @Bean(name = "test1TransactionManager") + @Primary + public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test1SqlSessionTemplate") + @Primary + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java new file mode 100644 index 000000000..e52928c43 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java @@ -0,0 +1,46 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test2", sqlSessionTemplateRef = "test2SqlSessionTemplate") +public class DataSource2Config { + + @Bean(name = "test2DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test2") + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test2SqlSessionFactory") + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + return bean.getObject(); + } + + @Bean(name = "test2TransactionManager") + public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test2SqlSessionTemplate") + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java new file mode 100644 index 000000000..6ab2e6a09 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java @@ -0,0 +1,35 @@ +package com.neo.mapper.test1; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +public interface User1Mapper { + + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java new file mode 100644 index 000000000..50c5c855d --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java @@ -0,0 +1,35 @@ +package com.neo.mapper.test2; + +import java.util.List; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import org.apache.ibatis.annotations.*; + +public interface User2Mapper { + + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..c92c15d66 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,50 @@ +package com.neo.web; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import com.neo.model.User; +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.RestController; + +import com.neo.mapper.test2.User2Mapper; + +@RestController +public class UserController { + + @Autowired + private User1Mapper user1Mapper; + + @Autowired + private User2Mapper user2Mapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=user1Mapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=user2Mapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + user2Mapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + user2Mapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + user1Mapper.delete(id); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties new file mode 100644 index 000000000..819d06c92 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties @@ -0,0 +1,12 @@ +mybatis.type-aliases-package=com.neo.model + +spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test1.username=root +spring.datasource.test1.password=root +spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test2.username=root +spring.datasource.test2.password=root +spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java new file mode 100644 index 000000000..8b7bbef35 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MAMApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java new file mode 100644 index 000000000..b08f07b7c --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java @@ -0,0 +1,52 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User1MapperTest { + + @Autowired + private User1Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.size()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(6l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(6l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java new file mode 100644 index 000000000..77ebc4675 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java @@ -0,0 +1,51 @@ +package com.neo.mapper; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import com.neo.mapper.test2.User2Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User2MapperTest { + + @Autowired + private User2Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(6l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(6l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml new file mode 100644 index 000000000..45ab8ec36 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml @@ -0,0 +1,57 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-annotation + 1.0.0 + jar + + spring-boot-mybatis-annotation + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java new file mode 100644 index 000000000..ebac358ad --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.neo.mapper") +public class MybatisAnnotationApplication { + + public static void main(String[] args) { + SpringApplication.run(MybatisAnnotationApplication.class, args); + } +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java new file mode 100644 index 000000000..0189ea95c --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java @@ -0,0 +1,40 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import com.neo.enums.UserSexEnum; + +public interface UserMapper { + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..25144b362 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,47 @@ +package com.neo.web; + +import java.util.List; + +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.UserMapper; + +@RestController +public class UserController { + + @Autowired + private UserMapper userMapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=userMapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=userMapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + userMapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + userMapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + userMapper.delete(id); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties new file mode 100644 index 000000000..06400e91a --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties @@ -0,0 +1,6 @@ +mybatis.type-aliases-package=com.neo.model + +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java new file mode 100644 index 000000000..9a9777482 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MybatisAnnotationApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java new file mode 100644 index 000000000..0e12f6fd3 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java @@ -0,0 +1,47 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserMapperTest { + + @Autowired + private UserMapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa1", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb1", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc1", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + System.out.println(users.toString()); + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(30l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(30l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml new file mode 100644 index 000000000..66f257af5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-xml-mulidatasource + 1.0.0 + jar + + spring-boot-mybatis-xml-mulidatasource + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java new file mode 100644 index 000000000..ad7b9d9d7 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MXMApplication { + + public static void main(String[] args) { + SpringApplication.run(MXMApplication.class, args); + } +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java new file mode 100644 index 000000000..40bcf28d5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java @@ -0,0 +1,53 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +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 org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate") +public class DataSource1Config { + + @Bean(name = "test1DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test1") + @Primary + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test1SqlSessionFactory") + @Primary + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml")); + return bean.getObject(); + } + + @Bean(name = "test1TransactionManager") + @Primary + public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test1SqlSessionTemplate") + @Primary + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java new file mode 100644 index 000000000..67864089a --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java @@ -0,0 +1,48 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test2", sqlSessionTemplateRef = "test2SqlSessionTemplate") +public class DataSource2Config { + + @Bean(name = "test2DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test2") + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test2SqlSessionFactory") + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml")); + return bean.getObject(); + } + + @Bean(name = "test2TransactionManager") + public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test2SqlSessionTemplate") + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java new file mode 100644 index 000000000..d9502822f --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper.test1; + +import com.neo.model.User; + +import java.util.List; + +public interface User1Mapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java new file mode 100644 index 000000000..d5c91ebf1 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper.test2; + +import java.util.List; + +import com.neo.model.User; + +public interface User2Mapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..a608500f1 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,51 @@ +package com.neo.web; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.test2.User2Mapper; + +@RestController +public class UserController { + + @Autowired + private User1Mapper user1Mapper; + + @Autowired + private User2Mapper user2Mapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=user1Mapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=user2Mapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + user2Mapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + user2Mapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + user1Mapper.delete(id); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties new file mode 100644 index 000000000..e2e0f4a74 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties @@ -0,0 +1,11 @@ +mybatis.config-location=classpath:mybatis/mybatis-config.xml + +spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test1.username=root +spring.datasource.test1.password=root +spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test2.username=root +spring.datasource.test2.password=root +spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml new file mode 100644 index 000000000..0a2ced2ce --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml new file mode 100644 index 000000000..da3dc2e7c --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 000000000..56097ffb9 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java new file mode 100644 index 000000000..422edba96 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MXMApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java new file mode 100644 index 000000000..12c4b6aa8 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java @@ -0,0 +1,52 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User1MapperTest { + + @Autowired + private User1Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.size()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(6l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(6l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java new file mode 100644 index 000000000..77ebc4675 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java @@ -0,0 +1,51 @@ +package com.neo.mapper; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import com.neo.mapper.test2.User2Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User2MapperTest { + + @Autowired + private User2Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(6l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(6l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml new file mode 100644 index 000000000..389ee8163 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-xml + 1.0.0 + jar + + spring-boot-mybatis-xml + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java new file mode 100644 index 000000000..863b95aba --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.neo.mapper") +public class MybatisXmlApplication { + + public static void main(String[] args) { + SpringApplication.run(MybatisXmlApplication.class, args); + } +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java new file mode 100644 index 000000000..f08f70bf3 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; + +public interface UserMapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..25144b362 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,47 @@ +package com.neo.web; + +import java.util.List; + +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.UserMapper; + +@RestController +public class UserController { + + @Autowired + private UserMapper userMapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=userMapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=userMapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + userMapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + userMapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + userMapper.delete(id); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties new file mode 100644 index 000000000..0e2bea577 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties @@ -0,0 +1,8 @@ +mybatis.config-location=classpath:mybatis/mybatis-config.xml +mybatis.mapper-locations=classpath:mybatis/mapper/*.xml +mybatis.type-aliases-package=com.neo.model + +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml new file mode 100644 index 000000000..b84731b11 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 000000000..56097ffb9 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java new file mode 100644 index 000000000..3938dfde3 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MybatisXmlApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java new file mode 100644 index 000000000..586ff57af --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java @@ -0,0 +1,51 @@ +package com.neo.mapper; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserMapperTest { + + @Autowired + private UserMapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(6l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(6l).getNickName()))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java new file mode 100644 index 000000000..2fd5fa943 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java @@ -0,0 +1,37 @@ +package com.neo.web; + + + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserControllerTest { + @Autowired + private WebApplicationContext wac; + private MockMvc mockMvc; + + @Before + public void setUp() throws Exception { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 + } + + @Test + public void getUsers() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/getUsers") + .accept(MediaType.APPLICATION_JSON_UTF8)).andDo(print()); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/2.x/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/2.x/spring-boot-package-war/pom.xml b/2.x/spring-boot-package-war/pom.xml new file mode 100644 index 000000000..c54d0da80 --- /dev/null +++ b/2.x/spring-boot-package-war/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.neo + spring-boot-package-war + 0.0.1-SNAPSHOT + war + + spring-boot-package-war + Demo project for Spring Boot package war + + + org.springframework.boot + spring-boot-starter-parent + 1.3.6.RELEASE + + + + + UTF-8 + 1.7 + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/2.x/spring-boot-package-war/src/main/java/com/neo/Application.java b/2.x/spring-boot-package-war/src/main/java/com/neo/Application.java new file mode 100644 index 000000000..6cda50c81 --- /dev/null +++ b/2.x/spring-boot-package-war/src/main/java/com/neo/Application.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/2.x/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java b/2.x/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java new file mode 100644 index 000000000..e57ead010 --- /dev/null +++ b/2.x/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +/** + * Created by summer on 2017/5/8. + */ +public class ServletInitializer extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } +} diff --git a/2.x/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java b/2.x/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java new file mode 100644 index 000000000..c231fae49 --- /dev/null +++ b/2.x/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @RequestMapping("/hello") + public String index() { + return "Hello World xx"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-package-war/src/main/resources/application.properties b/2.x/spring-boot-package-war/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java b/2.x/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java new file mode 100644 index 000000000..f35d76c7a --- /dev/null +++ b/2.x/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = Application.class) +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java b/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..02133d7ef --- /dev/null +++ b/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,39 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = MockServletContext.class) +@WebAppConfiguration +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..423d57caa --- /dev/null +++ b/2.x/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,37 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = MockServletContext.class) +@WebAppConfiguration +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-package/pom.xml b/2.x/spring-boot-package/pom.xml new file mode 100644 index 000000000..58d3791cf --- /dev/null +++ b/2.x/spring-boot-package/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + com.neo + spring-boot-package + 1.0.0 + jar + + spring-boot-package + Demo project for Spring Boot package war + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-package/src/main/java/com/neo/PackageApplication.java b/2.x/spring-boot-package/src/main/java/com/neo/PackageApplication.java new file mode 100644 index 000000000..6611164fa --- /dev/null +++ b/2.x/spring-boot-package/src/main/java/com/neo/PackageApplication.java @@ -0,0 +1,19 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class PackageApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(PackageApplication.class); + } + + public static void main(String[] args) { + SpringApplication.run(PackageApplication.class, args); + } +} diff --git a/2.x/spring-boot-package/src/main/java/com/neo/controller/HelloController.java b/2.x/spring-boot-package/src/main/java/com/neo/controller/HelloController.java new file mode 100644 index 000000000..5e93f0dda --- /dev/null +++ b/2.x/spring-boot-package/src/main/java/com/neo/controller/HelloController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-package/src/main/resources/application-dev.properties b/2.x/spring-boot-package/src/main/resources/application-dev.properties new file mode 100644 index 000000000..c83a6aaa9 --- /dev/null +++ b/2.x/spring-boot-package/src/main/resources/application-dev.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-test +info.app.version= 1.0.0 \ No newline at end of file diff --git a/2.x/spring-boot-package/src/main/resources/application-pro.properties b/2.x/spring-boot-package/src/main/resources/application-pro.properties new file mode 100644 index 000000000..5bc6c5ce3 --- /dev/null +++ b/2.x/spring-boot-package/src/main/resources/application-pro.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-pro +info.app.version= 1.0.0 \ No newline at end of file diff --git a/2.x/spring-boot-package/src/main/resources/application-test.properties b/2.x/spring-boot-package/src/main/resources/application-test.properties new file mode 100644 index 000000000..995c6d213 --- /dev/null +++ b/2.x/spring-boot-package/src/main/resources/application-test.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-uat +info.app.version= 1.0.0 \ No newline at end of file diff --git a/2.x/spring-boot-package/src/main/resources/application.properties b/2.x/spring-boot-package/src/main/resources/application.properties new file mode 100644 index 000000000..bba9dfd9a --- /dev/null +++ b/2.x/spring-boot-package/src/main/resources/application.properties @@ -0,0 +1,26 @@ +# \u9879\u76EEcontextPath\uFF0C\u4E00\u822C\u4E0D\u914D\u7F6E +#server.servlet.context-path=/myspringboot +# \u9519\u8BEF\u9875\uFF0C\u6307\u5B9A\u53D1\u751F\u9519\u8BEF\u65F6\uFF0C\u8DF3\u8F6C\u7684URL\u3002 +server.error.path=/error +# \u670D\u52A1\u7AEF\u53E3 +server.port=8080 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 +# \u8BE5\u670D\u52A1\u7ED1\u5B9AIP\u5730\u5740\uFF0C\u542F\u52A8\u670D\u52A1\u5668\u65F6\u5982\u672C\u673A\u4E0D\u662F\u8BE5IP\u5730\u5740\u5219\u629B\u51FA\u5F02\u5E38\u542F\u52A8\u5931\u8D25\uFF0C\u53EA\u6709\u7279\u6B8A\u9700\u6C42\u7684\u60C5\u51B5\u4E0B\u624D\u914D\u7F6E +#server.address=192.168.0.6 + +# tomcat \u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=600 +# tomcat\u7684URI\u7F16\u7801 +server.tomcat.uri-encoding=UTF-8 +# \u5B58\u653ETomcat\u7684\u65E5\u5FD7\u3001Dump\u7B49\u6587\u4EF6\u7684\u4E34\u65F6\u6587\u4EF6\u5939\uFF0C\u9ED8\u8BA4\u4E3A\u7CFB\u7EDF\u7684tmp\u6587\u4EF6\u5939 +server.tomcat.basedir=/tmp/log +# \u6253\u5F00Tomcat\u7684Access\u65E5\u5FD7\uFF0C\u5E76\u53EF\u4EE5\u8BBE\u7F6E\u65E5\u5FD7\u683C\u5F0F +#server.tomcat.access-log-enabled=true +#server.tomcat.access-log-pattern= +# accesslog\u76EE\u5F55\uFF0C\u9ED8\u8BA4\u5728basedir/logs +#server.tomcat.accesslog.directory= +# \u65E5\u5FD7\u6587\u4EF6\u76EE\u5F55 +logging.path=/tmp/log +# \u65E5\u5FD7\u6587\u4EF6\u540D\u79F0\uFF0C\u9ED8\u8BA4\u4E3Aspring.log +logging.file=myapp.log \ No newline at end of file diff --git a/2.x/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java b/2.x/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java new file mode 100644 index 000000000..ff737b922 --- /dev/null +++ b/2.x/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class PackageApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java b/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..149543930 --- /dev/null +++ b/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,36 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..d8b01a50d --- /dev/null +++ b/2.x/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,34 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/pom.xml b/2.x/spring-boot-rabbitmq/pom.xml new file mode 100644 index 000000000..a23b8581d --- /dev/null +++ b/2.x/spring-boot-rabbitmq/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + com.neo + spring-boot-rabbitmq + 1.0.0 + jar + + spring-boot-rabbitmq + Demo project for Spring Boot and rabbitmq + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java new file mode 100644 index 000000000..15d177f39 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RabbitMQApplication { + + public static void main(String[] args) { + SpringApplication.run(RabbitMQApplication.class, args); + } +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..f4eec95e4 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/model/User.java @@ -0,0 +1,37 @@ +package com.neo.model; + +import java.io.Serializable; + +/** + * Created by summer on 2016/11/29. + */ +public class User implements Serializable{ + + private String name; + + private String pass; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + @Override + public String toString() { + return "User{" + + "name='" + name + '\'' + + ", pass='" + pass + '\'' + + '}'; + } +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java new file mode 100644 index 000000000..4fe21fa9f --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/FanoutRabbitConfig.java @@ -0,0 +1,49 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.FanoutExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class FanoutRabbitConfig { + + @Bean + public Queue AMessage() { + return new Queue("fanout.A"); + } + + @Bean + public Queue BMessage() { + return new Queue("fanout.B"); + } + + @Bean + public Queue CMessage() { + return new Queue("fanout.C"); + } + + @Bean + FanoutExchange fanoutExchange() { + return new FanoutExchange("fanoutExchange"); + } + + @Bean + Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) { + return BindingBuilder.bind(AMessage).to(fanoutExchange); + } + + @Bean + Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) { + return BindingBuilder.bind(BMessage).to(fanoutExchange); + } + + @Bean + Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) { + return BindingBuilder.bind(CMessage).to(fanoutExchange); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java new file mode 100644 index 000000000..d5d649b5c --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/RabbitConfig.java @@ -0,0 +1,27 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class RabbitConfig { + + @Bean + public Queue helloQueue() { + return new Queue("hello"); + } + + @Bean + public Queue neoQueue() { + return new Queue("neo"); + } + + @Bean + public Queue objectQueue() { + return new Queue("object"); + } + + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java new file mode 100644 index 000000000..7bd2a096c --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/TopicRabbitConfig.java @@ -0,0 +1,41 @@ +package com.neo.rabbit; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.TopicExchange; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class TopicRabbitConfig { + + final static String message = "topic.message"; + final static String messages = "topic.messages"; + + @Bean + public Queue queueMessage() { + return new Queue(TopicRabbitConfig.message); + } + + @Bean + public Queue queueMessages() { + return new Queue(TopicRabbitConfig.messages); + } + + @Bean + TopicExchange exchange() { + return new TopicExchange("topicExchange"); + } + + @Bean + Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) { + return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message"); + } + + @Bean + Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) { + return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#"); + } +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java new file mode 100644 index 000000000..256de2eee --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverA.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.A") +public class FanoutReceiverA { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver A : " + message); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java new file mode 100644 index 000000000..a721da684 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverB.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.B") +public class FanoutReceiverB { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver B: " + message); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java new file mode 100644 index 000000000..aceef8b08 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutReceiverC.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "fanout.C") +public class FanoutReceiverC { + + @RabbitHandler + public void process(String message) { + System.out.println("fanout Receiver C: " + message); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java new file mode 100644 index 000000000..2fa62d39c --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/fanout/FanoutSender.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.fanout; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class FanoutSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hi, fanout msg "; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("fanoutExchange","", context); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java new file mode 100644 index 000000000..2d59b1740 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloReceiver.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.hello; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +@RabbitListener(queues = "hello") +public class HelloReceiver { + + @RabbitHandler + public void process(String hello) { + System.out.println("Receiver : " + hello); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java new file mode 100644 index 000000000..05fc740ac --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/hello/HelloSender.java @@ -0,0 +1,22 @@ +package com.neo.rabbit.hello; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class HelloSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hello " + new Date(); + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("hello", context); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java new file mode 100644 index 000000000..c352fbeb5 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver1.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "neo") +public class NeoReceiver1 { + + @RabbitHandler + public void process(String neo) { + System.out.println("Receiver 1: " + neo); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java new file mode 100644 index 000000000..d7cbdd758 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoReceiver2.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "neo") +public class NeoReceiver2 { + + @RabbitHandler + public void process(String neo) { + System.out.println("Receiver 2: " + neo); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java new file mode 100644 index 000000000..755918fb6 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class NeoSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(int i) { + String context = "spirng boot neo queue"+" ****** "+i; + System.out.println("Sender1 : " + context); + this.rabbitTemplate.convertAndSend("neo", context); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java new file mode 100644 index 000000000..e34cce647 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/many/NeoSender2.java @@ -0,0 +1,19 @@ +package com.neo.rabbit.many; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class NeoSender2 { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(int i) { + String context = "spirng boot neo queue"+" ****** "+i; + System.out.println("Sender2 : " + context); + this.rabbitTemplate.convertAndSend("neo", context); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java new file mode 100644 index 000000000..b97f8a026 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectReceiver.java @@ -0,0 +1,17 @@ +package com.neo.rabbit.object; + +import com.neo.model.User; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "object") +public class ObjectReceiver { + + @RabbitHandler + public void process(User user) { + System.out.println("Receiver object : " + user); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java new file mode 100644 index 000000000..9c7aba927 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/object/ObjectSender.java @@ -0,0 +1,21 @@ +package com.neo.rabbit.object; + +import com.neo.model.User; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class ObjectSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send(User user) { + System.out.println("Sender object: " + user.toString()); + this.rabbitTemplate.convertAndSend("object", user); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java new file mode 100644 index 000000000..14523941a --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "topic.message") +public class TopicReceiver { + + @RabbitHandler + public void process(String message) { + System.out.println("Topic Receiver1 : " + message); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java new file mode 100644 index 000000000..9ea81d7fe --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicReceiver2.java @@ -0,0 +1,16 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +@Component +@RabbitListener(queues = "topic.messages") +public class TopicReceiver2 { + + @RabbitHandler + public void process(String message) { + System.out.println("Topic Receiver2 : " + message); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java new file mode 100644 index 000000000..8f17c34e3 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/java/com/neo/rabbit/topic/TopicSender.java @@ -0,0 +1,33 @@ +package com.neo.rabbit.topic; + +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +public class TopicSender { + + @Autowired + private AmqpTemplate rabbitTemplate; + + public void send() { + String context = "hi, i am message all"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.1", context); + } + + public void send1() { + String context = "hi, i am message 1"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.message", context); + } + + public void send2() { + String context = "hi, i am messages 2"; + System.out.println("Sender : " + context); + this.rabbitTemplate.convertAndSend("topicExchange", "topic.messages", context); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/main/resources/application.properties b/2.x/spring-boot-rabbitmq/src/main/resources/application.properties new file mode 100644 index 000000000..c43cab4b7 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.application.name=spring-boot-rabbitmq + +spring.rabbitmq.host=192.168.0.56 +spring.rabbitmq.port=5672 +spring.rabbitmq.username=zzq +spring.rabbitmq.password=zzq diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java new file mode 100644 index 000000000..2bec30988 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RabbitMQApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java new file mode 100644 index 000000000..d9ee0afd9 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/FanoutTest.java @@ -0,0 +1,24 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.fanout.FanoutSender; +import com.neo.rabbit.topic.TopicSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class FanoutTest { + + @Autowired + private FanoutSender sender; + + @Test + public void fanoutSender() throws Exception { + sender.send(); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java new file mode 100644 index 000000000..f790b0452 --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/HelloTest.java @@ -0,0 +1,23 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.hello.HelloSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTest { + + @Autowired + private HelloSender helloSender; + + @Test + public void hello() throws Exception { + helloSender.send(); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java new file mode 100644 index 000000000..08c701cfd --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ManyTest.java @@ -0,0 +1,35 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.many.NeoSender; +import com.neo.rabbit.many.NeoSender2; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ManyTest { + @Autowired + private NeoSender neoSender; + + @Autowired + private NeoSender2 neoSender2; + + @Test + public void oneToMany() throws Exception { + for (int i=0;i<100;i++){ + neoSender.send(i); + } + } + + @Test + public void manyToMany() throws Exception { + for (int i=0;i<100;i++){ + neoSender.send(i); + neoSender2.send(i); + } + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java new file mode 100644 index 000000000..e36daf7ed --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/ObjectTest.java @@ -0,0 +1,26 @@ +package com.neo.rabbitmq; + +import com.neo.model.User; +import com.neo.rabbit.object.ObjectSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ObjectTest { + + @Autowired + private ObjectSender sender; + + @Test + public void sendOject() throws Exception { + User user=new User(); + user.setName("neo"); + user.setPass("123456"); + sender.send(user); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java new file mode 100644 index 000000000..d69a5b85e --- /dev/null +++ b/2.x/spring-boot-rabbitmq/src/test/java/com/neo/rabbitmq/TopicTest.java @@ -0,0 +1,32 @@ +package com.neo.rabbitmq; + +import com.neo.rabbit.topic.TopicSender; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TopicTest { + + @Autowired + private TopicSender sender; + + @Test + public void topic() throws Exception { + sender.send(); + } + + @Test + public void topic1() throws Exception { + sender.send1(); + } + + @Test + public void topic2() throws Exception { + sender.send2(); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-redis/pom.xml b/2.x/spring-boot-redis/pom.xml new file mode 100644 index 000000000..3f836ab99 --- /dev/null +++ b/2.x/spring-boot-redis/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + com.neo + spring-boot-redis + 1.0.0-SNAPSHOT + jar + + spring-boot-redis + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.apache.commons + commons-pool2 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.session + spring-session-data-redis + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-redis/src/main/java/com/neo/RedisApplication.java b/2.x/spring-boot-redis/src/main/java/com/neo/RedisApplication.java new file mode 100644 index 000000000..9c41bedc0 --- /dev/null +++ b/2.x/spring-boot-redis/src/main/java/com/neo/RedisApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RedisApplication { + + public static void main(String[] args) { + SpringApplication.run(RedisApplication.class, args); + } +} diff --git a/2.x/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java b/2.x/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java new file mode 100644 index 000000000..f26748985 --- /dev/null +++ b/2.x/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java @@ -0,0 +1,34 @@ +package com.neo.config; + +import java.lang.reflect.Method; + +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.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.core.RedisTemplate; + + +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport{ + + @Bean + public KeyGenerator keyGenerator() { + return new KeyGenerator() { + @Override + public Object generate(Object target, Method method, Object... 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(); + } + }; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java b/2.x/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java new file mode 100644 index 000000000..400f03fd7 --- /dev/null +++ b/2.x/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java @@ -0,0 +1,9 @@ +package com.neo.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; + +@Configuration +@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30) +public class SessionConfig { +} \ No newline at end of file diff --git a/2.x/spring-boot-redis/src/main/java/com/neo/model/User.java b/2.x/spring-boot-redis/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..045748877 --- /dev/null +++ b/2.x/spring-boot-redis/src/main/java/com/neo/model/User.java @@ -0,0 +1,88 @@ +package com.neo.model; + +import java.io.Serializable; + + + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String password; + private String email; + private String nickname; + private String regTime; + + public User() { + super(); + } + public User(String email, String nickname, String password, String userName, String regTime) { + super(); + this.email = email; + this.nickname = nickname; + this.password = password; + this.userName = userName; + this.regTime = regTime; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", nickname='" + nickname + '\'' + + ", regTime='" + regTime + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-redis/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-redis/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..0447fd1d6 --- /dev/null +++ b/2.x/spring-boot-redis/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,33 @@ +package com.neo.web; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.neo.model.User; + +import javax.servlet.http.HttpSession; +import java.util.UUID; + +@RestController +public class UserController { + + @RequestMapping("/getUser") + @Cacheable(value="user-key") + public User getUser() { + User user=new User("aa@126.com", "aa", "aa123456", "aa","123"); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return user; + } + + + @RequestMapping("/uid") + String uid(HttpSession session) { + UUID uid = (UUID) session.getAttribute("uid"); + if (uid == null) { + uid = UUID.randomUUID(); + } + session.setAttribute("uid", uid); + return session.getId(); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-redis/src/main/resources/application.properties b/2.x/spring-boot-redis/src/main/resources/application.properties new file mode 100644 index 000000000..2d4d7e89b --- /dev/null +++ b/2.x/spring-boot-redis/src/main/resources/application.properties @@ -0,0 +1,17 @@ +# REDIS +# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09 +spring.redis.database=0 +# Redis\u670D\u52A1\u5668\u5730\u5740 +spring.redis.host=localhost +# 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 \u9ED8\u8BA4 8 +spring.redis.lettuce.pool.max-active=8 +# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 \u9ED8\u8BA4 -1 +spring.redis.lettuce.pool.max-wait=-1 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 \u9ED8\u8BA4 8 +spring.redis.lettuce.pool.max-idle=8 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 \u9ED8\u8BA4 0 +spring.redis.lettuce.pool.min-idle=0 diff --git a/2.x/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java b/2.x/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java new file mode 100644 index 000000000..c92da71f7 --- /dev/null +++ b/2.x/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RedisApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello web"); + } + +} diff --git a/2.x/spring-boot-redis/src/test/java/com/neo/TestRedis.java b/2.x/spring-boot-redis/src/test/java/com/neo/TestRedis.java new file mode 100644 index 000000000..fe8f86e5f --- /dev/null +++ b/2.x/spring-boot-redis/src/test/java/com/neo/TestRedis.java @@ -0,0 +1,49 @@ +package com.neo; + +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.concurrent.TimeUnit; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestRedis { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + @Autowired + private RedisTemplate redisTemplate; + + @Test + public void test() throws Exception { + stringRedisTemplate.opsForValue().set("aaa", "111"); + Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa")); + } + + @Test + public void testObj() throws Exception { + User user=new User("aa@126.com", "aa", "aa123456", "aa","123"); + ValueOperations operations=redisTemplate.opsForValue(); + operations.set("com.neox", user); + operations.set("com.neo.f", user,1, TimeUnit.SECONDS); + Thread.sleep(1000); + //redisTemplate.delete("com.neo.f"); + boolean exists=redisTemplate.hasKey("com.neo.f"); + if(exists){ + System.out.println("exists is true"); + }else{ + System.out.println("exists is false"); + } + // Assert.assertEquals("aa", operations.get("com.neo.f").getUserName()); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-scheduler/pom.xml b/2.x/spring-boot-scheduler/pom.xml new file mode 100644 index 000000000..38ad39399 --- /dev/null +++ b/2.x/spring-boot-scheduler/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + com.neo + spring-boot-scheduler + 1.0.0 + jar + + spring-boot-scheduler + Demo project for Spring Boot and scheduler + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java b/2.x/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java new file mode 100644 index 000000000..1fd012d24 --- /dev/null +++ b/2.x/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class SchedulerApplication { + + public static void main(String[] args) { + SpringApplication.run(SchedulerApplication.class, args); + } +} diff --git a/2.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java b/2.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java new file mode 100644 index 000000000..7b59c9f2b --- /dev/null +++ b/2.x/spring-boot-scheduler/src/main/java/com/neo/task/Scheduler2Task.java @@ -0,0 +1,23 @@ +package com.neo.task; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Created by summer on 2016/12/1. + */ + +@Component +public class Scheduler2Task { + + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); + + @Scheduled(fixedRate = 6000) + public void reportCurrentTime() { + System.out.println("现在时间:" + dateFormat.format(new Date())); + } + +} diff --git a/2.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java b/2.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java new file mode 100644 index 000000000..69885e3cc --- /dev/null +++ b/2.x/spring-boot-scheduler/src/main/java/com/neo/task/SchedulerTask.java @@ -0,0 +1,22 @@ +package com.neo.task; + +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * Created by summer on 2016/12/1. + */ + +@Component +public class SchedulerTask { + + private int count=0; + + @Scheduled(cron="*/6 * * * * ?") + private void process(){ + System.out.println("this is scheduler task runing "+(count++)); + } + +} diff --git a/2.x/spring-boot-scheduler/src/main/resources/application.properties b/2.x/spring-boot-scheduler/src/main/resources/application.properties new file mode 100644 index 000000000..8978a46f1 --- /dev/null +++ b/2.x/spring-boot-scheduler/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=spirng-boot-scheduler + diff --git a/2.x/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java b/2.x/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java new file mode 100644 index 000000000..9a627ba57 --- /dev/null +++ b/2.x/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SchedulerApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/2.x/spring-boot-shiro/pom.xml b/2.x/spring-boot-shiro/pom.xml new file mode 100644 index 000000000..256443b33 --- /dev/null +++ b/2.x/spring-boot-shiro/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + com.neo + spring-boot-shiro + 0.0.1-SNAPSHOT + jar + + spring-boot-shiro + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + net.sourceforge.nekohtml + nekohtml + 1.9.22 + + + org.springframework.boot + spring-boot-starter-web + + + org.apache.shiro + shiro-spring + 1.7.2 + + + mysql + mysql-connector-java + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/ShiroApplication.java b/2.x/spring-boot-shiro/src/main/java/com/neo/ShiroApplication.java new file mode 100644 index 000000000..ee576763f --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/ShiroApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ShiroApplication { + + public static void main(String[] args) { + SpringApplication.run(ShiroApplication.class, args); + } +} diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java b/2.x/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java new file mode 100644 index 000000000..f7d28c553 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java @@ -0,0 +1,60 @@ +package com.neo.config; + +import com.neo.model.SysPermission; +import com.neo.model.SysRole; +import com.neo.model.UserInfo; +import com.neo.sevice.UserInfoService; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +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.apache.shiro.util.ByteSource; + +import javax.annotation.Resource; + +public class MyShiroRealm extends AuthorizingRealm { + @Resource + private UserInfoService userInfoService; + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()"); + SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); + UserInfo userInfo = (UserInfo)principals.getPrimaryPrincipal(); + for(SysRole role:userInfo.getRoleList()){ + authorizationInfo.addRole(role.getRole()); + for(SysPermission p:role.getPermissions()){ + authorizationInfo.addStringPermission(p.getPermission()); + } + } + return authorizationInfo; + } + + /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/ + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) + throws AuthenticationException { + System.out.println("MyShiroRealm.doGetAuthenticationInfo()"); + //获取用户的输入的账号. + String username = (String)token.getPrincipal(); + System.out.println(token.getCredentials()); + //通过username从数据库中查找 User对象,如果找到,没找到. + //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 + UserInfo userInfo = userInfoService.findByUsername(username); + System.out.println("----->>userInfo="+userInfo); + if(userInfo == null){ + return null; + } + SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( + userInfo, //用户名 + userInfo.getPassword(), //密码 + ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt + getName() //realm name + ); + return authenticationInfo; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java b/2.x/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java new file mode 100644 index 000000000..00f524b24 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java @@ -0,0 +1,98 @@ +package com.neo.config; + +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Properties; + +@Configuration +public class ShiroConfig { + @Bean + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + System.out.println("ShiroConfiguration.shirFilter()"); + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + shiroFilterFactoryBean.setSecurityManager(securityManager); + //拦截器. + Map filterChainDefinitionMap = new LinkedHashMap(); + // 配置不会被拦截的链接 顺序判断 + filterChainDefinitionMap.put("/static/**", "anon"); + //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 + filterChainDefinitionMap.put("/logout", "logout"); + //:这是一个坑呢,一不小心代码就不好使了; + // + filterChainDefinitionMap.put("/**", "authc"); + // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 + shiroFilterFactoryBean.setLoginUrl("/login"); + // 登录成功后要跳转的链接 + shiroFilterFactoryBean.setSuccessUrl("/index"); + + //未授权界面; + shiroFilterFactoryBean.setUnauthorizedUrl("/403"); + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; + } + + /** + * 凭证匹配器 + * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 + * ) + * @return + */ + @Bean + public HashedCredentialsMatcher hashedCredentialsMatcher(){ + HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); + hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; + hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); + return hashedCredentialsMatcher; + } + + @Bean + public MyShiroRealm myShiroRealm(){ + MyShiroRealm myShiroRealm = new MyShiroRealm(); + myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); + return myShiroRealm; + } + + + @Bean + public SecurityManager securityManager(){ + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + securityManager.setRealm(myShiroRealm()); + return securityManager; + } + + /** + * 开启shiro aop注解支持. + * 使用代理方式;所以需要开启代码支持; + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + + @Bean(name="simpleMappingExceptionResolver") + public SimpleMappingExceptionResolver + createSimpleMappingExceptionResolver() { + SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); + Properties mappings = new Properties(); + mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理 + mappings.setProperty("UnauthorizedException","403"); + r.setExceptionMappings(mappings); // None by default + r.setDefaultErrorView("error"); // No default + r.setExceptionAttribute("ex"); // Default is "exception" + //r.setWarnLogCategory("example.MvcLogger"); // No default + return r; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java b/2.x/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java new file mode 100644 index 000000000..dfd52c3dc --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java @@ -0,0 +1,9 @@ +package com.neo.dao; + +import com.neo.model.UserInfo; +import org.springframework.data.repository.CrudRepository; + +public interface UserInfoDao extends CrudRepository { + /**通过username查找用户信息;*/ + public UserInfo findByUsername(String username); +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysPermission.java b/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysPermission.java new file mode 100644 index 000000000..b603d521c --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysPermission.java @@ -0,0 +1,94 @@ +package com.neo.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.List; + +@Entity +public class SysPermission implements Serializable { + @Id@GeneratedValue + private Integer id;//主键. + private String name;//名称. + @Column(columnDefinition="enum('menu','button')") + private String resourceType;//资源类型,[menu|button] + private String url;//资源路径. + private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view + private Long parentId; //父编号 + private String parentIds; //父编号列表 + private Boolean available = Boolean.FALSE; + @ManyToMany + @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")}) + private List roles; + + 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 getResourceType() { + return resourceType; + } + + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public Long getParentId() { + return parentId; + } + + public void setParentId(Long parentId) { + this.parentId = parentId; + } + + public String getParentIds() { + return parentIds; + } + + public void setParentIds(String parentIds) { + this.parentIds = parentIds; + } + + public Boolean getAvailable() { + return available; + } + + public void setAvailable(Boolean available) { + this.available = available; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysRole.java b/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysRole.java new file mode 100644 index 000000000..e22131a44 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/model/SysRole.java @@ -0,0 +1,71 @@ +package com.neo.model; + +import javax.persistence.*; +import java.util.List; + +@Entity +public class SysRole { + @Id@GeneratedValue + private Integer id; // 编号 + private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的: + private String description; // 角色描述,UI界面显示使用 + private Boolean available = Boolean.FALSE; // 是否可用,如果不可用将不会添加给用户 + + //角色 -- 权限关系:多对多关系; + @ManyToMany(fetch= FetchType.EAGER) + @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")}) + private List permissions; + + // 用户 - 角色关系定义; + @ManyToMany + @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")}) + private List userInfos;// 一个角色对应多个用户 + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean getAvailable() { + return available; + } + + public void setAvailable(Boolean available) { + this.available = available; + } + + public List getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + public List getUserInfos() { + return userInfos; + } + + public void setUserInfos(List userInfos) { + this.userInfos = userInfos; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/model/UserInfo.java b/2.x/spring-boot-shiro/src/main/java/com/neo/model/UserInfo.java new file mode 100644 index 000000000..d23087686 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/model/UserInfo.java @@ -0,0 +1,86 @@ +package com.neo.model; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.List; + +@Entity +public class UserInfo implements Serializable { + @Id + @GeneratedValue + private Integer uid; + @Column(unique =true) + private String username;//帐号 + private String name;//名称(昵称或者真实姓名,不同系统不同定义) + private String password; //密码; + private String salt;//加密密码的盐 + private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定. + @ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据; + @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") }) + private List roleList;// 一个用户具有多个角色 + + public Integer getUid() { + return uid; + } + + public void setUid(Integer uid) { + this.uid = uid; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public byte getState() { + return state; + } + + public void setState(byte state) { + this.state = state; + } + + public List getRoleList() { + return roleList; + } + + public void setRoleList(List roleList) { + this.roleList = roleList; + } + + /** + * 密码盐. + * @return + */ + public String getCredentialsSalt(){ + return this.username+this.salt; + } + //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解 +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java b/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java new file mode 100644 index 000000000..b2bc0cb23 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java @@ -0,0 +1,8 @@ +package com.neo.sevice; + +import com.neo.model.UserInfo; + +public interface UserInfoService { + /**通过username查找用户信息;*/ + public UserInfo findByUsername(String username); +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java b/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java new file mode 100644 index 000000000..d63e4f7d0 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java @@ -0,0 +1,19 @@ +package com.neo.sevice.impl; + +import com.neo.dao.UserInfoDao; +import com.neo.model.UserInfo; +import com.neo.sevice.UserInfoService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +@Service +public class UserInfoServiceImpl implements UserInfoService { + @Resource + private UserInfoDao userInfoDao; + @Override + public UserInfo findByUsername(String username) { + System.out.println("UserInfoServiceImpl.findByUsername()"); + return userInfoDao.findByUsername(username); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java b/2.x/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java new file mode 100644 index 000000000..d1c069694 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java @@ -0,0 +1,52 @@ +package com.neo.web; + +import org.apache.shiro.authc.IncorrectCredentialsException; +import org.apache.shiro.authc.UnknownAccountException; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +@Controller +public class HomeController { + @RequestMapping({"/","/index"}) + public String index(){ + return"/index"; + } + + @RequestMapping("/login") + public String login(HttpServletRequest request, Map map) throws Exception{ + System.out.println("HomeController.login()"); + // 登录失败从request中获取shiro处理的异常信息。 + // shiroLoginFailure:就是shiro异常类的全类名. + String exception = (String) request.getAttribute("shiroLoginFailure"); + System.out.println("exception=" + exception); + String msg = ""; + if (exception != null) { + if (UnknownAccountException.class.getName().equals(exception)) { + System.out.println("UnknownAccountException -- > 账号不存在:"); + msg = "UnknownAccountException -- > 账号不存在:"; + } else if (IncorrectCredentialsException.class.getName().equals(exception)) { + System.out.println("IncorrectCredentialsException -- > 密码不正确:"); + msg = "IncorrectCredentialsException -- > 密码不正确:"; + } else if ("kaptchaValidateFailed".equals(exception)) { + System.out.println("kaptchaValidateFailed -- > 验证码错误"); + msg = "kaptchaValidateFailed -- > 验证码错误"; + } else { + msg = "else >> "+exception; + System.out.println("else -- >" + exception); + } + } + map.put("msg", msg); + // 此方法不处理登录成功,由shiro进行处理 + return "/login"; + } + + @RequestMapping("/403") + public String unauthorizedRole(){ + System.out.println("------没有权限-------"); + return "403"; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java b/2.x/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java new file mode 100644 index 000000000..4e8bde77a --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java @@ -0,0 +1,40 @@ +package com.neo.web; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +@RequestMapping("/userInfo") +public class UserInfoController { + + /** + * 用户查询. + * @return + */ + @RequestMapping("/userList") + @RequiresPermissions("userInfo:view")//权限管理; + public String userInfo(){ + return "userInfo"; + } + + /** + * 用户添加; + * @return + */ + @RequestMapping("/userAdd") + @RequiresPermissions("userInfo:add")//权限管理; + public String userInfoAdd(){ + return "userInfoAdd"; + } + + /** + * 用户删除; + * @return + */ + @RequestMapping("/userDel") + @RequiresPermissions("userInfo:del")//权限管理; + public String userDel(){ + return "userInfoDel"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/application.yml b/2.x/spring-boot-shiro/src/main/resources/application.yml new file mode 100644 index 000000000..c34ffa012 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/application.yml @@ -0,0 +1,21 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true + username: root + password: root + #schema: database/import.sql + #sql-script-encoding: utf-8 + driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + database: mysql + show-sql: true + hibernate: + ddl-auto: update + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL5Dialect + + thymeleaf: + cache: false + mode: HTML \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/database/import.sql b/2.x/spring-boot-shiro/src/main/resources/database/import.sql new file mode 100644 index 000000000..73a7f02a0 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/database/import.sql @@ -0,0 +1,12 @@ +INSERT INTO `user_info` (`uid`,`username`,`name`,`password`,`salt`,`state`) VALUES ('1', 'admin', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', 0); +INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (1,0,'用户管理',0,'0/','userInfo:view','menu','userInfo/userList'); +INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (2,0,'用户添加',1,'0/1','userInfo:add','button','userInfo/userAdd'); +INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (3,0,'用户删除',1,'0/1','userInfo:del','button','userInfo/userDel'); +INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (1,0,'管理员','admin'); +INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (2,0,'VIP会员','vip'); +INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (3,1,'test','test'); +INSERT INTO `sys_role_permission` VALUES ('1', '1'); +INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (1,1); +INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (2,1); +INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (3,2); +INSERT INTO `sys_user_role` (`role_id`,`uid`) VALUES (1,1); \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/403.html b/2.x/spring-boot-shiro/src/main/resources/templates/403.html new file mode 100644 index 000000000..97a10975c --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/403.html @@ -0,0 +1,10 @@ + + + + + 403 + + +

403没有权限

+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/index.html b/2.x/spring-boot-shiro/src/main/resources/templates/index.html new file mode 100644 index 000000000..088725ce7 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/index.html @@ -0,0 +1,10 @@ + + + + + index + + +

index

+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/login.html b/2.x/spring-boot-shiro/src/main/resources/templates/login.html new file mode 100644 index 000000000..07ca33195 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/login.html @@ -0,0 +1,15 @@ + + + + + Login + + +错误信息:

+
+

账号:

+

密码:

+

+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/userInfo.html b/2.x/spring-boot-shiro/src/main/resources/templates/userInfo.html new file mode 100644 index 000000000..f835b3fc9 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/userInfo.html @@ -0,0 +1,10 @@ + + + + + UserInfo + + +

用户查询界面

+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html b/2.x/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html new file mode 100644 index 000000000..0716e44ff --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html @@ -0,0 +1,10 @@ + + + + + Add + + +

用户添加界面

+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/main/resources/templates/userInfoDel.html b/2.x/spring-boot-shiro/src/main/resources/templates/userInfoDel.html new file mode 100644 index 000000000..031e00949 --- /dev/null +++ b/2.x/spring-boot-shiro/src/main/resources/templates/userInfoDel.html @@ -0,0 +1,10 @@ + + + + + Del + + +

用户删除界面

+ + \ No newline at end of file diff --git a/2.x/spring-boot-shiro/src/test/java/com/neo/ShiroApplicationTests.java b/2.x/spring-boot-shiro/src/test/java/com/neo/ShiroApplicationTests.java new file mode 100644 index 000000000..fd8a415ef --- /dev/null +++ b/2.x/spring-boot-shiro/src/test/java/com/neo/ShiroApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ShiroApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-swagger/pom.xml b/2.x/spring-boot-swagger/pom.xml new file mode 100644 index 000000000..d001164db --- /dev/null +++ b/2.x/spring-boot-swagger/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + spring-boot-swagger + Spring Boot swagger Sample + Spring Boot swagger Sample + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/SwaggerApplication.java b/2.x/spring-boot-swagger/src/main/java/com/neo/SwaggerApplication.java new file mode 100644 index 000000000..7f12e1bd1 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/SwaggerApplication.java @@ -0,0 +1,15 @@ + +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +@SpringBootApplication +public class SwaggerApplication { + + public static void main(String[] args) { + SpringApplication.run(SwaggerApplication.class, args); + } + +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/config/BaseResult.java b/2.x/spring-boot-swagger/src/main/java/com/neo/config/BaseResult.java new file mode 100644 index 000000000..4e3363fff --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/config/BaseResult.java @@ -0,0 +1,112 @@ +package com.neo.config; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * 通用响应对象 + */ +@ApiModel(description = "响应对象") +public class BaseResult { + private static final int SUCCESS_CODE = 0; + private static final String SUCCESS_MESSAGE = "成功"; + + @ApiModelProperty(value = "响应码", name = "code", required = true, example = "" + SUCCESS_CODE) + private int code; + + @ApiModelProperty(value = "响应消息", name = "msg", required = true, example = SUCCESS_MESSAGE) + private String msg; + + @ApiModelProperty(value = "响应数据", name = "data") + private T data; + + private BaseResult(int code, String msg, T data) { + this.code = code; + this.msg = msg; + this.data = data; + } + + private BaseResult() { + this(SUCCESS_CODE, SUCCESS_MESSAGE); + } + + private BaseResult(int code, String msg) { + this(code, msg, null); + } + + private BaseResult(T data) { + this(SUCCESS_CODE, SUCCESS_MESSAGE, data); + } + + public static BaseResult success() { + return new BaseResult<>(); + } + + public static BaseResult successWithData(T data) { + return new BaseResult<>(data); + } + + public static BaseResult failWithCodeAndMsg(int code, String msg) { + return new BaseResult<>(code, msg, null); + } + + public static BaseResult buildWithParam(ResponseParam param) { + return new BaseResult<>(param.getCode(), param.getMsg(), null); + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + + + public static class ResponseParam { + private int code; + private String msg; + + private ResponseParam(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public static ResponseParam buildParam(int code, String msg) { + return new ResponseParam(code, msg); + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + } +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/config/SwaggerConfig.java b/2.x/spring-boot-swagger/src/main/java/com/neo/config/SwaggerConfig.java new file mode 100644 index 000000000..babb224a7 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/config/SwaggerConfig.java @@ -0,0 +1,39 @@ +package com.neo.config; + +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.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + // 自行修改为自己的包路径 + .apis(RequestHandlerSelectors.basePackage("com.neo.controller")) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("客户管理") + .description("客户管理中心 API 1.0 操作文档") + //服务条款网址 + .termsOfServiceUrl("http://www.ityouknow.com/") + .version("1.0") + .contact(new Contact("纯洁的微笑", "http://www.ityouknow.com/", "ityouknow@126.com")) + .build(); + } +} \ No newline at end of file diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/controller/MessageController.java b/2.x/spring-boot-swagger/src/main/java/com/neo/controller/MessageController.java new file mode 100644 index 000000000..f4ee8b806 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/controller/MessageController.java @@ -0,0 +1,85 @@ + +package com.neo.controller; + +import com.neo.config.BaseResult; +import com.neo.model.Message; +import com.neo.repository.MessageRepository; +import io.swagger.annotations.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(value = "消息", description = "消息操作 API", position = 100, protocols = "http") +@RestController +@RequestMapping("/") +public class MessageController { + + @Autowired + private MessageRepository messageRepository; + + @ApiOperation( + value = "消息列表", + notes = "完整的消息内容列表", + produces="application/json, application/xml", + consumes="application/json, application/xml", + response = List.class) + @GetMapping(value = "messages") + public List list() { + List messages = this.messageRepository.findAll(); + return messages; + } + + @ApiOperation( + value = "添加消息", + notes = "根据参数创建消息" + ) + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "消息 ID", required = true, dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "text", value = "正文", required = true, dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "summary", value = "摘要", required = false, dataType = "String", paramType = "query"), + }) + @PostMapping(value = "message") + public Message create(Message message) { + System.out.println("message===="+message.toString()); + message = this.messageRepository.save(message); + return message; + } + + @ApiOperation( + value = "修改消息", + notes = "根据参数修改消息" + ) + @PutMapping(value = "message") + @ApiResponses({ + @ApiResponse(code = 100, message = "请求参数有误"), + @ApiResponse(code = 101, message = "未授权"), + @ApiResponse(code = 103, message = "禁止访问"), + @ApiResponse(code = 104, message = "请求路径不存在"), + @ApiResponse(code = 200, message = "服务器内部错误") + }) + public Message modify(Message message) { + Message messageResult=this.messageRepository.update(message); + return messageResult; + } + + @PatchMapping(value="/message/text") + public BaseResult patch(Message message) { + Message messageResult=this.messageRepository.updateText(message); + return BaseResult.successWithData(messageResult); + } + + @GetMapping(value = "message/{id}") + public Message get(@PathVariable Long id) { + Message message = this.messageRepository.findMessage(id); + return message; + } + + @DeleteMapping(value = "message/{id}") + public void delete(@PathVariable("id") Long id) { + this.messageRepository.deleteMessage(id); + } + + + +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/controller/UserController.java b/2.x/spring-boot-swagger/src/main/java/com/neo/controller/UserController.java new file mode 100644 index 000000000..74723d09d --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/controller/UserController.java @@ -0,0 +1,76 @@ +package com.neo.controller; + +import com.neo.config.BaseResult; +import com.neo.model.User; +import io.swagger.annotations.*; +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 springfox.documentation.annotations.ApiIgnore; + +import java.util.*; + + +@Api(value = "用户管理", description = "用户管理API", position = 100, protocols = "http") +@RestController +@RequestMapping(value = "/user") +public class UserController { + static Map users = Collections.synchronizedMap(new HashMap<>()); + + @ApiOperation(value = "获取用户列表", notes = "查询用户列表") + @RequestMapping(value = {""}, method = RequestMethod.GET) + @ApiResponses({ + @ApiResponse(code = 100, message = "异常数据") + }) + public List getUserList() { + return new ArrayList<>(users.values()); + } + + @ApiOperation(value = "创建用户", notes = "根据User对象创建用户") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "ipAddr", value = "ip哟", required = false, dataType = "String", paramType = "query") + }) + @RequestMapping(value = "", method = RequestMethod.POST) + public BaseResult postUser(@ApiIgnore User user) { + users.put(user.getId(), user); + return BaseResult.successWithData(user); + } + + @ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息") + @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path") + @RequestMapping(value = "/{id}", method = RequestMethod.GET) + public User getUser(@PathVariable Long id) { + return users.get(id); + } + + @ApiOperation(value = "更新用户信息", notes = "根据用户ID更新信息") + @ApiImplicitParams({ + @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "query"), + @ApiImplicitParam(name = "name", value = "用户名", required = true, dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "age", value = "年龄", required = true, dataType = "String", paramType = "query") + }) + @RequestMapping(value = "/{id}", method = RequestMethod.PUT) + public BaseResult putUser(@PathVariable Long id, @ApiIgnore User user) { + User u = users.get(id); + u.setName(user.getName()); + u.setAge(user.getAge()); + users.put(id, u); + return BaseResult.successWithData(u); + } + + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + public String deleteUser(@PathVariable Long id) { + users.remove(id); + return "success"; + } + + @RequestMapping(value = "/ignoreMe/{id}", method = RequestMethod.DELETE) + public String ignoreMe(@PathVariable Long id) { + users.remove(id); + return "success"; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/model/Message.java b/2.x/spring-boot-swagger/src/main/java/com/neo/model/Message.java new file mode 100644 index 000000000..c218fffd9 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/model/Message.java @@ -0,0 +1,60 @@ +package com.neo.model; + +import io.swagger.annotations.ApiModelProperty; + +import java.util.Calendar; +import java.util.Date; + +import javax.validation.constraints.NotEmpty; + + +public class Message { + private Long id; + @ApiModelProperty(value = "消息体") + private String text; + @ApiModelProperty(value = "消息总结") + private String summary; + private Date createDate; + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + + public String getSummary() { + return this.summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + + @Override + public String toString() { + return "Message{" + + "id=" + id + + ", text='" + text + '\'' + + ", summary='" + summary + '\'' + + ", createDate=" + createDate + + '}'; + } +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/model/User.java b/2.x/spring-boot-swagger/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..fde335a7d --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/model/User.java @@ -0,0 +1,31 @@ +package com.neo.model; + +public class User { + private Long id; + private String name; + private int age; + + 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; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/repository/InMemoryMessageRepository.java b/2.x/spring-boot-swagger/src/main/java/com/neo/repository/InMemoryMessageRepository.java new file mode 100644 index 000000000..c550ebb50 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/repository/InMemoryMessageRepository.java @@ -0,0 +1,59 @@ +package com.neo.repository; + +import com.neo.model.Message; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; + +@Service("messageRepository") +public class InMemoryMessageRepository implements MessageRepository { + + private static AtomicLong counter = new AtomicLong(); + private final ConcurrentMap messages = new ConcurrentHashMap<>(); + + @Override + public List findAll() { + List messages = new ArrayList(this.messages.values()); + return messages; + } + + @Override + public Message save(Message message) { + Long id = message.getId(); + if (id == null) { + id = counter.incrementAndGet(); + message.setId(id); + } + this.messages.put(id, message); + return message; + } + + @Override + public Message update(Message message) { + this.messages.put(message.getId(), message); + return message; + } + + @Override + public Message updateText(Message message) { + Message msg=this.messages.get(message.getId()); + msg.setText(message.getText()); + this.messages.put(msg.getId(), msg); + return msg; + } + + @Override + public Message findMessage(Long id) { + return this.messages.get(id); + } + + @Override + public void deleteMessage(Long id) { + this.messages.remove(id); + } + +} diff --git a/2.x/spring-boot-swagger/src/main/java/com/neo/repository/MessageRepository.java b/2.x/spring-boot-swagger/src/main/java/com/neo/repository/MessageRepository.java new file mode 100644 index 000000000..99549b5c3 --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/java/com/neo/repository/MessageRepository.java @@ -0,0 +1,22 @@ + +package com.neo.repository; + +import com.neo.model.Message; + +import java.util.List; + +public interface MessageRepository { + + List findAll(); + + Message save(Message message); + + Message update(Message message); + + Message updateText(Message message); + + Message findMessage(Long id); + + void deleteMessage(Long id); + +} diff --git a/2.x/spring-boot-swagger/src/main/resources/application.properties b/2.x/spring-boot-swagger/src/main/resources/application.properties new file mode 100644 index 000000000..a942fc84d --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/resources/application.properties @@ -0,0 +1 @@ +logging.level.io.swagger.models.parameters.AbstractSerializableParameter=error \ No newline at end of file diff --git a/2.x/spring-boot-swagger/src/main/resources/logback.xml b/2.x/spring-boot-swagger/src/main/resources/logback.xml new file mode 100644 index 000000000..620db4a2a --- /dev/null +++ b/2.x/spring-boot-swagger/src/main/resources/logback.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/2.x/spring-boot-swagger/src/test/java/com/neo/SwaggerApplicationTests.java b/2.x/spring-boot-swagger/src/test/java/com/neo/SwaggerApplicationTests.java new file mode 100644 index 000000000..8b6b178c0 --- /dev/null +++ b/2.x/spring-boot-swagger/src/test/java/com/neo/SwaggerApplicationTests.java @@ -0,0 +1,14 @@ + +package com.neo; + + + +import org.junit.Test; + +public class SwaggerApplicationTests { + + @Test + public void test() { + } + +} diff --git a/2.x/spring-boot-swagger/src/test/java/com/neo/web/MessageControllerTest.java b/2.x/spring-boot-swagger/src/test/java/com/neo/web/MessageControllerTest.java new file mode 100644 index 000000000..0aead737a --- /dev/null +++ b/2.x/spring-boot-swagger/src/test/java/com/neo/web/MessageControllerTest.java @@ -0,0 +1,105 @@ +package com.neo.web; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MessageControllerTest { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + saveMessages(); + } + + @Test + public void saveMessage() throws Exception { + final MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("text", "text"); + params.add("summary", "summary"); + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.post("/message") + .params(params)).andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + @Test + public void getAllMessages() throws Exception { + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/messages")) + .andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + @Test + public void getMessage() throws Exception { + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/message/6")) + .andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + @Test + public void modifyMessage() throws Exception { + final MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("id", "6"); + params.add("text", "text"); + params.add("summary", "summary"); + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.put("/message").params(params)) + .andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + @Test + public void patchMessage() throws Exception { + final MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("id", "6"); + params.add("text", "text"); + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.patch("/message/text").params(params)) + .andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + @Test + public void deleteMessage() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.delete("/message/6")) + .andReturn(); + String mvcResult= mockMvc.perform(MockMvcRequestBuilders.get("/messages")) + .andReturn().getResponse().getContentAsString(); + System.out.println("Result === "+mvcResult); + } + + private void saveMessages() { + for (int i=1;i<10;i++){ + final MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("id",""+i); + params.add("text", "text"+i); + params.add("summary", "summary"+i); + try { + MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.post("/message") + .params(params)).andReturn(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + +} diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml new file mode 100644 index 000000000..d44c1050a --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.neo + spring-boot-thymeleaf-layout + 0.0.1-SNAPSHOT + jar + + spring-boot-thymeleaf-layout + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java new file mode 100644 index 000000000..0e4e29af2 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java @@ -0,0 +1,13 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TLayoutApplication { + + public static void main(String[] args) { + SpringApplication.run(TLayoutApplication.class, args); + } + +} diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java new file mode 100644 index 000000000..3b2554172 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java @@ -0,0 +1,31 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class IndexController { + + @RequestMapping("/index") + public String index() { + return "index"; + } + + @RequestMapping("/fragment") + public String fragment() { + return "fragment"; + } + + @RequestMapping("/layout") + public String layout() { + return "layout"; + } + + @RequestMapping("/home") + public String home() { + return "home"; + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties new file mode 100644 index 000000000..975a5172a --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties @@ -0,0 +1,2 @@ +com.neo.title=\u7EAF\u6D01\u7684\u5FAE\u7B11 +com.neo.description=\u5206\u4EAB\u751F\u6D3B\u548C\u6280\u672F \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html new file mode 100644 index 000000000..6a491191e --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html @@ -0,0 +1,15 @@ + + + + comm title + + + + + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html new file mode 100644 index 000000000..bb65abe2e --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html @@ -0,0 +1,11 @@ + + + + Fragment - Page + + + + + + + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html new file mode 100644 index 000000000..bd0de8076 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html @@ -0,0 +1,11 @@ + + + + Home + + +
+

个性化的内容

+
+ + diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html new file mode 100644 index 000000000..40d36573a --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html @@ -0,0 +1,11 @@ + + + + + Index + + +
+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html new file mode 100644 index 000000000..4bc09f3c9 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html @@ -0,0 +1,15 @@ + + + + + Layout + + +
+
+
+
content
+
+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html new file mode 100644 index 000000000..223de9f3e --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html @@ -0,0 +1,12 @@ + + + + + Title + + + + © 2018 + + + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html new file mode 100644 index 000000000..48a9c7def --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html @@ -0,0 +1,12 @@ + + + + + footer + + +
+

我是 尾部

+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html new file mode 100644 index 000000000..adc6b8c67 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html @@ -0,0 +1,12 @@ + + + + + header + + +
+

我是 头部

+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html new file mode 100644 index 000000000..04d887574 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html @@ -0,0 +1,12 @@ + + + + + left + + + +

我是 左侧

+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java new file mode 100644 index 000000000..3e1b0ab0c --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TLayoutApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml new file mode 100644 index 000000000..73702eefb --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + com.neo + spring-boot-thymeleaf + 0.0.1-SNAPSHOT + jar + + spring-boot-thymeleaf + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.0.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java new file mode 100644 index 000000000..e194e8686 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java @@ -0,0 +1,13 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ThymeleafApplication { + + public static void main(String[] args) { + SpringApplication.run(ThymeleafApplication.class, args); + } + +} diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..38e19acc9 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java @@ -0,0 +1,49 @@ +package com.neo.model; + +import org.hibernate.validator.constraints.Length; +import org.hibernate.validator.constraints.NotEmpty; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.Size; + +public class User { + private String name; + private int age; + private String pass; + + public User(String name, int age, String pass) { + this.name = name; + this.age = age; + this.pass = pass; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + @Override + public String toString() { + return ("name=" + this.name + ",age=" + this.age + ",pass=" + this.pass); + } +} diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java new file mode 100644 index 000000000..112760366 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java @@ -0,0 +1,66 @@ +package com.neo.web; + +import com.neo.model.User; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Controller +public class ExampleController { + + @RequestMapping("/string") + public String string(ModelMap map) { + map.addAttribute("userName", "ityouknow"); + return "string"; + } + + @RequestMapping("/if") + public String ifunless(ModelMap map) { + map.addAttribute("flag", "yes"); + return "if"; + } + + @RequestMapping("/list") + public String list(ModelMap map) { + map.addAttribute("users", getUserList()); + return "list"; + } + + @RequestMapping("/url") + public String url(ModelMap map) { + map.addAttribute("type", "link"); + map.addAttribute("pageId", "springcloud/2017/09/11/"); + map.addAttribute("img", "http://www.ityouknow.com/assets/images/neo.jpg"); + return "url"; + } + + @RequestMapping("/eq") + public String eq(ModelMap map) { + map.addAttribute("name", "neo"); + map.addAttribute("age", 30); + map.addAttribute("flag", "yes"); + return "eq"; + } + + @RequestMapping("/switch") + public String switchcase(ModelMap map) { + map.addAttribute("sex", "woman"); + return "switch"; + } + + private List getUserList(){ + List list=new ArrayList(); + User user1=new User("大牛",12,"123456"); + User user2=new User("小牛",6,"123563"); + User user3=new User("纯洁的微笑",66,"666666"); + list.add(user1); + list.add(user2); + list.add(user3); + return list; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..2eac4e8a9 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,16 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class HelloController { + + @RequestMapping("/") + public String index(ModelMap map) { + map.addAttribute("message", "http://www.ityouknow.com"); + return "hello"; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties new file mode 100644 index 000000000..4b9333aa3 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html new file mode 100644 index 000000000..70e65a9fa --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html @@ -0,0 +1,17 @@ + + + + + Example gt eq + + +
+

EQ

+ +
+ +
+ favorites +
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html new file mode 100644 index 000000000..28c51163e --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + + Hello + + +

Hello World

+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html new file mode 100644 index 000000000..9127c233c --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html @@ -0,0 +1,15 @@ + + + + + Example If/Unless + + +
+

If/Unless

+ home +
+ ityouknow +
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html new file mode 100644 index 000000000..017c65e96 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html @@ -0,0 +1,20 @@ + + + + + Example If/Unless + + +
+

for 循环

+ + + + + + + +
neo6213index
+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html new file mode 100644 index 000000000..7a2e3f66d --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html @@ -0,0 +1,16 @@ + + + + + Example String + + +
+

text

+

neo

+ +
+ +
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html new file mode 100644 index 000000000..aef5a3031 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html @@ -0,0 +1,17 @@ + + + + + Example switch + + +
+
+

她是一个姑娘...

+

这是一个爷们!

+ +

未知性别的一个家伙。

+
+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html new file mode 100644 index 000000000..ded52686f --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html @@ -0,0 +1,19 @@ + + + + + Example If/Unless + + +
+

URL

+ link1 +
+ view +
+
+


+
+
+ + \ No newline at end of file diff --git a/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java new file mode 100644 index 000000000..3ccf7f4b9 --- /dev/null +++ b/2.x/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ThymeleafApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/2.x/spring-boot-web-thymeleaf/pom.xml b/2.x/spring-boot-web-thymeleaf/pom.xml new file mode 100644 index 000000000..29d75f28c --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + spring-boot-web-thymeleaf + Spring Boot Web thymeleaf Sample + Spring Boot Web thymeleaf Sample + + + org.springframework.boot + spring-boot-starter-parent + 2.0.0.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java new file mode 100644 index 000000000..3fc821be9 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * 本示例参数于: + * https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-web-ui + */ +package com.neo; + +import com.neo.model.Message; +import com.neo.repository.InMemoryMessageRepository; +import com.neo.repository.MessageRepository; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.core.convert.converter.Converter; + + +@SpringBootApplication +public class ThymeleafApplication { + + @Bean + public MessageRepository messageRepository() { + return new InMemoryMessageRepository(); + } + + @Bean + public Converter messageConverter() { + return new Converter() { + @Override + public Message convert(String id) { + return messageRepository().findMessage(Long.valueOf(id)); + } + }; + } + + public static void main(String[] args) { + SpringApplication.run(ThymeleafApplication.class, args); + } + +} diff --git a/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java new file mode 100644 index 000000000..0f5b33d0b --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java @@ -0,0 +1,72 @@ + +package com.neo.controller; + +import javax.validation.Valid; + +import com.neo.model.Message; +import com.neo.repository.MessageRepository; +import org.springframework.stereotype.Controller; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +@Controller +@RequestMapping("/") +public class MessageController { + + private final MessageRepository messageRepository; + + public MessageController(MessageRepository messageRepository) { + this.messageRepository = messageRepository; + } + + @GetMapping + public ModelAndView list() { + Iterable messages = this.messageRepository.findAll(); + return new ModelAndView("messages/list", "messages", messages); + } + + @GetMapping("{id}") + public ModelAndView view(@PathVariable("id") Message message) { + return new ModelAndView("messages/view", "message", message); + } + + @GetMapping(params = "form") + public String createForm(@ModelAttribute Message message) { + return "messages/form"; + } + + @PostMapping + public ModelAndView create(@Valid Message message, BindingResult result, + RedirectAttributes redirect) { + if (result.hasErrors()) { + return new ModelAndView("messages/form", "formErrors", result.getAllErrors()); + } + message = this.messageRepository.save(message); + redirect.addFlashAttribute("globalMessage", "Successfully created a new message"); + return new ModelAndView("redirect:/{message.id}", "message.id", message.getId()); + } + + @RequestMapping("foo") + public String foo() { + throw new RuntimeException("Expected exception in controller"); + } + + @GetMapping(value = "delete/{id}") + public ModelAndView delete(@PathVariable("id") Long id) { + this.messageRepository.deleteMessage(id); + Iterable messages = this.messageRepository.findAll(); + return new ModelAndView("messages/list", "messages", messages); + } + + @GetMapping(value = "modify/{id}") + public ModelAndView modifyForm(@PathVariable("id") Message message) { + return new ModelAndView("messages/form", "message", message); + } + +} diff --git a/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java new file mode 100644 index 000000000..d4f09e648 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java @@ -0,0 +1,52 @@ +package com.neo.model; + +import java.util.Calendar; + +import javax.validation.constraints.NotEmpty; + + +public class Message { + + private Long id; + + @NotEmpty(message = "Text is required.") + private String text; + + @NotEmpty(message = "Summary is required.") + private String summary; + + private Calendar created = Calendar.getInstance(); + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public Calendar getCreated() { + return this.created; + } + + public void setCreated(Calendar created) { + this.created = created; + } + + public String getText() { + return this.text; + } + + public void setText(String text) { + this.text = text; + } + + public String getSummary() { + return this.summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } + +} diff --git a/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/InMemoryMessageRepository.java b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/InMemoryMessageRepository.java new file mode 100644 index 000000000..185b19711 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/InMemoryMessageRepository.java @@ -0,0 +1,44 @@ + + +package com.neo.repository; + +import com.neo.model.Message; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; + + +public class InMemoryMessageRepository implements MessageRepository { + + private static AtomicLong counter = new AtomicLong(); + + private final ConcurrentMap messages = new ConcurrentHashMap<>(); + + @Override + public Iterable findAll() { + return this.messages.values(); + } + + @Override + public Message save(Message message) { + Long id = message.getId(); + if (id == null) { + id = counter.incrementAndGet(); + message.setId(id); + } + this.messages.put(id, message); + return message; + } + + @Override + public Message findMessage(Long id) { + return this.messages.get(id); + } + + @Override + public void deleteMessage(Long id) { + this.messages.remove(id); + } + +} diff --git a/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/MessageRepository.java b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/MessageRepository.java new file mode 100644 index 000000000..b4830d8bd --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/java/com/neo/repository/MessageRepository.java @@ -0,0 +1,16 @@ + +package com.neo.repository; + +import com.neo.model.Message; + +public interface MessageRepository { + + Iterable findAll(); + + Message save(Message message); + + Message findMessage(Long id); + + void deleteMessage(Long id); + +} diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/application.properties b/2.x/spring-boot-web-thymeleaf/src/main/resources/application.properties new file mode 100644 index 000000000..6665cd62d --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/application.properties @@ -0,0 +1,4 @@ +# Allow Thymeleaf templates to be reloaded at dev time +spring.thymeleaf.cache: false +server.tomcat.access_log_enabled: true +server.tomcat.basedir: target/tomcat \ No newline at end of file diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/logback.xml b/2.x/spring-boot-web-thymeleaf/src/main/resources/logback.xml new file mode 100644 index 000000000..620db4a2a --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/logback.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/static/css/bootstrap.min.css b/2.x/spring-boot-web-thymeleaf/src/main/resources/static/css/bootstrap.min.css new file mode 100644 index 000000000..c814524fe --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/static/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v4.0.0 (https://getbootstrap.com) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-family:inherit;font-weight:500;line-height:1.2;color:inherit}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline-item{display:inline-block}.list-inline-item:not(:last-child){margin-right:.5rem}.initialism{font-size:90%;text-transform:uppercase}.blockquote{margin-bottom:1rem;font-size:1.25rem}.blockquote-footer{display:block;font-size:80%;color:#6c757d}.blockquote-footer::before{content:"\2014 \00A0"}.img-fluid{max-width:100%;height:auto}.img-thumbnail{padding:.25rem;background-color:#fff;border:1px solid #dee2e6;border-radius:.25rem;max-width:100%;height:auto}.figure{display:inline-block}.figure-img{margin-bottom:.5rem;line-height:1}.figure-caption{font-size:90%;color:#6c757d}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}code{font-size:87.5%;color:#e83e8c;word-break:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:87.5%;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:100%;font-weight:700}pre{display:block;font-size:87.5%;color:#212529}pre code{font-size:inherit;color:inherit;word-break:normal}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.table{width:100%;max-width:100%;margin-bottom:1rem;background-color:transparent}.table td,.table th{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6}.table thead th{vertical-align:bottom;border-bottom:2px solid #dee2e6}.table tbody+tbody{border-top:2px solid #dee2e6}.table .table{background-color:#fff}.table-sm td,.table-sm th{padding:.3rem}.table-bordered{border:1px solid #dee2e6}.table-bordered td,.table-bordered th{border:1px solid #dee2e6}.table-bordered thead td,.table-bordered thead th{border-bottom-width:2px}.table-striped tbody tr:nth-of-type(odd){background-color:rgba(0,0,0,.05)}.table-hover tbody tr:hover{background-color:rgba(0,0,0,.075)}.table-primary,.table-primary>td,.table-primary>th{background-color:#b8daff}.table-hover .table-primary:hover{background-color:#9fcdff}.table-hover .table-primary:hover>td,.table-hover .table-primary:hover>th{background-color:#9fcdff}.table-secondary,.table-secondary>td,.table-secondary>th{background-color:#d6d8db}.table-hover .table-secondary:hover{background-color:#c8cbcf}.table-hover .table-secondary:hover>td,.table-hover .table-secondary:hover>th{background-color:#c8cbcf}.table-success,.table-success>td,.table-success>th{background-color:#c3e6cb}.table-hover .table-success:hover{background-color:#b1dfbb}.table-hover .table-success:hover>td,.table-hover .table-success:hover>th{background-color:#b1dfbb}.table-info,.table-info>td,.table-info>th{background-color:#bee5eb}.table-hover .table-info:hover{background-color:#abdde5}.table-hover .table-info:hover>td,.table-hover .table-info:hover>th{background-color:#abdde5}.table-warning,.table-warning>td,.table-warning>th{background-color:#ffeeba}.table-hover .table-warning:hover{background-color:#ffe8a1}.table-hover .table-warning:hover>td,.table-hover .table-warning:hover>th{background-color:#ffe8a1}.table-danger,.table-danger>td,.table-danger>th{background-color:#f5c6cb}.table-hover .table-danger:hover{background-color:#f1b0b7}.table-hover .table-danger:hover>td,.table-hover .table-danger:hover>th{background-color:#f1b0b7}.table-light,.table-light>td,.table-light>th{background-color:#fdfdfe}.table-hover .table-light:hover{background-color:#ececf6}.table-hover .table-light:hover>td,.table-hover .table-light:hover>th{background-color:#ececf6}.table-dark,.table-dark>td,.table-dark>th{background-color:#c6c8ca}.table-hover .table-dark:hover{background-color:#b9bbbe}.table-hover .table-dark:hover>td,.table-hover .table-dark:hover>th{background-color:#b9bbbe}.table-active,.table-active>td,.table-active>th{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover{background-color:rgba(0,0,0,.075)}.table-hover .table-active:hover>td,.table-hover .table-active:hover>th{background-color:rgba(0,0,0,.075)}.table .thead-dark th{color:#fff;background-color:#212529;border-color:#32383e}.table .thead-light th{color:#495057;background-color:#e9ecef;border-color:#dee2e6}.table-dark{color:#fff;background-color:#212529}.table-dark td,.table-dark th,.table-dark thead th{border-color:#32383e}.table-dark.table-bordered{border:0}.table-dark.table-striped tbody tr:nth-of-type(odd){background-color:rgba(255,255,255,.05)}.table-dark.table-hover tbody tr:hover{background-color:rgba(255,255,255,.075)}@media (max-width:575.98px){.table-responsive-sm{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-sm>.table-bordered{border:0}}@media (max-width:767.98px){.table-responsive-md{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-md>.table-bordered{border:0}}@media (max-width:991.98px){.table-responsive-lg{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-lg>.table-bordered{border:0}}@media (max-width:1199.98px){.table-responsive-xl{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive-xl>.table-bordered{border:0}}.table-responsive{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;-ms-overflow-style:-ms-autohiding-scrollbar}.table-responsive>.table-bordered{border:0}.form-control{display:block;width:100%;padding:.375rem .75rem;font-size:1rem;line-height:1.5;color:#495057;background-color:#fff;background-clip:padding-box;border:1px solid #ced4da;border-radius:.25rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.form-control::-ms-expand{background-color:transparent;border:0}.form-control:focus{color:#495057;background-color:#fff;border-color:#80bdff;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.form-control::-webkit-input-placeholder{color:#6c757d;opacity:1}.form-control::-moz-placeholder{color:#6c757d;opacity:1}.form-control:-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::-ms-input-placeholder{color:#6c757d;opacity:1}.form-control::placeholder{color:#6c757d;opacity:1}.form-control:disabled,.form-control[readonly]{background-color:#e9ecef;opacity:1}select.form-control:not([size]):not([multiple]){height:calc(2.25rem + 2px)}select.form-control:focus::-ms-value{color:#495057;background-color:#fff}.form-control-file,.form-control-range{display:block;width:100%}.col-form-label{padding-top:calc(.375rem + 1px);padding-bottom:calc(.375rem + 1px);margin-bottom:0;font-size:inherit;line-height:1.5}.col-form-label-lg{padding-top:calc(.5rem + 1px);padding-bottom:calc(.5rem + 1px);font-size:1.25rem;line-height:1.5}.col-form-label-sm{padding-top:calc(.25rem + 1px);padding-bottom:calc(.25rem + 1px);font-size:.875rem;line-height:1.5}.form-control-plaintext{display:block;width:100%;padding-top:.375rem;padding-bottom:.375rem;margin-bottom:0;line-height:1.5;background-color:transparent;border:solid transparent;border-width:1px 0}.form-control-plaintext.form-control-lg,.form-control-plaintext.form-control-sm,.input-group-lg>.form-control-plaintext.form-control,.input-group-lg>.input-group-append>.form-control-plaintext.btn,.input-group-lg>.input-group-append>.form-control-plaintext.input-group-text,.input-group-lg>.input-group-prepend>.form-control-plaintext.btn,.input-group-lg>.input-group-prepend>.form-control-plaintext.input-group-text,.input-group-sm>.form-control-plaintext.form-control,.input-group-sm>.input-group-append>.form-control-plaintext.btn,.input-group-sm>.input-group-append>.form-control-plaintext.input-group-text,.input-group-sm>.input-group-prepend>.form-control-plaintext.btn,.input-group-sm>.input-group-prepend>.form-control-plaintext.input-group-text{padding-right:0;padding-left:0}.form-control-sm,.input-group-sm>.form-control,.input-group-sm>.input-group-append>.btn,.input-group-sm>.input-group-append>.input-group-text,.input-group-sm>.input-group-prepend>.btn,.input-group-sm>.input-group-prepend>.input-group-text{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.input-group-sm>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-sm>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-sm>select.form-control:not([size]):not([multiple]),select.form-control-sm:not([size]):not([multiple]){height:calc(1.8125rem + 2px)}.form-control-lg,.input-group-lg>.form-control,.input-group-lg>.input-group-append>.btn,.input-group-lg>.input-group-append>.input-group-text,.input-group-lg>.input-group-prepend>.btn,.input-group-lg>.input-group-prepend>.input-group-text{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.input-group-lg>.input-group-append>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-append>select.input-group-text:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.btn:not([size]):not([multiple]),.input-group-lg>.input-group-prepend>select.input-group-text:not([size]):not([multiple]),.input-group-lg>select.form-control:not([size]):not([multiple]),select.form-control-lg:not([size]):not([multiple]){height:calc(2.875rem + 2px)}.form-group{margin-bottom:1rem}.form-text{display:block;margin-top:.25rem}.form-row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-5px;margin-left:-5px}.form-row>.col,.form-row>[class*=col-]{padding-right:5px;padding-left:5px}.form-check{position:relative;display:block;padding-left:1.25rem}.form-check-input{position:absolute;margin-top:.3rem;margin-left:-1.25rem}.form-check-input:disabled~.form-check-label{color:#6c757d}.form-check-label{margin-bottom:0}.form-check-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-left:0;margin-right:.75rem}.form-check-inline .form-check-input{position:static;margin-top:0;margin-right:.3125rem;margin-left:0}.valid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#28a745}.valid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.5rem;margin-top:.1rem;font-size:.875rem;line-height:1;color:#fff;background-color:rgba(40,167,69,.8);border-radius:.2rem}.custom-select.is-valid,.form-control.is-valid,.was-validated .custom-select:valid,.was-validated .form-control:valid{border-color:#28a745}.custom-select.is-valid:focus,.form-control.is-valid:focus,.was-validated .custom-select:valid:focus,.was-validated .form-control:valid:focus{border-color:#28a745;box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.custom-select.is-valid~.valid-feedback,.custom-select.is-valid~.valid-tooltip,.form-control.is-valid~.valid-feedback,.form-control.is-valid~.valid-tooltip,.was-validated .custom-select:valid~.valid-feedback,.was-validated .custom-select:valid~.valid-tooltip,.was-validated .form-control:valid~.valid-feedback,.was-validated .form-control:valid~.valid-tooltip{display:block}.form-check-input.is-valid~.form-check-label,.was-validated .form-check-input:valid~.form-check-label{color:#28a745}.form-check-input.is-valid~.valid-feedback,.form-check-input.is-valid~.valid-tooltip,.was-validated .form-check-input:valid~.valid-feedback,.was-validated .form-check-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid~.custom-control-label,.was-validated .custom-control-input:valid~.custom-control-label{color:#28a745}.custom-control-input.is-valid~.custom-control-label::before,.was-validated .custom-control-input:valid~.custom-control-label::before{background-color:#71dd8a}.custom-control-input.is-valid~.valid-feedback,.custom-control-input.is-valid~.valid-tooltip,.was-validated .custom-control-input:valid~.valid-feedback,.was-validated .custom-control-input:valid~.valid-tooltip{display:block}.custom-control-input.is-valid:checked~.custom-control-label::before,.was-validated .custom-control-input:valid:checked~.custom-control-label::before{background-color:#34ce57}.custom-control-input.is-valid:focus~.custom-control-label::before,.was-validated .custom-control-input:valid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(40,167,69,.25)}.custom-file-input.is-valid~.custom-file-label,.was-validated .custom-file-input:valid~.custom-file-label{border-color:#28a745}.custom-file-input.is-valid~.custom-file-label::before,.was-validated .custom-file-input:valid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-valid~.valid-feedback,.custom-file-input.is-valid~.valid-tooltip,.was-validated .custom-file-input:valid~.valid-feedback,.was-validated .custom-file-input:valid~.valid-tooltip{display:block}.custom-file-input.is-valid:focus~.custom-file-label,.was-validated .custom-file-input:valid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(40,167,69,.25)}.invalid-feedback{display:none;width:100%;margin-top:.25rem;font-size:80%;color:#dc3545}.invalid-tooltip{position:absolute;top:100%;z-index:5;display:none;max-width:100%;padding:.5rem;margin-top:.1rem;font-size:.875rem;line-height:1;color:#fff;background-color:rgba(220,53,69,.8);border-radius:.2rem}.custom-select.is-invalid,.form-control.is-invalid,.was-validated .custom-select:invalid,.was-validated .form-control:invalid{border-color:#dc3545}.custom-select.is-invalid:focus,.form-control.is-invalid:focus,.was-validated .custom-select:invalid:focus,.was-validated .form-control:invalid:focus{border-color:#dc3545;box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.custom-select.is-invalid~.invalid-feedback,.custom-select.is-invalid~.invalid-tooltip,.form-control.is-invalid~.invalid-feedback,.form-control.is-invalid~.invalid-tooltip,.was-validated .custom-select:invalid~.invalid-feedback,.was-validated .custom-select:invalid~.invalid-tooltip,.was-validated .form-control:invalid~.invalid-feedback,.was-validated .form-control:invalid~.invalid-tooltip{display:block}.form-check-input.is-invalid~.form-check-label,.was-validated .form-check-input:invalid~.form-check-label{color:#dc3545}.form-check-input.is-invalid~.invalid-feedback,.form-check-input.is-invalid~.invalid-tooltip,.was-validated .form-check-input:invalid~.invalid-feedback,.was-validated .form-check-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid~.custom-control-label,.was-validated .custom-control-input:invalid~.custom-control-label{color:#dc3545}.custom-control-input.is-invalid~.custom-control-label::before,.was-validated .custom-control-input:invalid~.custom-control-label::before{background-color:#efa2a9}.custom-control-input.is-invalid~.invalid-feedback,.custom-control-input.is-invalid~.invalid-tooltip,.was-validated .custom-control-input:invalid~.invalid-feedback,.was-validated .custom-control-input:invalid~.invalid-tooltip{display:block}.custom-control-input.is-invalid:checked~.custom-control-label::before,.was-validated .custom-control-input:invalid:checked~.custom-control-label::before{background-color:#e4606d}.custom-control-input.is-invalid:focus~.custom-control-label::before,.was-validated .custom-control-input:invalid:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(220,53,69,.25)}.custom-file-input.is-invalid~.custom-file-label,.was-validated .custom-file-input:invalid~.custom-file-label{border-color:#dc3545}.custom-file-input.is-invalid~.custom-file-label::before,.was-validated .custom-file-input:invalid~.custom-file-label::before{border-color:inherit}.custom-file-input.is-invalid~.invalid-feedback,.custom-file-input.is-invalid~.invalid-tooltip,.was-validated .custom-file-input:invalid~.invalid-feedback,.was-validated .custom-file-input:invalid~.invalid-tooltip{display:block}.custom-file-input.is-invalid:focus~.custom-file-label,.was-validated .custom-file-input:invalid:focus~.custom-file-label{box-shadow:0 0 0 .2rem rgba(220,53,69,.25)}.form-inline{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.form-inline .form-check{width:100%}@media (min-width:576px){.form-inline label{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;margin-bottom:0}.form-inline .form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:0}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-plaintext{display:inline-block}.form-inline .input-group{width:auto}.form-inline .form-check{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:auto;padding-left:0}.form-inline .form-check-input{position:relative;margin-top:0;margin-right:.25rem;margin-left:0}.form-inline .custom-control{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.form-inline .custom-control-label{margin-bottom:0}}.btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;padding:.375rem .75rem;font-size:1rem;line-height:1.5;border-radius:.25rem;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out}.btn:focus,.btn:hover{text-decoration:none}.btn.focus,.btn:focus{outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.btn.disabled,.btn:disabled{opacity:.65}.btn:not(:disabled):not(.disabled){cursor:pointer}.btn:not(:disabled):not(.disabled).active,.btn:not(:disabled):not(.disabled):active{background-image:none}a.btn.disabled,fieldset:disabled a.btn{pointer-events:none}.btn-primary{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:hover{color:#fff;background-color:#0069d9;border-color:#0062cc}.btn-primary.focus,.btn-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-primary.disabled,.btn-primary:disabled{color:#fff;background-color:#007bff;border-color:#007bff}.btn-primary:not(:disabled):not(.disabled).active,.btn-primary:not(:disabled):not(.disabled):active,.show>.btn-primary.dropdown-toggle{color:#fff;background-color:#0062cc;border-color:#005cbf}.btn-primary:not(:disabled):not(.disabled).active:focus,.btn-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-secondary{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:hover{color:#fff;background-color:#5a6268;border-color:#545b62}.btn-secondary.focus,.btn-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-secondary.disabled,.btn-secondary:disabled{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-secondary:not(:disabled):not(.disabled).active,.btn-secondary:not(:disabled):not(.disabled):active,.show>.btn-secondary.dropdown-toggle{color:#fff;background-color:#545b62;border-color:#4e555b}.btn-secondary:not(:disabled):not(.disabled).active:focus,.btn-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-success{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:hover{color:#fff;background-color:#218838;border-color:#1e7e34}.btn-success.focus,.btn-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-success.disabled,.btn-success:disabled{color:#fff;background-color:#28a745;border-color:#28a745}.btn-success:not(:disabled):not(.disabled).active,.btn-success:not(:disabled):not(.disabled):active,.show>.btn-success.dropdown-toggle{color:#fff;background-color:#1e7e34;border-color:#1c7430}.btn-success:not(:disabled):not(.disabled).active:focus,.btn-success:not(:disabled):not(.disabled):active:focus,.show>.btn-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-info{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:hover{color:#fff;background-color:#138496;border-color:#117a8b}.btn-info.focus,.btn-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-info.disabled,.btn-info:disabled{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-info:not(:disabled):not(.disabled).active,.btn-info:not(:disabled):not(.disabled):active,.show>.btn-info.dropdown-toggle{color:#fff;background-color:#117a8b;border-color:#10707f}.btn-info:not(:disabled):not(.disabled).active:focus,.btn-info:not(:disabled):not(.disabled):active:focus,.show>.btn-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-warning{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:hover{color:#212529;background-color:#e0a800;border-color:#d39e00}.btn-warning.focus,.btn-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-warning.disabled,.btn-warning:disabled{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-warning:not(:disabled):not(.disabled).active,.btn-warning:not(:disabled):not(.disabled):active,.show>.btn-warning.dropdown-toggle{color:#212529;background-color:#d39e00;border-color:#c69500}.btn-warning:not(:disabled):not(.disabled).active:focus,.btn-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-danger{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:hover{color:#fff;background-color:#c82333;border-color:#bd2130}.btn-danger.focus,.btn-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-danger.disabled,.btn-danger:disabled{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-danger:not(:disabled):not(.disabled).active,.btn-danger:not(:disabled):not(.disabled):active,.show>.btn-danger.dropdown-toggle{color:#fff;background-color:#bd2130;border-color:#b21f2d}.btn-danger:not(:disabled):not(.disabled).active:focus,.btn-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-light{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:hover{color:#212529;background-color:#e2e6ea;border-color:#dae0e5}.btn-light.focus,.btn-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-light.disabled,.btn-light:disabled{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-light:not(:disabled):not(.disabled).active,.btn-light:not(:disabled):not(.disabled):active,.show>.btn-light.dropdown-toggle{color:#212529;background-color:#dae0e5;border-color:#d3d9df}.btn-light:not(:disabled):not(.disabled).active:focus,.btn-light:not(:disabled):not(.disabled):active:focus,.show>.btn-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-dark{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:hover{color:#fff;background-color:#23272b;border-color:#1d2124}.btn-dark.focus,.btn-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-dark.disabled,.btn-dark:disabled{color:#fff;background-color:#343a40;border-color:#343a40}.btn-dark:not(:disabled):not(.disabled).active,.btn-dark:not(:disabled):not(.disabled):active,.show>.btn-dark.dropdown-toggle{color:#fff;background-color:#1d2124;border-color:#171a1d}.btn-dark:not(:disabled):not(.disabled).active:focus,.btn-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-primary{color:#007bff;background-color:transparent;background-image:none;border-color:#007bff}.btn-outline-primary:hover{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary.focus,.btn-outline-primary:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-primary.disabled,.btn-outline-primary:disabled{color:#007bff;background-color:transparent}.btn-outline-primary:not(:disabled):not(.disabled).active,.btn-outline-primary:not(:disabled):not(.disabled):active,.show>.btn-outline-primary.dropdown-toggle{color:#fff;background-color:#007bff;border-color:#007bff}.btn-outline-primary:not(:disabled):not(.disabled).active:focus,.btn-outline-primary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-primary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(0,123,255,.5)}.btn-outline-secondary{color:#6c757d;background-color:transparent;background-image:none;border-color:#6c757d}.btn-outline-secondary:hover{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary.focus,.btn-outline-secondary:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-secondary.disabled,.btn-outline-secondary:disabled{color:#6c757d;background-color:transparent}.btn-outline-secondary:not(:disabled):not(.disabled).active,.btn-outline-secondary:not(:disabled):not(.disabled):active,.show>.btn-outline-secondary.dropdown-toggle{color:#fff;background-color:#6c757d;border-color:#6c757d}.btn-outline-secondary:not(:disabled):not(.disabled).active:focus,.btn-outline-secondary:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-secondary.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(108,117,125,.5)}.btn-outline-success{color:#28a745;background-color:transparent;background-image:none;border-color:#28a745}.btn-outline-success:hover{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success.focus,.btn-outline-success:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-success.disabled,.btn-outline-success:disabled{color:#28a745;background-color:transparent}.btn-outline-success:not(:disabled):not(.disabled).active,.btn-outline-success:not(:disabled):not(.disabled):active,.show>.btn-outline-success.dropdown-toggle{color:#fff;background-color:#28a745;border-color:#28a745}.btn-outline-success:not(:disabled):not(.disabled).active:focus,.btn-outline-success:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-success.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(40,167,69,.5)}.btn-outline-info{color:#17a2b8;background-color:transparent;background-image:none;border-color:#17a2b8}.btn-outline-info:hover{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info.focus,.btn-outline-info:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-info.disabled,.btn-outline-info:disabled{color:#17a2b8;background-color:transparent}.btn-outline-info:not(:disabled):not(.disabled).active,.btn-outline-info:not(:disabled):not(.disabled):active,.show>.btn-outline-info.dropdown-toggle{color:#fff;background-color:#17a2b8;border-color:#17a2b8}.btn-outline-info:not(:disabled):not(.disabled).active:focus,.btn-outline-info:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-info.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(23,162,184,.5)}.btn-outline-warning{color:#ffc107;background-color:transparent;background-image:none;border-color:#ffc107}.btn-outline-warning:hover{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning.focus,.btn-outline-warning:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-warning.disabled,.btn-outline-warning:disabled{color:#ffc107;background-color:transparent}.btn-outline-warning:not(:disabled):not(.disabled).active,.btn-outline-warning:not(:disabled):not(.disabled):active,.show>.btn-outline-warning.dropdown-toggle{color:#212529;background-color:#ffc107;border-color:#ffc107}.btn-outline-warning:not(:disabled):not(.disabled).active:focus,.btn-outline-warning:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-warning.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(255,193,7,.5)}.btn-outline-danger{color:#dc3545;background-color:transparent;background-image:none;border-color:#dc3545}.btn-outline-danger:hover{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger.focus,.btn-outline-danger:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-danger.disabled,.btn-outline-danger:disabled{color:#dc3545;background-color:transparent}.btn-outline-danger:not(:disabled):not(.disabled).active,.btn-outline-danger:not(:disabled):not(.disabled):active,.show>.btn-outline-danger.dropdown-toggle{color:#fff;background-color:#dc3545;border-color:#dc3545}.btn-outline-danger:not(:disabled):not(.disabled).active:focus,.btn-outline-danger:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-danger.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(220,53,69,.5)}.btn-outline-light{color:#f8f9fa;background-color:transparent;background-image:none;border-color:#f8f9fa}.btn-outline-light:hover{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light.focus,.btn-outline-light:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-light.disabled,.btn-outline-light:disabled{color:#f8f9fa;background-color:transparent}.btn-outline-light:not(:disabled):not(.disabled).active,.btn-outline-light:not(:disabled):not(.disabled):active,.show>.btn-outline-light.dropdown-toggle{color:#212529;background-color:#f8f9fa;border-color:#f8f9fa}.btn-outline-light:not(:disabled):not(.disabled).active:focus,.btn-outline-light:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-light.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(248,249,250,.5)}.btn-outline-dark{color:#343a40;background-color:transparent;background-image:none;border-color:#343a40}.btn-outline-dark:hover{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark.focus,.btn-outline-dark:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-outline-dark.disabled,.btn-outline-dark:disabled{color:#343a40;background-color:transparent}.btn-outline-dark:not(:disabled):not(.disabled).active,.btn-outline-dark:not(:disabled):not(.disabled):active,.show>.btn-outline-dark.dropdown-toggle{color:#fff;background-color:#343a40;border-color:#343a40}.btn-outline-dark:not(:disabled):not(.disabled).active:focus,.btn-outline-dark:not(:disabled):not(.disabled):active:focus,.show>.btn-outline-dark.dropdown-toggle:focus{box-shadow:0 0 0 .2rem rgba(52,58,64,.5)}.btn-link{font-weight:400;color:#007bff;background-color:transparent}.btn-link:hover{color:#0056b3;text-decoration:underline;background-color:transparent;border-color:transparent}.btn-link.focus,.btn-link:focus{text-decoration:underline;border-color:transparent;box-shadow:none}.btn-link.disabled,.btn-link:disabled{color:#6c757d}.btn-group-lg>.btn,.btn-lg{padding:.5rem 1rem;font-size:1.25rem;line-height:1.5;border-radius:.3rem}.btn-group-sm>.btn,.btn-sm{padding:.25rem .5rem;font-size:.875rem;line-height:1.5;border-radius:.2rem}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:.5rem}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;transition:opacity .15s linear}.fade.show{opacity:1}.collapse{display:none}.collapse.show{display:block}tr.collapse.show{display:table-row}tbody.collapse.show{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;transition:height .35s ease}.dropdown,.dropup{position:relative}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-bottom:0;border-left:.3em solid transparent}.dropdown-toggle:empty::after{margin-left:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:10rem;padding:.5rem 0;margin:.125rem 0 0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.dropup .dropdown-menu{margin-top:0;margin-bottom:.125rem}.dropup .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:0;border-right:.3em solid transparent;border-bottom:.3em solid;border-left:.3em solid transparent}.dropup .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-menu{margin-top:0;margin-left:.125rem}.dropright .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-bottom:.3em solid transparent;border-left:.3em solid}.dropright .dropdown-toggle:empty::after{margin-left:0}.dropright .dropdown-toggle::after{vertical-align:0}.dropleft .dropdown-menu{margin-top:0;margin-right:.125rem}.dropleft .dropdown-toggle::after{display:inline-block;width:0;height:0;margin-left:.255em;vertical-align:.255em;content:""}.dropleft .dropdown-toggle::after{display:none}.dropleft .dropdown-toggle::before{display:inline-block;width:0;height:0;margin-right:.255em;vertical-align:.255em;content:"";border-top:.3em solid transparent;border-right:.3em solid;border-bottom:.3em solid transparent}.dropleft .dropdown-toggle:empty::after{margin-left:0}.dropleft .dropdown-toggle::before{vertical-align:0}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid #e9ecef}.dropdown-item{display:block;width:100%;padding:.25rem 1.5rem;clear:both;font-weight:400;color:#212529;text-align:inherit;white-space:nowrap;background-color:transparent;border:0}.dropdown-item:focus,.dropdown-item:hover{color:#16181b;text-decoration:none;background-color:#f8f9fa}.dropdown-item.active,.dropdown-item:active{color:#fff;text-decoration:none;background-color:#007bff}.dropdown-item.disabled,.dropdown-item:disabled{color:#6c757d;background-color:transparent}.dropdown-menu.show{display:block}.dropdown-header{display:block;padding:.5rem 1.5rem;margin-bottom:0;font-size:.875rem;color:#6c757d;white-space:nowrap}.btn-group,.btn-group-vertical{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.btn-group-vertical>.btn:hover,.btn-group>.btn:hover{z-index:1}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus{z-index:1}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group,.btn-group-vertical .btn+.btn,.btn-group-vertical .btn+.btn-group,.btn-group-vertical .btn-group+.btn,.btn-group-vertical .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.btn-toolbar .input-group{width:auto}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn-group:not(:last-child)>.btn,.btn-group>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:not(:first-child)>.btn,.btn-group>.btn:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-toggle-split{padding-right:.5625rem;padding-left:.5625rem}.dropdown-toggle-split::after{margin-left:0}.btn-group-sm>.btn+.dropdown-toggle-split,.btn-sm+.dropdown-toggle-split{padding-right:.375rem;padding-left:.375rem}.btn-group-lg>.btn+.dropdown-toggle-split,.btn-lg+.dropdown-toggle-split{padding-right:.75rem;padding-left:.75rem}.btn-group-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.btn-group-vertical .btn,.btn-group-vertical .btn-group{width:100%}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn-group:not(:last-child)>.btn,.btn-group-vertical>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child)>.btn,.btn-group-vertical>.btn:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}.btn-group-toggle>.btn,.btn-group-toggle>.btn-group>.btn{margin-bottom:0}.btn-group-toggle>.btn input[type=checkbox],.btn-group-toggle>.btn input[type=radio],.btn-group-toggle>.btn-group>.btn input[type=checkbox],.btn-group-toggle>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;width:100%}.input-group>.custom-file,.input-group>.custom-select,.input-group>.form-control{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:1%;margin-bottom:0}.input-group>.custom-file:focus,.input-group>.custom-select:focus,.input-group>.form-control:focus{z-index:3}.input-group>.custom-file+.custom-file,.input-group>.custom-file+.custom-select,.input-group>.custom-file+.form-control,.input-group>.custom-select+.custom-file,.input-group>.custom-select+.custom-select,.input-group>.custom-select+.form-control,.input-group>.form-control+.custom-file,.input-group>.form-control+.custom-select,.input-group>.form-control+.form-control{margin-left:-1px}.input-group>.custom-select:not(:last-child),.input-group>.form-control:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-select:not(:first-child),.input-group>.form-control:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.input-group>.custom-file{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.input-group>.custom-file:not(:last-child) .custom-file-label,.input-group>.custom-file:not(:last-child) .custom-file-label::before{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.custom-file:not(:first-child) .custom-file-label,.input-group>.custom-file:not(:first-child) .custom-file-label::before{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-append,.input-group-prepend{display:-webkit-box;display:-ms-flexbox;display:flex}.input-group-append .btn,.input-group-prepend .btn{position:relative;z-index:2}.input-group-append .btn+.btn,.input-group-append .btn+.input-group-text,.input-group-append .input-group-text+.btn,.input-group-append .input-group-text+.input-group-text,.input-group-prepend .btn+.btn,.input-group-prepend .btn+.input-group-text,.input-group-prepend .input-group-text+.btn,.input-group-prepend .input-group-text+.input-group-text{margin-left:-1px}.input-group-prepend{margin-right:-1px}.input-group-append{margin-left:-1px}.input-group-text{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.375rem .75rem;margin-bottom:0;font-size:1rem;font-weight:400;line-height:1.5;color:#495057;text-align:center;white-space:nowrap;background-color:#e9ecef;border:1px solid #ced4da;border-radius:.25rem}.input-group-text input[type=checkbox],.input-group-text input[type=radio]{margin-top:0}.input-group>.input-group-append:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group>.input-group-append:last-child>.input-group-text:not(:last-child),.input-group>.input-group-append:not(:last-child)>.btn,.input-group>.input-group-append:not(:last-child)>.input-group-text,.input-group>.input-group-prepend>.btn,.input-group>.input-group-prepend>.input-group-text{border-top-right-radius:0;border-bottom-right-radius:0}.input-group>.input-group-append>.btn,.input-group>.input-group-append>.input-group-text,.input-group>.input-group-prepend:first-child>.btn:not(:first-child),.input-group>.input-group-prepend:first-child>.input-group-text:not(:first-child),.input-group>.input-group-prepend:not(:first-child)>.btn,.input-group>.input-group-prepend:not(:first-child)>.input-group-text{border-top-left-radius:0;border-bottom-left-radius:0}.custom-control{position:relative;display:block;min-height:1.5rem;padding-left:1.5rem}.custom-control-inline{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;margin-right:1rem}.custom-control-input{position:absolute;z-index:-1;opacity:0}.custom-control-input:checked~.custom-control-label::before{color:#fff;background-color:#007bff}.custom-control-input:focus~.custom-control-label::before{box-shadow:0 0 0 1px #fff,0 0 0 .2rem rgba(0,123,255,.25)}.custom-control-input:active~.custom-control-label::before{color:#fff;background-color:#b3d7ff}.custom-control-input:disabled~.custom-control-label{color:#6c757d}.custom-control-input:disabled~.custom-control-label::before{background-color:#e9ecef}.custom-control-label{margin-bottom:0}.custom-control-label::before{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;pointer-events:none;content:"";-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-color:#dee2e6}.custom-control-label::after{position:absolute;top:.25rem;left:0;display:block;width:1rem;height:1rem;content:"";background-repeat:no-repeat;background-position:center center;background-size:50% 50%}.custom-checkbox .custom-control-label::before{border-radius:.25rem}.custom-checkbox .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-checkbox .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::before{background-color:#007bff}.custom-checkbox .custom-control-input:indeterminate~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E")}.custom-checkbox .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-checkbox .custom-control-input:disabled:indeterminate~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-radio .custom-control-label::before{border-radius:50%}.custom-radio .custom-control-input:checked~.custom-control-label::before{background-color:#007bff}.custom-radio .custom-control-input:checked~.custom-control-label::after{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E")}.custom-radio .custom-control-input:disabled:checked~.custom-control-label::before{background-color:rgba(0,123,255,.5)}.custom-select{display:inline-block;width:100%;height:calc(2.25rem + 2px);padding:.375rem 1.75rem .375rem .75rem;line-height:1.5;color:#495057;vertical-align:middle;background:#fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right .75rem center;background-size:8px 10px;border:1px solid #ced4da;border-radius:.25rem;-webkit-appearance:none;-moz-appearance:none;appearance:none}.custom-select:focus{border-color:#80bdff;outline:0;box-shadow:inset 0 1px 2px rgba(0,0,0,.075),0 0 5px rgba(128,189,255,.5)}.custom-select:focus::-ms-value{color:#495057;background-color:#fff}.custom-select[multiple],.custom-select[size]:not([size="1"]){height:auto;padding-right:.75rem;background-image:none}.custom-select:disabled{color:#6c757d;background-color:#e9ecef}.custom-select::-ms-expand{opacity:0}.custom-select-sm{height:calc(1.8125rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:75%}.custom-select-lg{height:calc(2.875rem + 2px);padding-top:.375rem;padding-bottom:.375rem;font-size:125%}.custom-file{position:relative;display:inline-block;width:100%;height:calc(2.25rem + 2px);margin-bottom:0}.custom-file-input{position:relative;z-index:2;width:100%;height:calc(2.25rem + 2px);margin:0;opacity:0}.custom-file-input:focus~.custom-file-control{border-color:#80bdff;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.custom-file-input:focus~.custom-file-control::before{border-color:#80bdff}.custom-file-input:lang(en)~.custom-file-label::after{content:"Browse"}.custom-file-label{position:absolute;top:0;right:0;left:0;z-index:1;height:calc(2.25rem + 2px);padding:.375rem .75rem;line-height:1.5;color:#495057;background-color:#fff;border:1px solid #ced4da;border-radius:.25rem}.custom-file-label::after{position:absolute;top:0;right:0;bottom:0;z-index:3;display:block;height:calc(calc(2.25rem + 2px) - 1px * 2);padding:.375rem .75rem;line-height:1.5;color:#495057;content:"Browse";background-color:#e9ecef;border-left:1px solid #ced4da;border-radius:0 .25rem .25rem 0}.nav{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-left:0;margin-bottom:0;list-style:none}.nav-link{display:block;padding:.5rem 1rem}.nav-link:focus,.nav-link:hover{text-decoration:none}.nav-link.disabled{color:#6c757d}.nav-tabs{border-bottom:1px solid #dee2e6}.nav-tabs .nav-item{margin-bottom:-1px}.nav-tabs .nav-link{border:1px solid transparent;border-top-left-radius:.25rem;border-top-right-radius:.25rem}.nav-tabs .nav-link:focus,.nav-tabs .nav-link:hover{border-color:#e9ecef #e9ecef #dee2e6}.nav-tabs .nav-link.disabled{color:#6c757d;background-color:transparent;border-color:transparent}.nav-tabs .nav-item.show .nav-link,.nav-tabs .nav-link.active{color:#495057;background-color:#fff;border-color:#dee2e6 #dee2e6 #fff}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.nav-pills .nav-link{border-radius:.25rem}.nav-pills .nav-link.active,.nav-pills .show>.nav-link{color:#fff;background-color:#007bff}.nav-fill .nav-item{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;text-align:center}.nav-justified .nav-item{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;text-align:center}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.navbar{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:.5rem 1rem}.navbar>.container,.navbar>.container-fluid{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.navbar-brand{display:inline-block;padding-top:.3125rem;padding-bottom:.3125rem;margin-right:1rem;font-size:1.25rem;line-height:inherit;white-space:nowrap}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-nav{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0;list-style:none}.navbar-nav .nav-link{padding-right:0;padding-left:0}.navbar-nav .dropdown-menu{position:static;float:none}.navbar-text{display:inline-block;padding-top:.5rem;padding-bottom:.5rem}.navbar-collapse{-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.navbar-toggler{padding:.25rem .75rem;font-size:1.25rem;line-height:1;background-color:transparent;border:1px solid transparent;border-radius:.25rem}.navbar-toggler:focus,.navbar-toggler:hover{text-decoration:none}.navbar-toggler:not(:disabled):not(.disabled){cursor:pointer}.navbar-toggler-icon{display:inline-block;width:1.5em;height:1.5em;vertical-align:middle;content:"";background:no-repeat center center;background-size:100% 100%}@media (max-width:575.98px){.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:576px){.navbar-expand-sm{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-sm .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-sm .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-sm .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-sm .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-sm>.container,.navbar-expand-sm>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-sm .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-sm .navbar-toggler{display:none}.navbar-expand-sm .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:767.98px){.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:768px){.navbar-expand-md{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-md .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-md .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-md .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-md .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-md>.container,.navbar-expand-md>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-md .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-md .navbar-toggler{display:none}.navbar-expand-md .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:991.98px){.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:992px){.navbar-expand-lg{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-lg .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-lg .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-lg .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-lg .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-lg>.container,.navbar-expand-lg>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-lg .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-lg .navbar-toggler{display:none}.navbar-expand-lg .dropup .dropdown-menu{top:auto;bottom:100%}}@media (max-width:1199.98px){.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{padding-right:0;padding-left:0}}@media (min-width:1200px){.navbar-expand-xl{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand-xl .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand-xl .navbar-nav .dropdown-menu{position:absolute}.navbar-expand-xl .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand-xl .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand-xl>.container,.navbar-expand-xl>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand-xl .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand-xl .navbar-toggler{display:none}.navbar-expand-xl .dropup .dropdown-menu{top:auto;bottom:100%}}.navbar-expand{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.navbar-expand>.container,.navbar-expand>.container-fluid{padding-right:0;padding-left:0}.navbar-expand .navbar-nav{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.navbar-expand .navbar-nav .dropdown-menu{position:absolute}.navbar-expand .navbar-nav .dropdown-menu-right{right:0;left:auto}.navbar-expand .navbar-nav .nav-link{padding-right:.5rem;padding-left:.5rem}.navbar-expand>.container,.navbar-expand>.container-fluid{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.navbar-expand .navbar-collapse{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-preferred-size:auto;flex-basis:auto}.navbar-expand .navbar-toggler{display:none}.navbar-expand .dropup .dropdown-menu{top:auto;bottom:100%}.navbar-light .navbar-brand{color:rgba(0,0,0,.9)}.navbar-light .navbar-brand:focus,.navbar-light .navbar-brand:hover{color:rgba(0,0,0,.9)}.navbar-light .navbar-nav .nav-link{color:rgba(0,0,0,.5)}.navbar-light .navbar-nav .nav-link:focus,.navbar-light .navbar-nav .nav-link:hover{color:rgba(0,0,0,.7)}.navbar-light .navbar-nav .nav-link.disabled{color:rgba(0,0,0,.3)}.navbar-light .navbar-nav .active>.nav-link,.navbar-light .navbar-nav .nav-link.active,.navbar-light .navbar-nav .nav-link.show,.navbar-light .navbar-nav .show>.nav-link{color:rgba(0,0,0,.9)}.navbar-light .navbar-toggler{color:rgba(0,0,0,.5);border-color:rgba(0,0,0,.1)}.navbar-light .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-light .navbar-text{color:rgba(0,0,0,.5)}.navbar-light .navbar-text a{color:rgba(0,0,0,.9)}.navbar-light .navbar-text a:focus,.navbar-light .navbar-text a:hover{color:rgba(0,0,0,.9)}.navbar-dark .navbar-brand{color:#fff}.navbar-dark .navbar-brand:focus,.navbar-dark .navbar-brand:hover{color:#fff}.navbar-dark .navbar-nav .nav-link{color:rgba(255,255,255,.5)}.navbar-dark .navbar-nav .nav-link:focus,.navbar-dark .navbar-nav .nav-link:hover{color:rgba(255,255,255,.75)}.navbar-dark .navbar-nav .nav-link.disabled{color:rgba(255,255,255,.25)}.navbar-dark .navbar-nav .active>.nav-link,.navbar-dark .navbar-nav .nav-link.active,.navbar-dark .navbar-nav .nav-link.show,.navbar-dark .navbar-nav .show>.nav-link{color:#fff}.navbar-dark .navbar-toggler{color:rgba(255,255,255,.5);border-color:rgba(255,255,255,.1)}.navbar-dark .navbar-toggler-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E")}.navbar-dark .navbar-text{color:rgba(255,255,255,.5)}.navbar-dark .navbar-text a{color:#fff}.navbar-dark .navbar-text a:focus,.navbar-dark .navbar-text a:hover{color:#fff}.card{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-width:0;word-wrap:break-word;background-color:#fff;background-clip:border-box;border:1px solid rgba(0,0,0,.125);border-radius:.25rem}.card>hr{margin-right:0;margin-left:0}.card>.list-group:first-child .list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1.25rem}.card-title{margin-bottom:.75rem}.card-subtitle{margin-top:-.375rem;margin-bottom:0}.card-text:last-child{margin-bottom:0}.card-link:hover{text-decoration:none}.card-link+.card-link{margin-left:1.25rem}.card-header{padding:.75rem 1.25rem;margin-bottom:0;background-color:rgba(0,0,0,.03);border-bottom:1px solid rgba(0,0,0,.125)}.card-header:first-child{border-radius:calc(.25rem - 1px) calc(.25rem - 1px) 0 0}.card-header+.list-group .list-group-item:first-child{border-top:0}.card-footer{padding:.75rem 1.25rem;background-color:rgba(0,0,0,.03);border-top:1px solid rgba(0,0,0,.125)}.card-footer:last-child{border-radius:0 0 calc(.25rem - 1px) calc(.25rem - 1px)}.card-header-tabs{margin-right:-.625rem;margin-bottom:-.75rem;margin-left:-.625rem;border-bottom:0}.card-header-pills{margin-right:-.625rem;margin-left:-.625rem}.card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1.25rem}.card-img{width:100%;border-radius:calc(.25rem - 1px)}.card-img-top{width:100%;border-top-left-radius:calc(.25rem - 1px);border-top-right-radius:calc(.25rem - 1px)}.card-img-bottom{width:100%;border-bottom-right-radius:calc(.25rem - 1px);border-bottom-left-radius:calc(.25rem - 1px)}.card-deck{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.card-deck .card{margin-bottom:15px}@media (min-width:576px){.card-deck{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;margin-right:-15px;margin-left:-15px}.card-deck .card{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:15px;margin-bottom:0;margin-left:15px}}.card-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.card-group>.card{margin-bottom:15px}@media (min-width:576px){.card-group{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.card-group>.card{-webkit-box-flex:1;-ms-flex:1 0 0%;flex:1 0 0%;margin-bottom:0}.card-group>.card+.card{margin-left:0;border-left:0}.card-group>.card:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.card-group>.card:first-child .card-header,.card-group>.card:first-child .card-img-top{border-top-right-radius:0}.card-group>.card:first-child .card-footer,.card-group>.card:first-child .card-img-bottom{border-bottom-right-radius:0}.card-group>.card:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.card-group>.card:last-child .card-header,.card-group>.card:last-child .card-img-top{border-top-left-radius:0}.card-group>.card:last-child .card-footer,.card-group>.card:last-child .card-img-bottom{border-bottom-left-radius:0}.card-group>.card:only-child{border-radius:.25rem}.card-group>.card:only-child .card-header,.card-group>.card:only-child .card-img-top{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.card-group>.card:only-child .card-footer,.card-group>.card:only-child .card-img-bottom{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.card-group>.card:not(:first-child):not(:last-child):not(:only-child){border-radius:0}.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-footer,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-header,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,.card-group>.card:not(:first-child):not(:last-child):not(:only-child) .card-img-top{border-radius:0}}.card-columns .card{margin-bottom:.75rem}@media (min-width:576px){.card-columns{-webkit-column-count:3;-moz-column-count:3;column-count:3;-webkit-column-gap:1.25rem;-moz-column-gap:1.25rem;column-gap:1.25rem}.card-columns .card{display:inline-block;width:100%}}.breadcrumb{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:.75rem 1rem;margin-bottom:1rem;list-style:none;background-color:#e9ecef;border-radius:.25rem}.breadcrumb-item+.breadcrumb-item::before{display:inline-block;padding-right:.5rem;padding-left:.5rem;color:#6c757d;content:"/"}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:underline}.breadcrumb-item+.breadcrumb-item:hover::before{text-decoration:none}.breadcrumb-item.active{color:#6c757d}.pagination{display:-webkit-box;display:-ms-flexbox;display:flex;padding-left:0;list-style:none;border-radius:.25rem}.page-link{position:relative;display:block;padding:.5rem .75rem;margin-left:-1px;line-height:1.25;color:#007bff;background-color:#fff;border:1px solid #dee2e6}.page-link:hover{color:#0056b3;text-decoration:none;background-color:#e9ecef;border-color:#dee2e6}.page-link:focus{z-index:2;outline:0;box-shadow:0 0 0 .2rem rgba(0,123,255,.25)}.page-link:not(:disabled):not(.disabled){cursor:pointer}.page-item:first-child .page-link{margin-left:0;border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.page-item:last-child .page-link{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.page-item.active .page-link{z-index:1;color:#fff;background-color:#007bff;border-color:#007bff}.page-item.disabled .page-link{color:#6c757d;pointer-events:none;cursor:auto;background-color:#fff;border-color:#dee2e6}.pagination-lg .page-link{padding:.75rem 1.5rem;font-size:1.25rem;line-height:1.5}.pagination-lg .page-item:first-child .page-link{border-top-left-radius:.3rem;border-bottom-left-radius:.3rem}.pagination-lg .page-item:last-child .page-link{border-top-right-radius:.3rem;border-bottom-right-radius:.3rem}.pagination-sm .page-link{padding:.25rem .5rem;font-size:.875rem;line-height:1.5}.pagination-sm .page-item:first-child .page-link{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}.pagination-sm .page-item:last-child .page-link{border-top-right-radius:.2rem;border-bottom-right-radius:.2rem}.badge{display:inline-block;padding:.25em .4em;font-size:75%;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.badge-pill{padding-right:.6em;padding-left:.6em;border-radius:10rem}.badge-primary{color:#fff;background-color:#007bff}.badge-primary[href]:focus,.badge-primary[href]:hover{color:#fff;text-decoration:none;background-color:#0062cc}.badge-secondary{color:#fff;background-color:#6c757d}.badge-secondary[href]:focus,.badge-secondary[href]:hover{color:#fff;text-decoration:none;background-color:#545b62}.badge-success{color:#fff;background-color:#28a745}.badge-success[href]:focus,.badge-success[href]:hover{color:#fff;text-decoration:none;background-color:#1e7e34}.badge-info{color:#fff;background-color:#17a2b8}.badge-info[href]:focus,.badge-info[href]:hover{color:#fff;text-decoration:none;background-color:#117a8b}.badge-warning{color:#212529;background-color:#ffc107}.badge-warning[href]:focus,.badge-warning[href]:hover{color:#212529;text-decoration:none;background-color:#d39e00}.badge-danger{color:#fff;background-color:#dc3545}.badge-danger[href]:focus,.badge-danger[href]:hover{color:#fff;text-decoration:none;background-color:#bd2130}.badge-light{color:#212529;background-color:#f8f9fa}.badge-light[href]:focus,.badge-light[href]:hover{color:#212529;text-decoration:none;background-color:#dae0e5}.badge-dark{color:#fff;background-color:#343a40}.badge-dark[href]:focus,.badge-dark[href]:hover{color:#fff;text-decoration:none;background-color:#1d2124}.jumbotron{padding:2rem 1rem;margin-bottom:2rem;background-color:#e9ecef;border-radius:.3rem}@media (min-width:576px){.jumbotron{padding:4rem 2rem}}.jumbotron-fluid{padding-right:0;padding-left:0;border-radius:0}.alert{position:relative;padding:.75rem 1.25rem;margin-bottom:1rem;border:1px solid transparent;border-radius:.25rem}.alert-heading{color:inherit}.alert-link{font-weight:700}.alert-dismissible{padding-right:4rem}.alert-dismissible .close{position:absolute;top:0;right:0;padding:.75rem 1.25rem;color:inherit}.alert-primary{color:#004085;background-color:#cce5ff;border-color:#b8daff}.alert-primary hr{border-top-color:#9fcdff}.alert-primary .alert-link{color:#002752}.alert-secondary{color:#383d41;background-color:#e2e3e5;border-color:#d6d8db}.alert-secondary hr{border-top-color:#c8cbcf}.alert-secondary .alert-link{color:#202326}.alert-success{color:#155724;background-color:#d4edda;border-color:#c3e6cb}.alert-success hr{border-top-color:#b1dfbb}.alert-success .alert-link{color:#0b2e13}.alert-info{color:#0c5460;background-color:#d1ecf1;border-color:#bee5eb}.alert-info hr{border-top-color:#abdde5}.alert-info .alert-link{color:#062c33}.alert-warning{color:#856404;background-color:#fff3cd;border-color:#ffeeba}.alert-warning hr{border-top-color:#ffe8a1}.alert-warning .alert-link{color:#533f03}.alert-danger{color:#721c24;background-color:#f8d7da;border-color:#f5c6cb}.alert-danger hr{border-top-color:#f1b0b7}.alert-danger .alert-link{color:#491217}.alert-light{color:#818182;background-color:#fefefe;border-color:#fdfdfe}.alert-light hr{border-top-color:#ececf6}.alert-light .alert-link{color:#686868}.alert-dark{color:#1b1e21;background-color:#d6d8d9;border-color:#c6c8ca}.alert-dark hr{border-top-color:#b9bbbe}.alert-dark .alert-link{color:#040505}@-webkit-keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:1rem 0}to{background-position:0 0}}.progress{display:-webkit-box;display:-ms-flexbox;display:flex;height:1rem;overflow:hidden;font-size:.75rem;background-color:#e9ecef;border-radius:.25rem}.progress-bar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;color:#fff;text-align:center;background-color:#007bff;transition:width .6s ease}.progress-bar-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:1rem 1rem}.progress-bar-animated{-webkit-animation:progress-bar-stripes 1s linear infinite;animation:progress-bar-stripes 1s linear infinite}.media{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.media-body{-webkit-box-flex:1;-ms-flex:1;flex:1}.list-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding-left:0;margin-bottom:0}.list-group-item-action{width:100%;color:#495057;text-align:inherit}.list-group-item-action:focus,.list-group-item-action:hover{color:#495057;text-decoration:none;background-color:#f8f9fa}.list-group-item-action:active{color:#212529;background-color:#e9ecef}.list-group-item{position:relative;display:block;padding:.75rem 1.25rem;margin-bottom:-1px;background-color:#fff;border:1px solid rgba(0,0,0,.125)}.list-group-item:first-child{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.list-group-item:focus,.list-group-item:hover{z-index:1;text-decoration:none}.list-group-item.disabled,.list-group-item:disabled{color:#6c757d;background-color:#fff}.list-group-item.active{z-index:2;color:#fff;background-color:#007bff;border-color:#007bff}.list-group-flush .list-group-item{border-right:0;border-left:0;border-radius:0}.list-group-flush:first-child .list-group-item:first-child{border-top:0}.list-group-flush:last-child .list-group-item:last-child{border-bottom:0}.list-group-item-primary{color:#004085;background-color:#b8daff}.list-group-item-primary.list-group-item-action:focus,.list-group-item-primary.list-group-item-action:hover{color:#004085;background-color:#9fcdff}.list-group-item-primary.list-group-item-action.active{color:#fff;background-color:#004085;border-color:#004085}.list-group-item-secondary{color:#383d41;background-color:#d6d8db}.list-group-item-secondary.list-group-item-action:focus,.list-group-item-secondary.list-group-item-action:hover{color:#383d41;background-color:#c8cbcf}.list-group-item-secondary.list-group-item-action.active{color:#fff;background-color:#383d41;border-color:#383d41}.list-group-item-success{color:#155724;background-color:#c3e6cb}.list-group-item-success.list-group-item-action:focus,.list-group-item-success.list-group-item-action:hover{color:#155724;background-color:#b1dfbb}.list-group-item-success.list-group-item-action.active{color:#fff;background-color:#155724;border-color:#155724}.list-group-item-info{color:#0c5460;background-color:#bee5eb}.list-group-item-info.list-group-item-action:focus,.list-group-item-info.list-group-item-action:hover{color:#0c5460;background-color:#abdde5}.list-group-item-info.list-group-item-action.active{color:#fff;background-color:#0c5460;border-color:#0c5460}.list-group-item-warning{color:#856404;background-color:#ffeeba}.list-group-item-warning.list-group-item-action:focus,.list-group-item-warning.list-group-item-action:hover{color:#856404;background-color:#ffe8a1}.list-group-item-warning.list-group-item-action.active{color:#fff;background-color:#856404;border-color:#856404}.list-group-item-danger{color:#721c24;background-color:#f5c6cb}.list-group-item-danger.list-group-item-action:focus,.list-group-item-danger.list-group-item-action:hover{color:#721c24;background-color:#f1b0b7}.list-group-item-danger.list-group-item-action.active{color:#fff;background-color:#721c24;border-color:#721c24}.list-group-item-light{color:#818182;background-color:#fdfdfe}.list-group-item-light.list-group-item-action:focus,.list-group-item-light.list-group-item-action:hover{color:#818182;background-color:#ececf6}.list-group-item-light.list-group-item-action.active{color:#fff;background-color:#818182;border-color:#818182}.list-group-item-dark{color:#1b1e21;background-color:#c6c8ca}.list-group-item-dark.list-group-item-action:focus,.list-group-item-dark.list-group-item-action:hover{color:#1b1e21;background-color:#b9bbbe}.list-group-item-dark.list-group-item-action.active{color:#fff;background-color:#1b1e21;border-color:#1b1e21}.close{float:right;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.5}.close:focus,.close:hover{color:#000;text-decoration:none;opacity:.75}.close:not(:disabled):not(.disabled){cursor:pointer}button.close{padding:0;background-color:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;outline:0}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:.5rem;pointer-events:none}.modal.fade .modal-dialog{transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out;-webkit-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.show .modal-dialog{-webkit-transform:translate(0,0);transform:translate(0,0)}.modal-dialog-centered{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;min-height:calc(100% - (.5rem * 2))}.modal-content{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%;pointer-events:auto;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop.show{opacity:.5}.modal-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:1rem;border-bottom:1px solid #e9ecef;border-top-left-radius:.3rem;border-top-right-radius:.3rem}.modal-header .close{padding:1rem;margin:-1rem -1rem -1rem auto}.modal-title{margin-bottom:0;line-height:1.5}.modal-body{position:relative;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem}.modal-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;padding:1rem;border-top:1px solid #e9ecef}.modal-footer>:not(:first-child){margin-left:.25rem}.modal-footer>:not(:last-child){margin-right:.25rem}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:576px){.modal-dialog{max-width:500px;margin:1.75rem auto}.modal-dialog-centered{min-height:calc(100% - (1.75rem * 2))}.modal-sm{max-width:300px}}@media (min-width:992px){.modal-lg{max-width:800px}}.tooltip{position:absolute;z-index:1070;display:block;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;opacity:0}.tooltip.show{opacity:.9}.tooltip .arrow{position:absolute;display:block;width:.8rem;height:.4rem}.tooltip .arrow::before{position:absolute;content:"";border-color:transparent;border-style:solid}.bs-tooltip-auto[x-placement^=top],.bs-tooltip-top{padding:.4rem 0}.bs-tooltip-auto[x-placement^=top] .arrow,.bs-tooltip-top .arrow{bottom:0}.bs-tooltip-auto[x-placement^=top] .arrow::before,.bs-tooltip-top .arrow::before{top:0;border-width:.4rem .4rem 0;border-top-color:#000}.bs-tooltip-auto[x-placement^=right],.bs-tooltip-right{padding:0 .4rem}.bs-tooltip-auto[x-placement^=right] .arrow,.bs-tooltip-right .arrow{left:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=right] .arrow::before,.bs-tooltip-right .arrow::before{right:0;border-width:.4rem .4rem .4rem 0;border-right-color:#000}.bs-tooltip-auto[x-placement^=bottom],.bs-tooltip-bottom{padding:.4rem 0}.bs-tooltip-auto[x-placement^=bottom] .arrow,.bs-tooltip-bottom .arrow{top:0}.bs-tooltip-auto[x-placement^=bottom] .arrow::before,.bs-tooltip-bottom .arrow::before{bottom:0;border-width:0 .4rem .4rem;border-bottom-color:#000}.bs-tooltip-auto[x-placement^=left],.bs-tooltip-left{padding:0 .4rem}.bs-tooltip-auto[x-placement^=left] .arrow,.bs-tooltip-left .arrow{right:0;width:.4rem;height:.8rem}.bs-tooltip-auto[x-placement^=left] .arrow::before,.bs-tooltip-left .arrow::before{left:0;border-width:.4rem 0 .4rem .4rem;border-left-color:#000}.tooltip-inner{max-width:200px;padding:.25rem .5rem;color:#fff;text-align:center;background-color:#000;border-radius:.25rem}.popover{position:absolute;top:0;left:0;z-index:1060;display:block;max-width:276px;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:.3rem}.popover .arrow{position:absolute;display:block;width:1rem;height:.5rem;margin:0 .3rem}.popover .arrow::after,.popover .arrow::before{position:absolute;display:block;content:"";border-color:transparent;border-style:solid}.bs-popover-auto[x-placement^=top],.bs-popover-top{margin-bottom:.5rem}.bs-popover-auto[x-placement^=top] .arrow,.bs-popover-top .arrow{bottom:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::after,.bs-popover-top .arrow::before{border-width:.5rem .5rem 0}.bs-popover-auto[x-placement^=top] .arrow::before,.bs-popover-top .arrow::before{bottom:0;border-top-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=top] .arrow::after,.bs-popover-top .arrow::after{bottom:1px;border-top-color:#fff}.bs-popover-auto[x-placement^=right],.bs-popover-right{margin-left:.5rem}.bs-popover-auto[x-placement^=right] .arrow,.bs-popover-right .arrow{left:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::after,.bs-popover-right .arrow::before{border-width:.5rem .5rem .5rem 0}.bs-popover-auto[x-placement^=right] .arrow::before,.bs-popover-right .arrow::before{left:0;border-right-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=right] .arrow::after,.bs-popover-right .arrow::after{left:1px;border-right-color:#fff}.bs-popover-auto[x-placement^=bottom],.bs-popover-bottom{margin-top:.5rem}.bs-popover-auto[x-placement^=bottom] .arrow,.bs-popover-bottom .arrow{top:calc((.5rem + 1px) * -1)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::after,.bs-popover-bottom .arrow::before{border-width:0 .5rem .5rem .5rem}.bs-popover-auto[x-placement^=bottom] .arrow::before,.bs-popover-bottom .arrow::before{top:0;border-bottom-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=bottom] .arrow::after,.bs-popover-bottom .arrow::after{top:1px;border-bottom-color:#fff}.bs-popover-auto[x-placement^=bottom] .popover-header::before,.bs-popover-bottom .popover-header::before{position:absolute;top:0;left:50%;display:block;width:1rem;margin-left:-.5rem;content:"";border-bottom:1px solid #f7f7f7}.bs-popover-auto[x-placement^=left],.bs-popover-left{margin-right:.5rem}.bs-popover-auto[x-placement^=left] .arrow,.bs-popover-left .arrow{right:calc((.5rem + 1px) * -1);width:.5rem;height:1rem;margin:.3rem 0}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::after,.bs-popover-left .arrow::before{border-width:.5rem 0 .5rem .5rem}.bs-popover-auto[x-placement^=left] .arrow::before,.bs-popover-left .arrow::before{right:0;border-left-color:rgba(0,0,0,.25)}.bs-popover-auto[x-placement^=left] .arrow::after,.bs-popover-left .arrow::after{right:1px;border-left-color:#fff}.popover-header{padding:.5rem .75rem;margin-bottom:0;font-size:1rem;color:inherit;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-top-left-radius:calc(.3rem - 1px);border-top-right-radius:calc(.3rem - 1px)}.popover-header:empty{display:none}.popover-body{padding:.5rem .75rem;color:#212529}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-item{position:relative;display:none;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:100%;transition:-webkit-transform .6s ease;transition:transform .6s ease;transition:transform .6s ease,-webkit-transform .6s ease;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-item-next,.carousel-item-prev,.carousel-item.active{display:block}.carousel-item-next,.carousel-item-prev{position:absolute;top:0}.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translateX(0);transform:translateX(0)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.carousel-item-next.carousel-item-left,.carousel-item-prev.carousel-item-right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.active.carousel-item-right,.carousel-item-next{-webkit-transform:translateX(100%);transform:translateX(100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-right,.carousel-item-next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translateX(-100%);transform:translateX(-100%)}@supports ((-webkit-transform-style:preserve-3d) or (transform-style:preserve-3d)){.active.carousel-item-left,.carousel-item-prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.carousel-control-next,.carousel-control-prev{position:absolute;top:0;bottom:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:15%;color:#fff;text-align:center;opacity:.5}.carousel-control-next:focus,.carousel-control-next:hover,.carousel-control-prev:focus,.carousel-control-prev:hover{color:#fff;text-decoration:none;outline:0;opacity:.9}.carousel-control-prev{left:0}.carousel-control-next{right:0}.carousel-control-next-icon,.carousel-control-prev-icon{display:inline-block;width:20px;height:20px;background:transparent no-repeat center center;background-size:100% 100%}.carousel-control-prev-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E")}.carousel-control-next-icon{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E")}.carousel-indicators{position:absolute;right:0;bottom:10px;left:0;z-index:15;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-left:0;margin-right:15%;margin-left:15%;list-style:none}.carousel-indicators li{position:relative;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;width:30px;height:3px;margin-right:3px;margin-left:3px;text-indent:-999px;background-color:rgba(255,255,255,.5)}.carousel-indicators li::before{position:absolute;top:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators li::after{position:absolute;bottom:-10px;left:0;display:inline-block;width:100%;height:10px;content:""}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center}.align-baseline{vertical-align:baseline!important}.align-top{vertical-align:top!important}.align-middle{vertical-align:middle!important}.align-bottom{vertical-align:bottom!important}.align-text-bottom{vertical-align:text-bottom!important}.align-text-top{vertical-align:text-top!important}.bg-primary{background-color:#007bff!important}a.bg-primary:focus,a.bg-primary:hover,button.bg-primary:focus,button.bg-primary:hover{background-color:#0062cc!important}.bg-secondary{background-color:#6c757d!important}a.bg-secondary:focus,a.bg-secondary:hover,button.bg-secondary:focus,button.bg-secondary:hover{background-color:#545b62!important}.bg-success{background-color:#28a745!important}a.bg-success:focus,a.bg-success:hover,button.bg-success:focus,button.bg-success:hover{background-color:#1e7e34!important}.bg-info{background-color:#17a2b8!important}a.bg-info:focus,a.bg-info:hover,button.bg-info:focus,button.bg-info:hover{background-color:#117a8b!important}.bg-warning{background-color:#ffc107!important}a.bg-warning:focus,a.bg-warning:hover,button.bg-warning:focus,button.bg-warning:hover{background-color:#d39e00!important}.bg-danger{background-color:#dc3545!important}a.bg-danger:focus,a.bg-danger:hover,button.bg-danger:focus,button.bg-danger:hover{background-color:#bd2130!important}.bg-light{background-color:#f8f9fa!important}a.bg-light:focus,a.bg-light:hover,button.bg-light:focus,button.bg-light:hover{background-color:#dae0e5!important}.bg-dark{background-color:#343a40!important}a.bg-dark:focus,a.bg-dark:hover,button.bg-dark:focus,button.bg-dark:hover{background-color:#1d2124!important}.bg-white{background-color:#fff!important}.bg-transparent{background-color:transparent!important}.border{border:1px solid #dee2e6!important}.border-top{border-top:1px solid #dee2e6!important}.border-right{border-right:1px solid #dee2e6!important}.border-bottom{border-bottom:1px solid #dee2e6!important}.border-left{border-left:1px solid #dee2e6!important}.border-0{border:0!important}.border-top-0{border-top:0!important}.border-right-0{border-right:0!important}.border-bottom-0{border-bottom:0!important}.border-left-0{border-left:0!important}.border-primary{border-color:#007bff!important}.border-secondary{border-color:#6c757d!important}.border-success{border-color:#28a745!important}.border-info{border-color:#17a2b8!important}.border-warning{border-color:#ffc107!important}.border-danger{border-color:#dc3545!important}.border-light{border-color:#f8f9fa!important}.border-dark{border-color:#343a40!important}.border-white{border-color:#fff!important}.rounded{border-radius:.25rem!important}.rounded-top{border-top-left-radius:.25rem!important;border-top-right-radius:.25rem!important}.rounded-right{border-top-right-radius:.25rem!important;border-bottom-right-radius:.25rem!important}.rounded-bottom{border-bottom-right-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-left{border-top-left-radius:.25rem!important;border-bottom-left-radius:.25rem!important}.rounded-circle{border-radius:50%!important}.rounded-0{border-radius:0!important}.clearfix::after{display:block;clear:both;content:""}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-webkit-inline-box!important;display:-ms-inline-flexbox!important;display:inline-flex!important}}.embed-responsive{position:relative;display:block;width:100%;padding:0;overflow:hidden}.embed-responsive::before{display:block;content:""}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-21by9::before{padding-top:42.857143%}.embed-responsive-16by9::before{padding-top:56.25%}.embed-responsive-4by3::before{padding-top:75%}.embed-responsive-1by1::before{padding-top:100%}.flex-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-sm-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-md-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-lg-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-webkit-box-orient:horizontal!important;-webkit-box-direction:normal!important;-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-webkit-box-orient:vertical!important;-webkit-box-direction:normal!important;-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-webkit-box-orient:horizontal!important;-webkit-box-direction:reverse!important;-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-webkit-box-orient:vertical!important;-webkit-box-direction:reverse!important;-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.justify-content-xl-start{-webkit-box-pack:start!important;-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-webkit-box-pack:end!important;-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-webkit-box-pack:center!important;-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-webkit-box-align:start!important;-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-webkit-box-align:center!important;-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-webkit-box-align:baseline!important;-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-webkit-box-align:stretch!important;-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.float-left{float:left!important}.float-right{float:right!important}.float-none{float:none!important}@media (min-width:576px){.float-sm-left{float:left!important}.float-sm-right{float:right!important}.float-sm-none{float:none!important}}@media (min-width:768px){.float-md-left{float:left!important}.float-md-right{float:right!important}.float-md-none{float:none!important}}@media (min-width:992px){.float-lg-left{float:left!important}.float-lg-right{float:right!important}.float-lg-none{float:none!important}}@media (min-width:1200px){.float-xl-left{float:left!important}.float-xl-right{float:right!important}.float-xl-none{float:none!important}}.position-static{position:static!important}.position-relative{position:relative!important}.position-absolute{position:absolute!important}.position-fixed{position:fixed!important}.position-sticky{position:-webkit-sticky!important;position:sticky!important}.fixed-top{position:fixed;top:0;right:0;left:0;z-index:1030}.fixed-bottom{position:fixed;right:0;bottom:0;left:0;z-index:1030}@supports ((position:-webkit-sticky) or (position:sticky)){.sticky-top{position:-webkit-sticky;position:sticky;top:0;z-index:1020}}.sr-only{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;-webkit-clip-path:inset(50%);clip-path:inset(50%);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal;-webkit-clip-path:none;clip-path:none}.w-25{width:25%!important}.w-50{width:50%!important}.w-75{width:75%!important}.w-100{width:100%!important}.h-25{height:25%!important}.h-50{height:50%!important}.h-75{height:75%!important}.h-100{height:100%!important}.mw-100{max-width:100%!important}.mh-100{max-height:100%!important}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}}.text-justify{text-align:justify!important}.text-nowrap{white-space:nowrap!important}.text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text-left{text-align:left!important}.text-right{text-align:right!important}.text-center{text-align:center!important}@media (min-width:576px){.text-sm-left{text-align:left!important}.text-sm-right{text-align:right!important}.text-sm-center{text-align:center!important}}@media (min-width:768px){.text-md-left{text-align:left!important}.text-md-right{text-align:right!important}.text-md-center{text-align:center!important}}@media (min-width:992px){.text-lg-left{text-align:left!important}.text-lg-right{text-align:right!important}.text-lg-center{text-align:center!important}}@media (min-width:1200px){.text-xl-left{text-align:left!important}.text-xl-right{text-align:right!important}.text-xl-center{text-align:center!important}}.text-lowercase{text-transform:lowercase!important}.text-uppercase{text-transform:uppercase!important}.text-capitalize{text-transform:capitalize!important}.font-weight-light{font-weight:300!important}.font-weight-normal{font-weight:400!important}.font-weight-bold{font-weight:700!important}.font-italic{font-style:italic!important}.text-white{color:#fff!important}.text-primary{color:#007bff!important}a.text-primary:focus,a.text-primary:hover{color:#0062cc!important}.text-secondary{color:#6c757d!important}a.text-secondary:focus,a.text-secondary:hover{color:#545b62!important}.text-success{color:#28a745!important}a.text-success:focus,a.text-success:hover{color:#1e7e34!important}.text-info{color:#17a2b8!important}a.text-info:focus,a.text-info:hover{color:#117a8b!important}.text-warning{color:#ffc107!important}a.text-warning:focus,a.text-warning:hover{color:#d39e00!important}.text-danger{color:#dc3545!important}a.text-danger:focus,a.text-danger:hover{color:#bd2130!important}.text-light{color:#f8f9fa!important}a.text-light:focus,a.text-light:hover{color:#dae0e5!important}.text-dark{color:#343a40!important}a.text-dark:focus,a.text-dark:hover{color:#1d2124!important}.text-muted{color:#6c757d!important}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.visible{visibility:visible!important}.invisible{visibility:hidden!important}@media print{*,::after,::before{text-shadow:none!important;box-shadow:none!important}a:not(.btn){text-decoration:underline}abbr[title]::after{content:" (" attr(title) ")"}pre{white-space:pre-wrap!important}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{size:a3}body{min-width:992px!important}.container{min-width:992px!important}.navbar{display:none}.badge{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}} +/*# sourceMappingURL=bootstrap.min.css.map */ diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/static/favicon.ico b/2.x/spring-boot-web-thymeleaf/src/main/resources/static/favicon.ico new file mode 100644 index 000000000..fd306001d Binary files /dev/null and b/2.x/spring-boot-web-thymeleaf/src/main/resources/static/favicon.ico differ diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/fragments.html b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/fragments.html new file mode 100644 index 000000000..4aee99234 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/fragments.html @@ -0,0 +1,18 @@ + + + + Fragments + + + +
+ +
+ + diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html new file mode 100644 index 000000000..1d564bfba --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html @@ -0,0 +1,31 @@ + + + + Messages : Create + + +
+
+ +

Messages : Create

+
+
+ + +
+ + +
+
+ + +
+ +
+
+ + diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html new file mode 100644 index 000000000..88f00a8fd --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html @@ -0,0 +1,36 @@ + + + + Messages : View all + + +
+
+ +

Messages : View all

+ + + + + + + + + + + + + + + + + + +
IDCreatedSummary
No messages
1July 11, + 2012 2:17:16 PM CDT The summary
+
+ + diff --git a/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html new file mode 100644 index 000000000..e32cb74e0 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html @@ -0,0 +1,27 @@ + + + + Messages : View + + +
+
+
+ Messages +
+

Messages : View

+
+
Some Success message +
+
+
+

123 - A short summary...

+
July 11, 2012 2:17:16 PM CDT
+

A detailed message that is longer than the summary.

+ delete + modify +
+
+
+ + diff --git a/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/MessageControllerWebTests.java b/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/MessageControllerWebTests.java new file mode 100644 index 000000000..c27555309 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/MessageControllerWebTests.java @@ -0,0 +1,89 @@ + +package com.neo; + +import java.util.regex.Pattern; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@WebAppConfiguration +@ContextConfiguration(classes = ThymeleafApplication.class) +public class MessageControllerWebTests { + + @Autowired + private WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void testHome() throws Exception { + this.mockMvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(content().string(containsString("Messages"))); + } + + @Test + public void testCreate() throws Exception { + this.mockMvc.perform(post("/").param("text", "FOO text").param("summary", "FOO")) + .andExpect(status().isFound()) + .andExpect(header().string("location", RegexMatcher.matches("/[0-9]+"))); + } + + @Test + public void testCreateValidation() throws Exception { + this.mockMvc.perform(post("/").param("text", "").param("summary", "")) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("is required"))); + } + + private static class RegexMatcher extends TypeSafeMatcher<String> { + private final String regex; + + public RegexMatcher(String regex) { + this.regex = regex; + } + + public static org.hamcrest.Matcher<java.lang.String> matches(String regex) { + return new RegexMatcher(regex); + } + + @Override + public boolean matchesSafely(String item) { + return Pattern.compile(this.regex).matcher(item).find(); + } + + @Override + public void describeMismatchSafely(String item, Description mismatchDescription) { + mismatchDescription.appendText("was \"").appendText(item).appendText("\""); + } + + @Override + public void describeTo(Description description) { + description.appendText("a string that matches regex: ") + .appendText(this.regex); + } + } +} diff --git a/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java b/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java new file mode 100644 index 000000000..e97547773 --- /dev/null +++ b/2.x/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java @@ -0,0 +1,57 @@ + +package com.neo; + +import java.net.URI; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class ThymeleafApplicationTests { + + @Autowired + private TestRestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Test + public void testHome() { + ResponseEntity<String> entity = this.restTemplate.getForEntity("/", String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getBody()).contains("<title>Messages"); + assertThat(entity.getBody()).doesNotContain("layout:fragment"); + } + + @Test + public void testCreate() { + MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); + map.set("text", "FOO text"); + map.set("summary", "FOO"); + URI location = this.restTemplate.postForLocation("/", map); + assertThat(location.toString()).contains("localhost:" + this.port); + } + + @Test + public void testCss() { + ResponseEntity<String> entity = this.restTemplate.getForEntity( + "http://localhost:" + this.port + "/css/bootstrap.min.css", String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getBody()).contains("body"); + } + +} diff --git a/2.x/spring-boot-web/pom.xml b/2.x/spring-boot-web/pom.xml new file mode 100644 index 000000000..e0a2f96d0 --- /dev/null +++ b/2.x/spring-boot-web/pom.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.neo</groupId> + <artifactId>spring-boot-web</artifactId> + <version>1.0.01-SNAPSHOT</version> + <packaging>war</packaging> + + <name>spring-boot-web</name> + <description>Demo project for Spring Boot</description> + + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>2.1.3.RELEASE</version> + </parent> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <java.version>1.8</java.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-thymeleaf</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + </dependency> + <dependency> + <groupId>org.webjars.bower</groupId> + <artifactId>jquery</artifactId> + <version>2.0.3</version> + </dependency> + <dependency> + <groupId>org.webjars.bower</groupId> + <artifactId>bootstrap</artifactId> + <version>3.0.3</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + + +</project> diff --git a/2.x/spring-boot-web/src/main/java/com/neo/WebApplication.java b/2.x/spring-boot-web/src/main/java/com/neo/WebApplication.java new file mode 100644 index 000000000..ede8e479f --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/WebApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebApplication { + + public static void main(String[] args) { + SpringApplication.run(WebApplication.class, args); + } +} diff --git a/2.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java b/2.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java new file mode 100644 index 000000000..cbf7177fd --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/WebConfiguration.java @@ -0,0 +1,60 @@ +package com.neo; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.catalina.filters.RemoteIpFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebConfiguration { + @Bean + public RemoteIpFilter remoteIpFilter() { + return new RemoteIpFilter(); + } + + @Bean + public FilterRegistrationBean testFilterRegistration() { + + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new MyFilter()); + registration.addUrlPatterns("/*"); + registration.addInitParameter("paramName", "paramValue"); + registration.setName("MyFilter"); + registration.setOrder(1); + return registration; + } + + public class MyFilter implements Filter { + @Override + public void destroy() { + // TODO Auto-generated method stub + } + + @Override + public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain filterChain) + throws IOException, ServletException { + // TODO Auto-generated method stub + HttpServletRequest request = (HttpServletRequest) srequest; + System.out.println("this is MyFilter,url :"+request.getRequestURI()); + filterChain.doFilter(srequest, sresponse); + } + + @Override + public void init(FilterConfig arg0) throws ServletException { + // TODO Auto-generated method stub + } + } +} + + + diff --git a/2.x/spring-boot-web/src/main/java/com/neo/model/User.java b/2.x/spring-boot-web/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..53204112f --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/model/User.java @@ -0,0 +1,76 @@ +package com.neo.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true) + private String email; + @Column(nullable = true, unique = true) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + super(); + } + public User(String nickName,String email,String userName, String passWord, String regTime) { + super(); + this.email = email; + this.nickName = nickName; + this.passWord = passWord; + this.userName = userName; + this.regTime = regTime; + } + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + public void setNickName(String nickName) { + this.nickName = nickName; + } + public String getRegTime() { + return regTime; + } + public void setRegTime(String regTime) { + this.regTime = regTime; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java b/2.x/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..b5c0c63ec --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository<User, Long> { + + User findByUserName(String userName); + + User findByUserNameOrEmail(String username, String email); + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java b/2.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java new file mode 100644 index 000000000..ab337bfbd --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/util/NeoProperties.java @@ -0,0 +1,26 @@ +package com.neo.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class NeoProperties { + + @Value("${com.neo.title}") + private String title; + @Value("${com.neo.description}") + private String description; + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/2.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java b/2.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..ac3dee8e6 --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,21 @@ +package com.neo.web; + +import java.util.Locale; +import java.util.UUID; + +import javax.servlet.http.HttpSession; + +import com.neo.model.User; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/hello") + public String hello(Locale locale, Model model) { + return "Hello World"; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java b/2.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java new file mode 100644 index 000000000..c384bd1d8 --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/web/ThymeleafController.java @@ -0,0 +1,26 @@ +package com.neo.web; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Locale; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class ThymeleafController { + + @RequestMapping("/hi") + public String hello(Locale locale, Model model) { + model.addAttribute("greeting", "Hello!"); + + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale); + String formattedDate = dateFormat.format(date); + model.addAttribute("currentTime", formattedDate); + + return "hello"; + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/java/com/neo/web/UserController.java b/2.x/spring-boot-web/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..b722a87d5 --- /dev/null +++ b/2.x/spring-boot-web/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,31 @@ +package com.neo.web; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.neo.model.User; +import com.neo.repository.UserRepository; + +@RestController +public class UserController { + + @Autowired + private UserRepository userRepository; + + @RequestMapping("/getUser") + public User getUser() { + User user=userRepository.findByUserName("aa"); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return user; + } + + @RequestMapping("/getUsers") + public List<User> getUsers() { + List<User> users=userRepository.findAll(); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return users; + } +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/resources/application.properties b/2.x/spring-boot-web/src/main/resources/application.properties new file mode 100644 index 000000000..bf2d2c8a7 --- /dev/null +++ b/2.x/spring-boot-web/src/main/resources/application.properties @@ -0,0 +1,14 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +#sql\u8F93\u51FA +spring.jpa.show-sql=true +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true + +com.neo.title=\u7EAF\u6D01\u7684\u5FAE\u7B11 +com.neo.description=\u5206\u4EAB\u751F\u6D3B\u548C\u6280\u672F \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/resources/static/css/starter.css b/2.x/spring-boot-web/src/main/resources/static/css/starter.css new file mode 100644 index 000000000..e2fc60cd4 --- /dev/null +++ b/2.x/spring-boot-web/src/main/resources/static/css/starter.css @@ -0,0 +1,8 @@ +body { + padding-top: 50px; +} + +.starter-template { + padding: 40px 15px; + text-align: center; +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/main/resources/static/images/favicon.png b/2.x/spring-boot-web/src/main/resources/static/images/favicon.png new file mode 100644 index 000000000..890ef0630 Binary files /dev/null and b/2.x/spring-boot-web/src/main/resources/static/images/favicon.png differ diff --git a/2.x/spring-boot-web/src/main/resources/templates/hello.html b/2.x/spring-boot-web/src/main/resources/templates/hello.html new file mode 100644 index 000000000..c417054af --- /dev/null +++ b/2.x/spring-boot-web/src/main/resources/templates/hello.html @@ -0,0 +1,18 @@ +<html xmlns:th="http://www.thymeleaf.org"> + <head th:include="layout :: htmlhead" th:with="title='Hello'"></head> + + <body> + <div th:replace="layout :: navbar">(navbar)</div> + + <div class="container"> + <div class="starter-template"> + <h1>Spring MVC / Thymeleaf / Bootstrap</h1> + <p class="lead" th:text="${greeting}">(greeting)</p> + <p>The current time is <span th:text="${currentTime}">(time)</span></p> + </div> + </div> + + <div th:include="layout :: footer" id="footer">(footer)</div> + + </body> +</html> diff --git a/2.x/spring-boot-web/src/main/resources/templates/layout.html b/2.x/spring-boot-web/src/main/resources/templates/layout.html new file mode 100644 index 000000000..422fbb71e --- /dev/null +++ b/2.x/spring-boot-web/src/main/resources/templates/layout.html @@ -0,0 +1,54 @@ +<html xmlns:th="http://www.thymeleaf.org"> + <head th:fragment="htmlhead"> + <meta charset="utf-8"></meta> + <meta http-equiv="X-UA-Compatible" content="IE=edge"></meta> + <meta name="viewport" content="width=device-width, initial-scale=1.0"></meta> + <meta name="description" content=""></meta> + <meta name="author" content=""></meta> + <link rel="shortcut icon" type="image/png" th:href="@{/images/favicon.png}"></link> + + <title th:text="${title}">(title) + + + + + + + + +
+
+

Spring MVC/Thymeleaf/Bootstrap

+

(greeting)

+
+
+ + + + + diff --git a/2.x/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java b/2.x/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java new file mode 100644 index 000000000..cd4cb770c --- /dev/null +++ b/2.x/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class WebApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello web"); + } + +} diff --git a/2.x/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java b/2.x/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java new file mode 100644 index 000000000..3b7d8ea33 --- /dev/null +++ b/2.x/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java @@ -0,0 +1,38 @@ +package com.neo.model; + +import java.text.DateFormat; +import java.util.Date; + +import com.neo.repository.UserRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + + @Autowired + private UserRepository userRepository; + + @Test + public void test() throws Exception { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userRepository.save(new User("aa1", "aa@126.com", "aa", "aa123456",formattedDate)); + userRepository.save(new User("bb2", "bb@126.com", "bb", "bb123456",formattedDate)); + userRepository.save(new User("cc3", "cc@126.com", "cc", "cc123456",formattedDate)); + +// Assert.assertEquals(9, userRepository.findAll().size()); + Assert.assertEquals("bb2", userRepository.findByUserNameOrEmail("bb", "xxx126.com").getNickName()); + userRepository.delete(userRepository.findByUserName("aa")); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java b/2.x/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java new file mode 100644 index 000000000..f0a83c9ae --- /dev/null +++ b/2.x/spring-boot-web/src/test/java/com/neo/web/HelloControlerTests.java @@ -0,0 +1,57 @@ +package com.neo.web; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.neo.web.HelloController; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + + + + @Test + public void testHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + + +} \ No newline at end of file diff --git a/2.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java b/2.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java new file mode 100644 index 000000000..93722c9a6 --- /dev/null +++ b/2.x/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java @@ -0,0 +1,35 @@ +package com.neo.web; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import com.neo.util.NeoProperties; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ProPertiesTest { + + @Autowired + private NeoProperties neoProperties; + + @Test + public void getHello() throws Exception { + System.out.println(neoProperties.getTitle()); + Assert.assertEquals(neoProperties.getTitle(), "纯洁的微笑"); + Assert.assertEquals(neoProperties.getDescription(), "分享生活和技术"); + } + + @Test + public void testMap() throws Exception { + Map orderMinTime=new HashMap(); + long xx=orderMinTime.get("123"); + } + +} \ No newline at end of file diff --git a/2.x/spring-boot-webflux/pom.xml b/2.x/spring-boot-webflux/pom.xml new file mode 100644 index 000000000..68a6ca1f2 --- /dev/null +++ b/2.x/spring-boot-webflux/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + com.neo + spring-boot-webflux + 1.0.0-SNAPSHOT + jar + + spring-boot-webflux + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 2.1.2.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-devtools + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/2.x/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java b/2.x/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java new file mode 100644 index 000000000..b89527d35 --- /dev/null +++ b/2.x/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebFluxApplication { + + public static void main(String[] args) { + SpringApplication.run(WebFluxApplication.class, args); + } +} diff --git a/2.x/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java b/2.x/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..681a1542f --- /dev/null +++ b/2.x/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,14 @@ +package com.neo.web; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class HelloController { + + @GetMapping("/hello") + public Mono hello() { + return Mono.just("Welcome to reactive world ~"); + } +} diff --git a/2.x/spring-boot-webflux/src/main/resources/application.properties b/2.x/spring-boot-webflux/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/2.x/spring-boot-webflux/src/test/java/com/neo/HelloTests.java b/2.x/spring-boot-webflux/src/test/java/com/neo/HelloTests.java new file mode 100644 index 000000000..aa9389c5f --- /dev/null +++ b/2.x/spring-boot-webflux/src/test/java/com/neo/HelloTests.java @@ -0,0 +1,21 @@ +package com.neo; + +import com.neo.web.HelloController; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + +@RunWith(SpringRunner.class) +@WebFluxTest(controllers = HelloController.class) +public class HelloTests { + @Autowired + WebTestClient client; + + @Test + public void getHello() { + client.get().uri("/hello").exchange().expectStatus().isOk(); + } +} diff --git a/2.x/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java b/2.x/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java new file mode 100644 index 000000000..b7b4ed765 --- /dev/null +++ b/2.x/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class WebFluxApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/README.md b/README.md index 026b871e6..de3f8c880 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,55 @@ -# Spring Boot Examples +Spring Boot 学习示例 +========================= -Spring Boot 使用的各种示例,以最简单、最实用为标准 +![Spring Boot 2.0](https://img.shields.io/badge/Spring%20Boot-2.0-brightgreen.svg) +![Mysql 5.6](https://img.shields.io/badge/Mysql-5.6-blue.svg) +![JDK 1.8](https://img.shields.io/badge/JDK-1.8-brightgreen.svg) +![Maven](https://img.shields.io/badge/Maven-3.5.0-yellowgreen.svg) +![license](https://img.shields.io/badge/license-MPL--2.0-blue.svg) + +Spring Boot 使用的各种示例,以最简单、最实用为标准,此开源项目中的每个示例都以最小依赖,最简单为标准,帮助初学者快速掌握 Spring Boot 各组件的使用。 [Spring Boot 中文索引](https://github.com/ityouknow/awesome-spring-boot)  |   [Spring Cloud学习示例代码](https://github.com/ityouknow/spring-cloud-examples)  |   [Spring Boot 精品课程](https://github.com/ityouknow/spring-boot-leaning) -[English](README_EN.md)  |   [Github地址](https://github.com/ityouknow/spring-boot-examples)  |   [码云地址](https://gitee.com/ityouknow/spring-boot-examples)  |   [Spring Boot 1.0](https://github.com/ityouknow/spring-boot-examples/tree/Spring-Boot-1.0) + [Github地址](https://github.com/ityouknow/spring-boot-examples)  |   [码云地址](https://gitee.com/ityouknow/spring-boot-examples)  |   [Spring Boot 1.X](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x) |   [Spring Boot 2.X](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x) --- -## Spring Boot 2.0 -**[Spring Boot 2.0 最全使用教程](https://github.com/ityouknow/spring-boot-leaning)** +**本项目中所有示例均已经更新到 Spring Boot 3.0** -**[Favorites-web](https://github.com/cloudfavorites/favorites-web):云收藏(Spring Boot 2.0 实战开源项目)** +- Spring Boot 1.X 系列示例代码请看这里:[Spring Boot 1.X](https://github.com/ityouknow/spring-boot-examples/tree/master/1.x) +- Spring Boot 2.X 系列示例代码请看这里:[Spring Boot 2.X](https://github.com/ityouknow/spring-boot-examples/tree/master/2.x) -**示例代码** -- [spring-boot-hello](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-hello):Spring Boot 2.0 Hello World 示例 -- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-banner):Spring Boot 定制 Banner 示例 -- [spring-boot-docker](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-banner):使用 Docker 部署 Spring Boot 示例 -- [dockercompose-springboot-mysql-nginx](https://github.com/ityouknow/spring-boot-examples/tree/master/dockercompose-springboot-mysql-nginx) :Docker Compose + Spring Boot + Nginx + Mysql 示例 -- [spring-boot-commandLineRunner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-commandLineRunner) :Spring Boot 使用 commandLineRunner 实现项目启动时资源初始化示例 -- [spring-boot-web-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web-thymeleaf) :Spring Boot 使用 thymeleaf 实现布局、验参、增删改查示例 -- [spring-boot-memcache-spymemcached](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-memcache-spymemcached) :Spring Boot 使用 spymemcached 集成 memcache 示例 +## 示例代码 -**参考文章** +- [spring-boot-hello](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-hello):Spring Boot 3.0 Hello World 示例 +- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-hello):Spring Boot 3.0 定制 banner 示例 +- [spring-boot-helloworld](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-helloWorld):Spring Boot 3.0 Hello World Test 单元测试示例 +- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-scheduler):Spring Boot 3.0 定时任务 scheduler 使用示例 +- [spring-boot-package](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package):Spring Boot 3.0 单元测试、集成测试、打 Jar/War 包、定制启动参数使用案例 +- [spring-boot-commandLineRunner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-commandLineRunner):Spring Boot 3.0 目启动时初始化资源案例 +- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web):Spring Boot 3.0 web 示例 +- [spring-boot-webflux](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-webflux):Spring Boot 3.0 响应式编程 WebFlux 使用案例 +- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-file-upload):Spring Boot 3.0 上传文件使用案例 +- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-thymeleaf):Spring Boot 3.0 Thymeleaf 语法、布局使用示例 +- [spring-boot-jpa](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-jpa):Spring Boot 3.0 Jpa 操作、增删、改查多数据源使用示例 +- [spring-boot-mybatis](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis):Spring Boot 3.0 Mybatis 注解、xml 使用、增删改查、多数据源使用示例 +- [spring-boot-web-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web-thymeleaf):Spring Boot 3.0 thymeleaf 增删该查示例 +- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-jpa-thymeleaf-curd):Spring Boot 3.0 Jpa thymeleaf 列表、增删改查使用案例 +- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mail):Spring Boot 3.0 邮件发送使用示例 +- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-rabbitmq):Spring Boot 3.0 RabbitMQ 各种常见场景使用示例 +- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):Spring Boot 3.0 MongoDB 增删改查示例 多数据源使用案例 +- [spring-boot-redis](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-redis):Spring Boot 3.0 Redis 示例 +- [spring-boot-memcache-spymemcached](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-memcache-spymemcached):Spring Boot 3.0 集成 Memcached 使用案例 +- [spring-boot-docker](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-docker):Spring Boot 3.0 Docker 使用案例 +- [dockercompose-springboot-mysql-nginx](https://github.com/ityouknow/spring-boot-examples/tree/master/dockercompose-springboot-mysql-nginx):Spring Boot 3.0 Docker Compose + Spring Boot + Nginx + Mysql 使用案例 -- [Spring Boot 2.0(一):【重磅】Spring Boot 2.0权威发布](http://www.ityouknow.com/springboot/2018/03/01/spring-boot-2.0.html) -- [Spring Boot 2.0(二):Spring Boot 2.0尝鲜-动态 Banner](http://www.ityouknow.com/springboot/2018/03/03/spring-boot-banner.html) -- [Spring Boot 2.0(三):Spring Boot 开源软件都有哪些?](http://www.ityouknow.com/springboot/2018/03/05/spring-boot-open-source.html) -- [Spring Boot 2.0(四):使用 Docker 部署 Spring Boot](http://www.ityouknow.com/springboot/2018/03/19/spring-boot-docker.html) -- [Spring Boot 2.0(五):Docker Compose + Spring Boot + Nginx + Mysql 实践](http://www.ityouknow.com/springboot/2018/03/28/dockercompose-springboot-mysql-nginx.html) -- [Spring Boot 2.0(六):使用 Docker 部署 Spring Boot 开源软件云收藏](http://www.ityouknow.com/springboot/2018/04/02/docker-favorites.html) -- [Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源](http://www.ityouknow.com/springboot/2018/05/03/spring-boot-commandLineRunner.html) -- [Spring Boot 2.0(八):Spring Boot 集成 Memcached](http://www.ityouknow.com/springboot/2018/09/01/spring-boot-memcached.html) ---- - -## Spring Boot 1.0 - -**示例代码** - -- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-helloWorld):spring-boot的helloWorld版本 -- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-annotation):注解版本 -- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-xml):xml配置版本 -- [spring-boot-mybatis-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-mulidatasource):springboot+mybatis多数据源最简解决方案 -- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-annotation-mulidatasource):springboot+mybatis(注解版)多数据源最简解决方案 -- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-thymeleaf):simple spring boot thymeleaf demo -- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-jpa-thymeleaf-curd):spring boot + jpa + thymeleaf 增删改查示例 -- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-rabbitmq):spring boot和rabbitmq各种消息应用案例 -- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-scheduler):spring boot和定时任务案例 -- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web):web开发综合使用案例 -- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mail):spring boot和邮件服务 -- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):spring boot和mongodb的使用 -- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):spring boot和mongodb多数据源的使用 -- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):spring-boot打包成war包示例 -- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-shiro):springboot 整合shiro rbac示例 -- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-file-upload):使用Spring Boot 上传文件示例 -- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-fastDFS):Spring Boot 整合FastDFS示例 -- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-actuator):Spring Boot Actuator 使用示例 -- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-admin-simple):Spring Boot Admin 的使用示例 - -**参考文章** - -- [springboot(一):入门篇](http://www.ityouknow.com/springboot/2016/01/06/spring-boot-quick-start.html) -- [springboot(二):web综合开发](http://www.ityouknow.com/springboot/2016/02/03/spring-boot-web.html) -- [springboot(三):Spring boot中Redis的使用](http://www.ityouknow.com/springboot/2016/03/06/spring-boot-redis.html) -- [springboot(四):thymeleaf使用详解](http://www.ityouknow.com/springboot/2016/05/01/spring-boot-thymeleaf.html) -- [springboot(五):spring data jpa的使用](http://www.ityouknow.com/springboot/2016/08/20/spring-boo-jpa.html) -- [springboot(六):如何优雅的使用mybatis](http://www.ityouknow.com/springboot/2016/11/06/spring-boo-mybatis.html) -- [springboot(七):springboot+mybatis多数据源最简解决方案](http://www.ityouknow.com/springboot/2016/11/25/spring-boot-multi-mybatis.html) -- [springboot(八):RabbitMQ详解](http://www.ityouknow.com/springboot/2016/11/30/spring-boot-rabbitMQ.html) -- [springboot(九):定时任务](http://www.ityouknow.com/springboot/2016/12/02/spring-boot-scheduler.html) -- [springboot(十):邮件服务](http://www.ityouknow.com/springboot/2017/05/06/springboot-mail.html) -- [springboot(十一):Spring boot中mongodb的使用](http://www.ityouknow.com/springboot/2017/05/08/springboot-mongodb.html) -- [springboot(十二):springboot如何测试打包部署](http://www.ityouknow.com/springboot/2017/05/09/springboot-deploy.html) -- [springboot(十三):springboot小技巧](http://www.ityouknow.com/springboot/2017/06/22/springboot-tips.html) -- [springboot(十四):springboot整合shiro-登录认证和权限管理](http://www.ityouknow.com/springboot/2017/06/26/springboot-shiro.html) -- [springboot(十五):springboot+jpa+thymeleaf增删改查示例](http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html) -- [springboot(十六):使用Jenkins部署Spring Boot](http://www.ityouknow.com/springboot/2017/11/11/springboot-jenkins.html) -- [springboot(十七):使用Spring Boot上传文件](http://www.ityouknow.com/springboot/2018/01/12/spring-boot-upload-file.html) -- [springboot(十八):使用Spring Boot集成FastDFS](http://www.ityouknow.com/springboot/2018/01/16/spring-boot-fastdfs.html) -- [springboot(十九):使用Spring Boot Actuator监控应用](http://www.ityouknow.com/springboot/2018/02/06/spring-boot-actuator.html) -- [springboot(二十):使用spring-boot-admin对spring-boot服务进行监控](http://www.ityouknow.com/springboot/2018/02/11/spring-boot-admin.html) - -**[Spring Boot 实战:我们的第一款开源项目](http://www.ityouknow.com/springboot/2016/09/26/spring-boot-opensource-favorites.html)** - ---- > 如果大家想了解关于 Spring Boot 的其它方面应用,也可以以[issues](https://github.com/ityouknow/spring-boot-examples/issues)的形式反馈给我,我后续来完善。 -关注公众号:纯洁的微笑,回复"springboot"进群交流 +关注公众号:纯洁的微笑,回复"666"进群交流 ![](http://www.ityouknow.com/assets/images/keeppuresmile_430.jpg) \ No newline at end of file diff --git a/README_EN.md b/README_EN.md deleted file mode 100644 index 3e465b938..000000000 --- a/README_EN.md +++ /dev/null @@ -1,49 +0,0 @@ -# Spring Boot Examples - -This tutorial is about learning Spring Boot via examples. - - -[Spring Cloud example code](https://github.com/ityouknow/spring-cloud-examples)  |   [中文](README.md) - -Spring Boot examples, using the simplest and the most useful scene demos. - ---- - -## Spring Boot 2.0 - - -**[Favorites-web](https://github.com/cloudfavorites/favorites-web):Open source projects developed using Spring Boot 2.0** - -- [spring-boot-hello](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-hello):Spring Boot 2.0 Hello World Demo -- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-banner):Spring Boot Customized Banner -- [spring-boot-docker](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-banner):Spring Boot with Docker -- [dockercompose-springboot-mysql-nginx](https://github.com/ityouknow/spring-boot-examples/tree/master/dockercompose-springboot-mysql-nginx) :Docker Compose + Spring Boot + Nginx + Mysql example -- [spring-boot-commandLineRunner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-commandLineRunner) :Example of resource initialization at project startup using Spring Boot and commandLineRunner -- [spring-boot-web-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web-thymeleaf) :Spring Boot uses thymeleaf to implement layout, check parameters and CURD -- [spring-boot-memcache-spymemcached](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-memcache-spymemcached) :Spring Boot uses spymemcached to memcache - - ---- - -## Spring Boot 1.0 - -- [spring-boot-helloWorld](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-helloWorld):Spring Boot helloWorld -- [spring-boot-mybaits-annotation](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-annotation):Spring Boot use mybatis annotation -- [spring-boot-mybaits-xml](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-xml):Spring Boot use mybatis xml -- [spring-boot-mybatis-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-mulidatasource):Spring Boot+mybatis+mulidatasource -- [spring-boot-mybatis-annotation-mulidatasource](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mybatis-annotation-mulidatasource):Spring Boot+ mybatis annotation + mulidatasource -- [spring-boot-thymeleaf](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-thymeleaf):simple spring boot thymeleaf demo -- [spring-boot-jpa-thymeleaf-curd](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-jpa-thymeleaf-curd):spring boot + jpa + thymeleaf curd demo -- [spring-boot-rabbitmq](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-rabbitmq): using AMQP and RabbitMQ -- [spring-boot-scheduler](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-scheduler):Timed tasks developed using Spring Boot -- [spring-boot-web](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-web):Web projects developed using Spring Boot -- [spring-boot-mail](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mail):Mail system developed using Spring Boot -- [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):Spring Boot + Mongodb -- [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):Spring Boot + multiMongodb -- [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):Spring Boot package war -- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-shiro):spring boot shiro rbac demo -- [spring-boot-file-upload](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-file-upload):Spring Boot upload file demo -- [spring-boot-fastDFS](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-fastDFS):Spring Boot Integrate FastDFS upload delete and so on -- [spring-boot-actuator](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-actuator):Spring Boot Actuator demo -- [spring-boot-admin-simple](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-admin-simple):Spring Boot Admin demo -- [spring-boot-banner](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-banner):Spring Boot Cumtom Banner diff --git a/dockercompose-springboot-mysql-nginx/app/Dockerfile b/dockercompose-springboot-mysql-nginx/app/Dockerfile index 6ae65e4e7..128ca1d00 100644 --- a/dockercompose-springboot-mysql-nginx/app/Dockerfile +++ b/dockercompose-springboot-mysql-nginx/app/Dockerfile @@ -1 +1 @@ -FROM maven:3.5-jdk-8 \ No newline at end of file +FROM maven:3.8.3-openjdk-17 diff --git a/dockercompose-springboot-mysql-nginx/app/pom.xml b/dockercompose-springboot-mysql-nginx/app/pom.xml index 1dc59f64b..4a8f04b98 100644 --- a/dockercompose-springboot-mysql-nginx/app/pom.xml +++ b/dockercompose-springboot-mysql-nginx/app/pom.xml @@ -14,12 +14,13 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 UTF-8 - 1.8 + UTF-8 + 17 @@ -38,7 +39,17 @@ org.springframework.boot spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine test + + + org.hamcrest + hamcrest-core + + diff --git a/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java b/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java index 583be103f..a73a030e0 100644 --- a/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java +++ b/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/controller/VisitorController.java @@ -6,7 +6,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; @RestController public class VisitorController { diff --git a/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java b/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java index 43cfa34b0..8db97fe96 100644 --- a/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java +++ b/dockercompose-springboot-mysql-nginx/app/src/main/java/com/neo/entity/Visitor.java @@ -1,9 +1,9 @@ package com.neo.entity; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; @Entity public class Visitor { diff --git a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties index 25126f01f..0d8ae3646 100644 --- a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties +++ b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-dev.properties @@ -1,4 +1,4 @@ spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.jdbc.Driver \ No newline at end of file +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties index eacae6203..60acaa93e 100644 --- a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties +++ b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application-docker.properties @@ -1,4 +1,4 @@ spring.datasource.url=jdbc:mysql://mysql:3306/test spring.datasource.username=root spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.jdbc.Driver \ No newline at end of file +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties index 242edfd64..c6c99312c 100644 --- a/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties +++ b/dockercompose-springboot-mysql-nginx/app/src/main/resources/application.properties @@ -1,5 +1,5 @@ spring.jpa.properties.hibernate.hbm2ddl.auto=update -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.jpa.show-sql=true spring.profiles.active=dev \ No newline at end of file diff --git a/dockercompose-springboot-mysql-nginx/docker-compose.yaml b/dockercompose-springboot-mysql-nginx/docker-compose.yaml index 028978f5b..ba38d573f 100644 --- a/dockercompose-springboot-mysql-nginx/docker-compose.yaml +++ b/dockercompose-springboot-mysql-nginx/docker-compose.yaml @@ -5,8 +5,8 @@ services: image: nginx:1.13 restart: always ports: - - 80:80 - - 443:443 + - 81:81 + - 445:445 volumes: - ./nginx/conf.d:/etc/nginx/conf.d @@ -18,7 +18,7 @@ services: MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_HOST: '%' ports: - - "3306:3306" + - "3308:3308" restart: always app: diff --git a/spring-boot-banner/pom.xml b/spring-boot-banner/pom.xml index 763b87317..bb57ab10c 100644 --- a/spring-boot-banner/pom.xml +++ b/spring-boot-banner/pom.xml @@ -5,7 +5,7 @@ com.example spring-boot-banner - 2.0.0 + 3.0.0 jar Spring Boot banner @@ -14,13 +14,14 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 + UTF-8 UTF-8 - 1.8 + 17 diff --git a/spring-boot-commandLineRunner/pom.xml b/spring-boot-commandLineRunner/pom.xml index 3dd6ee720..651f81439 100644 --- a/spring-boot-commandLineRunner/pom.xml +++ b/spring-boot-commandLineRunner/pom.xml @@ -14,13 +14,13 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 UTF-8 UTF-8 - 1.8 + 17 diff --git a/spring-boot-docker/pom.xml b/spring-boot-docker/pom.xml index 17946da0c..0854143e9 100644 --- a/spring-boot-docker/pom.xml +++ b/spring-boot-docker/pom.xml @@ -14,15 +14,17 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 UTF-8 - 1.8 + UTF-8 + 17 springboot + org.springframework.boot @@ -31,7 +33,17 @@ org.springframework.boot spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine test + + + org.hamcrest + hamcrest-core + + diff --git a/spring-boot-docker/src/main/docker/Dockerfile b/spring-boot-docker/src/main/docker/Dockerfile index be52a4852..153350ca8 100644 --- a/spring-boot-docker/src/main/docker/Dockerfile +++ b/spring-boot-docker/src/main/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:8-jdk-alpine +FROM openjdk:17-jdk-alpine VOLUME /tmp ADD spring-boot-docker-1.0.jar app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] \ No newline at end of file diff --git a/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java b/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java index b08b68913..341a10378 100644 --- a/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java +++ b/spring-boot-docker/src/test/java/com/neo/DockerApplicationTests.java @@ -3,7 +3,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) diff --git a/spring-boot-file-upload/pom.xml b/spring-boot-file-upload/pom.xml index 731cfa08c..fd25297d2 100644 --- a/spring-boot-file-upload/pom.xml +++ b/spring-boot-file-upload/pom.xml @@ -12,11 +12,13 @@ org.springframework.boot spring-boot-starter-parent - 1.5.9.RELEASE + 3.0.0 + - 1.8 + UTF-8 + 17 @@ -28,12 +30,6 @@ org.springframework.boot spring-boot-starter-thymeleaf
- - org.springframework.boot - spring-boot-devtools - true - - diff --git a/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java b/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java index 6e355e38d..059ae73fc 100644 --- a/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java +++ b/spring-boot-file-upload/src/main/java/com/neo/FileUploadWebApplication.java @@ -3,8 +3,8 @@ import org.apache.coyote.http11.AbstractHttp11Protocol; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; -import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.context.annotation.Bean; @SpringBootApplication @@ -16,8 +16,8 @@ public static void main(String[] args) throws Exception { //Tomcat large file upload connection reset @Bean - public TomcatEmbeddedServletContainerFactory tomcatEmbedded() { - TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); + public TomcatServletWebServerFactory tomcatEmbedded() { + TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { //-1 means unlimited diff --git a/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java b/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java index 8f5caf6cc..fb39f468e 100644 --- a/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java +++ b/spring-boot-file-upload/src/main/java/com/neo/controller/GlobalExceptionHandler.java @@ -12,7 +12,8 @@ public class GlobalExceptionHandler { //4.3.5 supports RedirectAttributes redirectAttributes @ExceptionHandler(MultipartException.class) public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { - redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); + System.out.printf(e.getMessage()); + redirectAttributes.addFlashAttribute("message", e.getMessage()); return "redirect:/uploadStatus"; } } diff --git a/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java b/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java index 13d3ab467..f72b2026a 100644 --- a/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java +++ b/spring-boot-file-upload/src/main/java/com/neo/controller/UploadController.java @@ -24,7 +24,7 @@ public String index() { @PostMapping("/upload") // //new annotation since 4.3 public String singleFileUpload(@RequestParam("file") MultipartFile file, - RedirectAttributes redirectAttributes) { + RedirectAttributes redirectAttributes) { if (file.isEmpty()) { redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); return "redirect:uploadStatus"; @@ -33,16 +33,20 @@ public String singleFileUpload(@RequestParam("file") MultipartFile file, try { // Get the file and save it somewhere byte[] bytes = file.getBytes(); + Path dir = Paths.get(UPLOADED_FOLDER); Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); + // Create parent dir if not exists + if(!Files.exists(dir)) { + Files.createDirectories(dir); + } Files.write(path, bytes); - redirectAttributes.addFlashAttribute("message", - "You successfully uploaded '" + file.getOriginalFilename() + "'"); + "You successfully uploaded '" + file.getOriginalFilename() + "'"); } catch (IOException e) { + redirectAttributes.addFlashAttribute("message", "Server throw IOException"); e.printStackTrace(); } - return "redirect:/uploadStatus"; } diff --git a/spring-boot-file-upload/src/main/resources/application.properties b/spring-boot-file-upload/src/main/resources/application.properties index 8ec671da4..9df793bc3 100644 --- a/spring-boot-file-upload/src/main/resources/application.properties +++ b/spring-boot-file-upload/src/main/resources/application.properties @@ -1,11 +1,4 @@ #http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties #search multipart -spring.http.multipart.max-file-size=10MB -spring.http.multipart.max-request-size=10MB - -#spring.http.multipart.enabled=true #\u9ED8\u8BA4\u652F\u6301\u6587\u4EF6\u4E0A\u4F20. -#spring.http.multipart.file-size-threshold=0 #\u652F\u6301\u6587\u4EF6\u5199\u5165\u78C1\u76D8. -#spring.http.multipart.location= # \u4E0A\u4F20\u6587\u4EF6\u7684\u4E34\u65F6\u76EE\u5F55 -#spring.http.multipart.max-file-size=1Mb # \u6700\u5927\u652F\u6301\u6587\u4EF6\u5927\u5C0F -#spring.http.multipart.max-request-size=10Mb # \u6700\u5927\u652F\u6301\u8BF7\u6C42\u5927\u5C0F - +spring.servlet.multipart.max-file-size=10000MB +spring.servlet.multipart.max-request-size=10000MB \ No newline at end of file diff --git a/spring-boot-hello/pom.xml b/spring-boot-hello/pom.xml index eba435698..ae54d9067 100644 --- a/spring-boot-hello/pom.xml +++ b/spring-boot-hello/pom.xml @@ -14,12 +14,13 @@ org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 + UTF-8 - 1.8 + 17 @@ -30,7 +31,6 @@ org.springframework.boot spring-boot-starter-test - test diff --git a/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java b/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java index 2c1c06de1..c6da75a69 100644 --- a/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java +++ b/spring-boot-hello/src/main/java/com/neo/controller/HelloController.java @@ -8,6 +8,6 @@ public class HelloController { @RequestMapping("/") public String index() { - return "Hello Spring Boot 2.0!"; + return "Hello Spring Boot 3.x!"; } } \ No newline at end of file diff --git a/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java b/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java index 09ba4ff06..0c8be4b44 100644 --- a/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java +++ b/spring-boot-hello/src/test/java/com/neo/HelloApplicationTests.java @@ -1,18 +1,16 @@ package com.neo; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) + @SpringBootTest public class HelloApplicationTests { + @Test - public void contextLoads() { - System.out.println("Hello Spring Boot 2.0!"); + void contextLoads() { + System.out.println("Hello Spring Boot 2.x!"); } } diff --git a/spring-boot-helloWorld/pom.xml b/spring-boot-helloWorld/pom.xml index c8280ef2e..039ba9688 100644 --- a/spring-boot-helloWorld/pom.xml +++ b/spring-boot-helloWorld/pom.xml @@ -5,7 +5,7 @@ com.neo spring-boot-helloworld - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT jar spring-boot-helloworld @@ -14,46 +14,43 @@ org.springframework.boot spring-boot-starter-parent - 1.5.6.RELEASE + 3.0.0 UTF-8 - 1.8 + 17 org.springframework.boot - spring-boot-starter + spring-boot-starter-web - org.springframework.boot spring-boot-starter-test test - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-devtools - true + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + - + org.springframework.boot spring-boot-maven-plugin - - true - diff --git a/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java b/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java index 1faf3f2e7..7fca0a8d3 100644 --- a/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java +++ b/spring-boot-helloWorld/src/test/java/com/neo/ApplicationTests.java @@ -1,12 +1,8 @@ package com.neo; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { diff --git a/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java b/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java index d42211135..987f9eb7f 100644 --- a/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java +++ b/spring-boot-helloWorld/src/test/java/com/neo/controller/HelloTests.java @@ -1,39 +1,37 @@ package com.neo.controller; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.http.MediaType; -import org.springframework.mock.web.MockServletContext; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; + import static org.hamcrest.Matchers.equalTo; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringRunner.class) -@SpringBootTest +@WebMvcTest(HelloWorldController.class) public class HelloTests { - + @Autowired private MockMvc mvc; - @Before - public void setUp() throws Exception { - mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); - } - @Test public void getHello() throws Exception { - mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(content().string(equalTo("Hello World"))); + mvc.perform(MockMvcRequestBuilders + .get("/hello") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andExpect(content() + .string(equalTo("Hello World"))); } } \ No newline at end of file diff --git a/spring-boot-jpa-thymeleaf-curd/pom.xml b/spring-boot-jpa-thymeleaf-curd/pom.xml index caa8ecc56..49c037386 100644 --- a/spring-boot-jpa-thymeleaf-curd/pom.xml +++ b/spring-boot-jpa-thymeleaf-curd/pom.xml @@ -7,11 +7,13 @@ org.springframework.boot spring-boot-starter-parent - 1.5.6.RELEASE + 3.0.0 + - 1.8 + UTF-8 + 17 @@ -31,20 +33,12 @@ mysql mysql-connector-java - - org.springframework.boot - spring-boot-devtools - true - org.springframework.boot spring-boot-maven-plugin - - true - diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java index 92f4c0aec..20dc3f130 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/JpaThymeleafApplication.java @@ -3,7 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..c8f9f1c59 --- /dev/null +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/model/User.java @@ -0,0 +1,55 @@ +package com.neo.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class User { + @Id + @GeneratedValue + private long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String password; + @Column(nullable = false) + private int age; + + public long getId() { + return id; + } + + public User setId(long id) { + this.id = id; + return this; + } + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public String getPassword() { + return password; + } + + public User setPassword(String password) { + this.password = password; + return this; + } + + public int getAge() { + return age; + } + + public User setAge(int age) { + this.age = age; + return this; + } +} diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java index 14821f515..f6a00c8c3 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/repository/UserRepository.java @@ -1,11 +1,11 @@ package com.neo.repository; -import com.neo.entity.User; +import com.neo.model.User; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository { User findById(long id); - Long deleteById(Long id); + void deleteById(Long id); } \ No newline at end of file diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java index be9becb4e..ba82b95f2 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/UserService.java @@ -1,6 +1,6 @@ package com.neo.service; -import com.neo.entity.User; +import com.neo.model.User; import java.util.List; diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java index 8e66fad24..a8a956174 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/service/impl/UserServiceImpl.java @@ -1,12 +1,11 @@ package com.neo.service.impl; -import com.neo.entity.User; +import com.neo.model.User; import com.neo.repository.UserRepository; import com.neo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.List; @Service @@ -37,7 +36,7 @@ public void edit(User user) { @Override public void delete(long id) { - userRepository.delete(id); + userRepository.deleteById(id); } } diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java index 02eef58ae..c8800eaa7 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java +++ b/spring-boot-jpa-thymeleaf-curd/src/main/java/com/neo/web/UserController.java @@ -1,14 +1,12 @@ package com.neo.web; -import com.neo.entity.User; +import com.neo.model.User; import com.neo.service.UserService; import org.springframework.stereotype.Controller; -import org.springframework.stereotype.Service; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import java.util.List; @Controller diff --git a/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties b/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties index 65ff9c384..b01900159 100644 --- a/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties +++ b/spring-boot-jpa-thymeleaf-curd/src/main/resources/application.properties @@ -1,10 +1,10 @@ spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true spring.datasource.username=root spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver -spring.jpa.properties.hibernate.hbm2ddl.auto=update -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.jpa.show-sql= true -spring.thymeleaf.cache=false \ No newline at end of file +spring.thymeleaf.cache=false diff --git a/spring-boot-jpa/spring-boot-jpa/pom.xml b/spring-boot-jpa/spring-boot-jpa/pom.xml new file mode 100644 index 000000000..8bf9a79ba --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + com.neo + spring-boot-Jpa + 1.0.0 + jar + + spring-boot-Jpa + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java new file mode 100644 index 000000000..7df2339ea --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/JpaApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JpaApplication { + + public static void main(String[] args) { + SpringApplication.run(JpaApplication.class, args); + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java new file mode 100644 index 000000000..973364706 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/Address.java @@ -0,0 +1,59 @@ +package com.neo.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class Address { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, length = 30) + private Long userId; + private String province; + private String city; + private String street; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..d82b98d99 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/User.java @@ -0,0 +1,83 @@ +package com.neo.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class User { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true, length = 30) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true, length = 30) + private String email; + @Column(nullable = true, unique = true, length = 30) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + } + + public User(String userName, String passWord, String email, String nickName, String regTime) { + this.userName = userName; + this.passWord = passWord; + this.email = email; + this.nickName = nickName; + this.regTime = regTime; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java new file mode 100644 index 000000000..0f11f0527 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserDetail.java @@ -0,0 +1,102 @@ +package com.neo.model; + + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import jakarta.persistence.*; +import java.io.Serializable; + +@Entity +public class UserDetail { + + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true, length = 30) + private Long userId; + private Integer age; + private String realName; + private String status; + private String hobby; + private String introduction; + private String lastLoginIp; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getHobby() { + return hobby; + } + + public void setHobby(String hobby) { + this.hobby = hobby; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public String getLastLoginIp() { + return lastLoginIp; + } + + public void setLastLoginIp(String lastLoginIp) { + this.lastLoginIp = lastLoginIp; + } + + @Override + public String toString() { + return "UserDetail{" + + "id=" + id + + ", userId=" + userId + + ", age=" + age + + ", realName='" + realName + '\'' + + ", status='" + status + '\'' + + ", hobby='" + hobby + '\'' + + ", introduction='" + introduction + '\'' + + ", lastLoginIp='" + lastLoginIp + '\'' + + '}'; + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java new file mode 100644 index 000000000..5a5ae5eb3 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/model/UserInfo.java @@ -0,0 +1,8 @@ +package com.neo.model; + +public interface UserInfo { + String getUserName(); + String getEmail(); + String getHobby(); + String getIntroduction(); +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java new file mode 100644 index 000000000..b87af7fec --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/param/UserDetailParam.java @@ -0,0 +1,65 @@ +package com.neo.param; + + +import com.neo.model.Address; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import jakarta.persistence.*; + +public class UserDetailParam { + private String userId; + private Integer minAge; + private Integer maxAge; + private String realName; + private String introduction; + private String city; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Integer getMinAge() { + return minAge; + } + + public void setMinAge(Integer minAge) { + this.minAge = minAge; + } + + public Integer getMaxAge() { + return maxAge; + } + + public void setMaxAge(Integer maxAge) { + this.maxAge = maxAge; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java new file mode 100644 index 000000000..3bba02753 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/AddressRepository.java @@ -0,0 +1,7 @@ +package com.neo.repository; + +import com.neo.model.Address; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AddressRepository extends JpaRepository { +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java new file mode 100644 index 000000000..e133b0564 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserDetailRepository.java @@ -0,0 +1,20 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.model.UserDetail; +import com.neo.model.UserInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + + +public interface UserDetailRepository extends JpaSpecificationExecutor,JpaRepository { + + UserDetail findByHobby(String hobby); + + @Query("select u.userName as userName, u.email as email, d.introduction as introduction , d.hobby as hobby from User u , UserDetail d " + + "where u.id=d.userId and d.hobby = ?1 ") + List findUserInfo(String hobby); +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..8318068a5 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,40 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.transaction.annotation.Transactional; + + +public interface UserRepository extends JpaRepository { + + User findByUserName(String userName); + + User findByUserNameOrEmail(String username, String email); + + @Transactional(timeout = 10) + @Modifying + @Query("update User set userName = ?1 where id = ?2") + int modifyById(String userName, Long id); + + @Transactional + @Modifying + @Query("delete from User where id = ?1") + void deleteById(Long id); + + @Query("select u from User u where u.email = ?1") + User findByEmail(String email); + + @Query("select u from User u") + Page findALL(Pageable pageable); + + Page findByNickName(String nickName, Pageable pageable); + + Slice findByNickNameAndEmail(String nickName, String email,Pageable pageable); + + +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java new file mode 100644 index 000000000..a5d14ead7 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailService.java @@ -0,0 +1,10 @@ +package com.neo.service; + +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface UserDetailService { + public Page findByCondition(UserDetailParam detailParam, Pageable pageable); +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java new file mode 100644 index 000000000..bc38ec475 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/java/com/neo/service/UserDetailServiceImpl.java @@ -0,0 +1,48 @@ +package com.neo.service; + +import com.mysql.cj.util.StringUtils; +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import com.neo.repository.UserDetailRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import jakarta.persistence.criteria.Predicate; +import java.util.ArrayList; +import java.util.List; + +@Service +public class UserDetailServiceImpl implements UserDetailService{ + + @Resource + private UserDetailRepository userDetailRepository; + + @Override + public Page findByCondition(UserDetailParam detailParam, Pageable pageable){ + + return userDetailRepository.findAll((root, query, cb) -> { + List predicates = new ArrayList(); + //equal 示例 + if (!StringUtils.isNullOrEmpty(detailParam.getIntroduction())){ + predicates.add(cb.equal(root.get("introduction"),detailParam.getIntroduction())); + } + //like 示例 + if (!StringUtils.isNullOrEmpty(detailParam.getRealName())){ + predicates.add(cb.like(root.get("realName"),"%"+detailParam.getRealName()+"%")); + } + //between 示例 + if (detailParam.getMinAge()!=null && detailParam.getMaxAge()!=null) { + Predicate agePredicate = cb.between(root.get("age"), detailParam.getMinAge(), detailParam.getMaxAge()); + predicates.add(agePredicate); + } + //greaterThan 大于等于示例 + if (detailParam.getMinAge()!=null){ + predicates.add(cb.greaterThan(root.get("age"),detailParam.getMinAge())); + } + return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); + }, pageable); + + } +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties b/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties new file mode 100644 index 000000000..bdde31fb0 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.hikari.maxLifeTime=600000 + +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect +#sql\u8F93\u51FA +spring.jpa.show-sql=true +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java new file mode 100644 index 000000000..4fe4fdbe0 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/JpaApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class JpaApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java new file mode 100644 index 000000000..312f78713 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/JpaSpecificationTests.java @@ -0,0 +1,38 @@ +package com.neo.repository; + +import com.neo.model.UserDetail; +import com.neo.param.UserDetailParam; +import com.neo.service.UserDetailService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import jakarta.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class JpaSpecificationTests { + + @Resource + private UserDetailService userDetailService; + + @Test + public void testFindByCondition() { + int page=0,size=10; + Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending()); + UserDetailParam param=new UserDetailParam(); + param.setIntroduction("程序员"); + param.setMinAge(10); + param.setMaxAge(30); + Page page1=userDetailService.findByCondition(param,pageable); + for (UserDetail userDetail:page1){ + System.out.println("userDetail: "+userDetail.toString()); + } + } + +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java new file mode 100644 index 000000000..08918cbb7 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserDetailRepositoryTests.java @@ -0,0 +1,55 @@ +package com.neo.repository; + +import com.neo.model.Address; +import com.neo.model.UserDetail; +import com.neo.model.UserInfo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import jakarta.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserDetailRepositoryTests { + + @Resource + private AddressRepository addressRepository; + @Resource + private UserDetailRepository userDetailRepository; + + @Test + public void testSaveAddress() { + Address address=new Address(); + address.setUserId(1L); + address.setCity("北京"); + address.setProvince("北京"); + address.setStreet("分钟寺"); + addressRepository.save(address); + } + + @Test + public void testSaveUserDetail() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + UserDetail userDetail=new UserDetail(); + userDetail.setUserId(3L); + userDetail.setHobby("吃鸡游戏"); + userDetail.setAge(28); + userDetail.setIntroduction("一个爱玩的人"); + userDetailRepository.save(userDetail); + } + + @Test + public void testUserInfo() { + List userInfos=userDetailRepository.findUserInfo("钓鱼"); + for (UserInfo userInfo:userInfos){ + System.out.println("userInfo: "+userInfo.getUserName()+"-"+userInfo.getEmail()+"-"+userInfo.getHobby()+"-"+userInfo.getIntroduction()); + } + } +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java new file mode 100644 index 000000000..13bab28a7 --- /dev/null +++ b/spring-boot-jpa/spring-boot-jpa/src/test/java/com/neo/repository/UserRepositoryTests.java @@ -0,0 +1,70 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import jakarta.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + + @Resource + private UserRepository userRepository; + + @Test + public void testSave() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userRepository.save(new User("aa", "aa123456","aa@126.com", "aa", formattedDate)); + userRepository.save(new User("bb", "bb123456","bb@126.com", "bb", formattedDate)); + userRepository.save(new User("cc", "cc123456","cc@126.com", "cc", formattedDate)); + +// Assert.assertEquals(3, userRepository.findAll().size()); +// Assert.assertEquals("bb", userRepository.findByUserNameOrEmail("bb", "bb@126.com").getNickName()); +// userRepository.delete(userRepository.findByUserName("aa")); + } + + + @Test + public void testBaseQuery() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + User user=new User("ff", "ff123456","ff@126.com", "ff", formattedDate); + userRepository.findAll(); + userRepository.findById(3L); + userRepository.save(user); + user.setId(2L); + userRepository.delete(user); + userRepository.count(); + userRepository.existsById(3L); + } + + @Test + public void testCustomSql() { + userRepository.modifyById("neo",3L); + userRepository.deleteById(3L); + userRepository.findByEmail("ff@126.com"); + } + + + @Test + public void testPageQuery() { + int page=1,size=2; + Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending()); + userRepository.findALL(pageable); + userRepository.findByNickName("aa", pageable); + } + +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml b/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml new file mode 100644 index 000000000..f6a223772 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + com.neo + spring-boot-multi-Jpa + 1.0 + jar + + spring-boot-multi-Jpa + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java new file mode 100644 index 000000000..2a9a26b17 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/MultiJpaApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultiJpaApplication { + + public static void main(String[] args) { + SpringApplication.run(MultiJpaApplication.class, args); + } +} diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java new file mode 100644 index 000000000..09f2b757d --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/DataSourceConfig.java @@ -0,0 +1,41 @@ +package com.neo.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings; +import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import javax.sql.DataSource; +import java.util.Map; + +@Configuration +public class DataSourceConfig { + + @Autowired + private JpaProperties jpaProperties; + @Autowired + private HibernateProperties hibernateProperties; + + @Bean(name = "primaryDataSource") + @Primary + @ConfigurationProperties("spring.datasource.primary") + public DataSource firstDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "secondaryDataSource") + @ConfigurationProperties("spring.datasource.secondary") + public DataSource secondDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "vendorProperties") + public Map getVendorProperties() { + return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings()); + } +} diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java new file mode 100644 index 000000000..068ac84fd --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/PrimaryConfig.java @@ -0,0 +1,59 @@ +package com.neo.config; + +import java.util.Map; + +import jakarta.persistence.EntityManager; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef="entityManagerFactoryPrimary", + transactionManagerRef="transactionManagerPrimary", + basePackages= { "com.neo.repository.test1" })//设置dao(repo)所在位置 +public class PrimaryConfig { + + @Autowired + @Qualifier("primaryDataSource") + private DataSource primaryDataSource; + + @Autowired + @Qualifier("vendorProperties") + private Map vendorProperties; + + @Bean(name = "entityManagerFactoryPrimary") + @Primary + public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) { + return builder + .dataSource(primaryDataSource) + .properties(vendorProperties) + .packages("com.neo.model") //设置实体类所在位置 + .persistenceUnit("primaryPersistenceUnit") + .build(); + } + + @Bean(name = "entityManagerPrimary") + @Primary + public EntityManager entityManager(EntityManagerFactoryBuilder builder) { + return entityManagerFactoryPrimary(builder).getObject().createEntityManager(); + } + + @Bean(name = "transactionManagerPrimary") + @Primary + PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) { + return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject()); + } + +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java new file mode 100644 index 000000000..81d35be79 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/config/SecondaryConfig.java @@ -0,0 +1,54 @@ +package com.neo.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.context.annotation.Bean; +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.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import jakarta.persistence.EntityManager; +import javax.sql.DataSource; +import java.util.Map; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef="entityManagerFactorySecondary", + transactionManagerRef="transactionManagerSecondary", + basePackages= { "com.neo.repository.test2" }) +public class SecondaryConfig { + + @Autowired + @Qualifier("secondaryDataSource") + private DataSource secondaryDataSource; + + @Autowired + @Qualifier("vendorProperties") + private Map vendorProperties; + + @Bean(name = "entityManagerFactorySecondary") + public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary (EntityManagerFactoryBuilder builder) { + return builder + .dataSource(secondaryDataSource) + .properties(vendorProperties) + .packages("com.neo.model") + .persistenceUnit("secondaryPersistenceUnit") + .build(); + } + + @Bean(name = "entityManagerSecondary") + public EntityManager entityManager(EntityManagerFactoryBuilder builder) { + return entityManagerFactorySecondary(builder).getObject().createEntityManager(); + } + + @Bean(name = "transactionManagerSecondary") + PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) { + return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject()); + } + +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..142e81136 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/model/User.java @@ -0,0 +1,86 @@ +package com.neo.model; + + + +import jakarta.persistence.*; + +import java.io.Serializable; + +@Entity +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + @Column(nullable = false, unique = true) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true) + private String email; + @Column(nullable = true, unique = true) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + } + + public User(String userName, String passWord, String email, String nickName, String regTime) { + this.userName = userName; + this.passWord = passWord; + this.email = email; + this.nickName = nickName; + this.regTime = regTime; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } +} diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java new file mode 100644 index 000000000..feecceab6 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test1/UserTest1Repository.java @@ -0,0 +1,10 @@ +package com.neo.repository.test1; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserTest1Repository extends JpaRepository { + User findById(long id); + User findByUserName(String userName); + User findByUserNameOrEmail(String username, String email); +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java new file mode 100644 index 000000000..45f8c24fd --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/java/com/neo/repository/test2/UserTest2Repository.java @@ -0,0 +1,11 @@ +package com.neo.repository.test2; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + + +public interface UserTest2Repository extends JpaRepository { + User findById(long id); + User findByUserName(String userName); + User findByUserNameOrEmail(String username, String email); +} \ No newline at end of file diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties new file mode 100644 index 000000000..b7cc3f1e7 --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/main/resources/application.properties @@ -0,0 +1,16 @@ +spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.primary.username=root +spring.datasource.primary.password=root +spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.secondary.username=root +spring.datasource.secondary.password=root +spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver + +#sql\u8F93\u51FA +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.hbm2ddl.auto=create +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java new file mode 100644 index 000000000..c87999ccd --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/MultiJpaApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MultiJpaApplicationTests { + + @Test + public void contextLoads() { + System.out.println("Hello MultiJpa!"); + } + +} diff --git a/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java b/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java new file mode 100644 index 000000000..942a9e46d --- /dev/null +++ b/spring-boot-jpa/spring-boot-multi-Jpa/src/test/java/com/neo/repository/UserRepositoryTests.java @@ -0,0 +1,57 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.repository.test1.UserTest1Repository; +import com.neo.repository.test2.UserTest2Repository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import jakarta.annotation.Resource; +import java.text.DateFormat; +import java.util.Date; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + @Resource + private UserTest1Repository userTest1Repository; + @Resource + private UserTest2Repository userTest2Repository; + + @Test + public void testSave() throws Exception { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userTest1Repository.save(new User("aa", "aa123456","aa@126.com", "aa", formattedDate)); + userTest1Repository.save(new User("bb", "bb123456","bb@126.com", "bb", formattedDate)); + userTest2Repository.save(new User("cc", "cc123456","cc@126.com", "cc", formattedDate)); + } + + + @Test + public void testDelete() throws Exception { + userTest1Repository.deleteAll(); + userTest2Repository.deleteAll(); + } + + @Test + public void testBaseQuery() { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + User user=new User("ff", "ff123456","ff@126.com", "ff", formattedDate); + userTest1Repository.findAll(); + userTest2Repository.findById(3l); + userTest2Repository.save(user); + user.setId(2l); + userTest1Repository.delete(user); + userTest1Repository.count(); + userTest2Repository.findById(3l); + } + + +} \ No newline at end of file diff --git a/spring-boot-mail/pom.xml b/spring-boot-mail/pom.xml index d22376fce..f98e3ec3a 100644 --- a/spring-boot-mail/pom.xml +++ b/spring-boot-mail/pom.xml @@ -14,34 +14,20 @@ org.springframework.boot spring-boot-starter-parent - 1.5.3.RELEASE + 3.0.0 UTF-8 - 1.8 + 17 - - org.springframework.boot - spring-boot-starter - org.springframework.boot spring-boot-starter-mail - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.boot - spring-boot-devtools - true - org.springframework spring-context-support @@ -57,6 +43,20 @@ org.springframework.boot spring-boot-starter-thymeleaf + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + + + org.hamcrest + hamcrest-core + + + diff --git a/spring-boot-mail/src/main/java/com/neo/MailApplication.java b/spring-boot-mail/src/main/java/com/neo/MailApplication.java new file mode 100644 index 000000000..c0aee4155 --- /dev/null +++ b/spring-boot-mail/src/main/java/com/neo/MailApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MailApplication { + + public static void main(String[] args) { + SpringApplication.run(MailApplication.class, args); + } +} diff --git a/spring-boot-mail/src/main/java/com/neo/service/MailService.java b/spring-boot-mail/src/main/java/com/neo/service/MailService.java index a2948541c..41df35605 100644 --- a/spring-boot-mail/src/main/java/com/neo/service/MailService.java +++ b/spring-boot-mail/src/main/java/com/neo/service/MailService.java @@ -5,12 +5,12 @@ */ public interface MailService { - public void sendSimpleMail(String to, String subject, String content); + void sendSimpleMail(String to, String subject, String content); - public void sendHtmlMail(String to, String subject, String content); + void sendHtmlMail(String to, String subject, String content); - public void sendAttachmentsMail(String to, String subject, String content, String filePath); + void sendAttachmentsMail(String to, String subject, String content, String filePath); - public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId); + void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId); } diff --git a/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java b/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java index 9053e6fb7..5e9c5d574 100644 --- a/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java +++ b/spring-boot-mail/src/main/java/com/neo/service/impl/MailServiceImpl.java @@ -11,8 +11,8 @@ import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; -import javax.mail.MessagingException; -import javax.mail.internet.MimeMessage; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; import java.io.File; /** @@ -85,6 +85,7 @@ public void sendHtmlMail(String to, String subject, String content) { * @param content * @param filePath */ + @Override public void sendAttachmentsMail(String to, String subject, String content, String filePath){ MimeMessage message = mailSender.createMimeMessage(); @@ -116,6 +117,7 @@ public void sendAttachmentsMail(String to, String subject, String content, Strin * @param rscPath * @param rscId */ + @Override public void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId){ MimeMessage message = mailSender.createMimeMessage(); diff --git a/spring-boot-mail/src/main/resources/application.properties b/spring-boot-mail/src/main/resources/application.properties index dcbb52168..f7610b3c5 100644 --- a/spring-boot-mail/src/main/resources/application.properties +++ b/spring-boot-mail/src/main/resources/application.properties @@ -1,9 +1,10 @@ spring.application.name=spirng-boot-mail -spring.mail.host=smtp.163.com -spring.mail.username=xxoo@xxoo.com -spring.mail.password=xxoo +spring.mail.host=smtp.126.com +spring.mail.username=xxxx@126.com +spring.mail.password=Zxxxxxxx + spring.mail.default-encoding=UTF-8 -mail.fromMail.addr=xxoo@xxoo.com +mail.fromMail.addr=ixxxxw@126.com diff --git a/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java b/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java new file mode 100644 index 000000000..7a9e7a09b --- /dev/null +++ b/spring-boot-mail/src/test/java/com/neo/MailApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MailApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java b/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java index 91c4bbfd2..4f49737d5 100644 --- a/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java +++ b/spring-boot-mail/src/test/java/com/neo/service/MailServiceTest.java @@ -38,7 +38,7 @@ public void testHtmlMail() throws Exception { @Test public void sendAttachmentsMail() { - String filePath="e:\\tmp\\application.log"; + String filePath="D:\\Log\\TaxCard.log"; mailService.sendAttachmentsMail("ityouknow@126.com", "主题:带附件的邮件", "有附件,请查收!", filePath); } @@ -47,7 +47,7 @@ public void sendAttachmentsMail() { public void sendInlineResourceMail() { String rscId = "neo006"; String content="这是有图片的邮件:"; - String imgPath = "C:\\Users\\summer\\Pictures\\favicon.png"; + String imgPath = "C:\\Users\\ityou\\Pictures\\logo\\smilef.png"; mailService.sendInlineResourceMail("ityouknow@126.com", "主题:这是有图片的邮件", content, imgPath, rscId); } diff --git a/spring-boot-memcache-spymemcached/pom.xml b/spring-boot-memcache-spymemcached/pom.xml index 307afdb75..ae6f0c52c 100644 --- a/spring-boot-memcache-spymemcached/pom.xml +++ b/spring-boot-memcache-spymemcached/pom.xml @@ -14,14 +14,13 @@ org.springframework.boot spring-boot-starter-parent - 2.0.4.RELEASE + 3.0.0 UTF-8 - UTF-8 - 1.8 + 17 @@ -37,7 +36,17 @@ org.springframework.boot spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine test + + + org.hamcrest + hamcrest-core + + diff --git a/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java b/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java index e1175b654..07b0b8839 100644 --- a/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java +++ b/spring-boot-memcache-spymemcached/src/main/java/com/neo/config/MemcachedRunner.java @@ -6,7 +6,7 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/spring-boot-memcache-spymemcached/src/main/resources/application.properties b/spring-boot-memcache-spymemcached/src/main/resources/application.properties index 4d0269621..3102bdade 100644 --- a/spring-boot-memcache-spymemcached/src/main/resources/application.properties +++ b/spring-boot-memcache-spymemcached/src/main/resources/application.properties @@ -1,2 +1,2 @@ -memcache.ip=192.168.0.161 +memcache.ip=localhost memcache.port=11211 \ No newline at end of file diff --git a/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java b/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java index ceaef2205..cdeea20e2 100644 --- a/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java +++ b/spring-boot-memcache-spymemcached/src/test/java/com/neo/RepositoryTests.java @@ -7,7 +7,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import javax.annotation.Resource; +import jakarta.annotation.Resource; @RunWith(SpringRunner.class) @SpringBootTest diff --git a/spring-boot-mongodb/spring-boot-mongodb/pom.xml b/spring-boot-mongodb/spring-boot-mongodb/pom.xml new file mode 100644 index 000000000..ed9d7c5c0 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.neo + spring-boot-mongodb + 1.0.0 + jar + + spring-boot-mongodb + Demo project for Spring Boot and mongodb + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java new file mode 100644 index 000000000..b8c63d563 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/MongoDBApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MongoDBApplication { + + public static void main(String[] args) { + SpringApplication.run(MongoDBApplication.class, args); + } +} diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..c15340ae7 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/model/User.java @@ -0,0 +1,46 @@ +package com.neo.model; + +import java.io.Serializable; + +/** + * Created by summer on 2017/5/5. + */ +public class User implements Serializable { + private static final long serialVersionUID = -3258839839160856613L; + private Long id; + private String userName; + private String passWord; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + @Override + public String toString() { + return "UserEntity{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", passWord='" + passWord + '\'' + + '}'; + } +} diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..e1a3d4134 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,18 @@ +package com.neo.repository; + +import com.neo.model.User; + +/** + * Created by summer on 2017/5/5. + */ +public interface UserRepository { + + public void saveUser(User user); + + public User findUserByUserName(String userName); + + public long updateUser(User user); + + public void deleteUserById(Long id); + +} diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java new file mode 100644 index 000000000..8c96f5a42 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/main/java/com/neo/repository/impl/UserRepositoryImpl.java @@ -0,0 +1,70 @@ +package com.neo.repository.impl; + +import com.mongodb.client.result.UpdateResult; +import com.neo.repository.UserRepository; +import com.neo.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Component; + +/** + * Created by summer on 2017/5/5. + */ +@Component +public class UserRepositoryImpl implements UserRepository { + + @Autowired + private MongoTemplate mongoTemplate; + + /** + * 创建对象 + * @param user + */ + @Override + public void saveUser(User user) { + mongoTemplate.save(user); + } + + /** + * 根据用户名查询对象 + * @param userName + * @return + */ + @Override + public User findUserByUserName(String userName) { + Query query=new Query(Criteria.where("userName").is(userName)); + User user = mongoTemplate.findOne(query , User.class); + return user; + } + + /** + * 更新对象 + * @param user + */ + @Override + public long updateUser(User user) { + Query query=new Query(Criteria.where("id").is(user.getId())); + Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord()); + //更新查询返回结果集的第一条 + UpdateResult result =mongoTemplate.updateFirst(query,update,User.class); + //更新查询返回结果集的所有 + // mongoTemplate.updateMulti(query,update,UserEntity.class); + if(result!=null) + return result.getMatchedCount(); + else + return 0; + } + + /** + * 删除对象 + * @param id + */ + @Override + public void deleteUserById(Long id) { + Query query=new Query(Criteria.where("id").is(id)); + mongoTemplate.remove(query,User.class); + } +} diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties b/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties new file mode 100644 index 000000000..d2c101751 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/main/resources/application.properties @@ -0,0 +1,5 @@ +spring.application.name=spring-boot-mongodb + +spring.data.mongodb.uri=mongodb://119.0.0.6:27017/test + + diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java b/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java new file mode 100644 index 000000000..cd30276df --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/MongoDBApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MongoDBApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java b/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java new file mode 100644 index 000000000..cb6372f02 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-mongodb/src/test/java/com/neo/repository/UserRepositoryTest.java @@ -0,0 +1,49 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Created by summer on 2017/5/5. + */ +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTest { + + @Autowired + private UserRepository userDao; + + @Test + public void testSaveUser() throws Exception { + User user=new User(); + user.setId(2l); + user.setUserName("小明"); + user.setPassWord("fffooo123"); + userDao.saveUser(user); + } + + @Test + public void findUserByUserName(){ + User user= userDao.findUserByUserName("小明"); + System.out.println("user is "+user); + } + + @Test + public void updateUser(){ + User user=new User(); + user.setId(2l); + user.setUserName("天空"); + user.setPassWord("fffxxxx"); + userDao.updateUser(user); + } + + @Test + public void deleteUserById(){ + userDao.deleteUserById(1l); + } + +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml b/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml new file mode 100644 index 000000000..2c9b73c78 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.neo + spring-boot-multi-mongodb + 1.0.0 + jar + + spring-boot-multi-mongodb + Demo project for Spring Boot and multi mongodb + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java new file mode 100644 index 000000000..e33c97dae --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/MultiMongodbApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultiMongodbApplication { + + public static void main(String[] args) { + SpringApplication.run(MultiMongodbApplication.class, args); + } +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java new file mode 100644 index 000000000..d047711eb --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/MultipleMongoConfig.java @@ -0,0 +1,48 @@ +package com.neo.config; + + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; + + +@Configuration +public class MultipleMongoConfig { + + @Autowired + private MultipleMongoProperties mongoProperties; + + @Primary + @Bean(name = "primaryMongoTemplate") + public MongoTemplate primaryMongoTemplate() throws Exception { + return new MongoTemplate(primaryFactory(this.mongoProperties.getPrimary())); + } + + @Bean + @Qualifier("secondaryMongoTemplate") + public MongoTemplate secondaryMongoTemplate() throws Exception { + return new MongoTemplate(secondaryFactory(this.mongoProperties.getSecondary())); + } + + @Bean + @Primary + public MongoDatabaseFactory primaryFactory(MongoProperties mongo) throws Exception { + MongoClient client = MongoClients.create(mongo.getUri()); + return new SimpleMongoClientDatabaseFactory(client, mongoProperties.getPrimary().getDatabase()); + } + + @Bean + public MongoDatabaseFactory secondaryFactory(MongoProperties mongo) throws Exception { + MongoClient client = MongoClients.create(mongo.getUri()); + return new SimpleMongoClientDatabaseFactory(client, mongoProperties.getSecondary().getDatabase()); + } +} \ No newline at end of file diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java new file mode 100644 index 000000000..076bc33d9 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/PrimaryMongoConfig.java @@ -0,0 +1,14 @@ +package com.neo.config; + +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + + +@Configuration +@EnableConfigurationProperties(MultipleMongoProperties.class) +@EnableMongoRepositories(basePackages = "com.neo.repository.primary", + mongoTemplateRef = "primaryMongoTemplate") +public class PrimaryMongoConfig { +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java new file mode 100644 index 000000000..f07149bf0 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/SecondaryMongoConfig.java @@ -0,0 +1,15 @@ +package com.neo.config; + +import com.neo.config.props.MultipleMongoProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + + +@Configuration +@EnableConfigurationProperties(MultipleMongoProperties.class) +@EnableMongoRepositories(basePackages = "com.neo.repository.secondary", + mongoTemplateRef = "secondaryMongoTemplate") +public class SecondaryMongoConfig { + +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java new file mode 100644 index 000000000..5bf4ff66a --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/config/props/MultipleMongoProperties.java @@ -0,0 +1,27 @@ +package com.neo.config.props; + +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "mongodb") +public class MultipleMongoProperties { + + private MongoProperties primary = new MongoProperties(); + private MongoProperties secondary = new MongoProperties(); + + public MongoProperties getPrimary() { + return primary; + } + + public void setPrimary(MongoProperties primary) { + this.primary = primary; + } + + public MongoProperties getSecondary() { + return secondary; + } + + public void setSecondary(MongoProperties secondary) { + this.secondary = secondary; + } +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..b5cd0a861 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/model/User.java @@ -0,0 +1,49 @@ +package com.neo.model; + +import java.io.Serializable; + + +public class User implements Serializable { + private static final long serialVersionUID = -3258839839160856613L; + private String id; + private String userName; + private String passWord; + + public User(String userName, String passWord) { + this.userName = userName; + this.passWord = passWord; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + @Override + public String toString() { + return "User{" + + "id='" + id + '\'' + + ", userName='" + userName + '\'' + + ", passWord='" + passWord + '\'' + + '}'; + } +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java new file mode 100644 index 000000000..50877eb1c --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/primary/PrimaryRepository.java @@ -0,0 +1,10 @@ +package com.neo.repository.primary; + +import com.neo.model.User; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author neo + */ +public interface PrimaryRepository extends MongoRepository { +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java new file mode 100644 index 000000000..11df9153a --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/java/com/neo/repository/secondary/SecondaryRepository.java @@ -0,0 +1,10 @@ +package com.neo.repository.secondary; + +import com.neo.model.User; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author neo + */ +public interface SecondaryRepository extends MongoRepository { +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties new file mode 100644 index 000000000..5884b49ca --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/main/resources/application.properties @@ -0,0 +1,8 @@ +spring.application.name=spring-boot-multi-mongodb + +mongodb.primary.uri=mongodb://119.0.0.6:27017 +mongodb.primary.database=primary +mongodb.secondary.uri=mongodb://119.0.0.6:27017 +mongodb.secondary.database=secondary + + diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java new file mode 100644 index 000000000..8f59e588d --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/MultiMongodbApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MultiMongodbApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java b/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java new file mode 100644 index 000000000..42bf1b447 --- /dev/null +++ b/spring-boot-mongodb/spring-boot-multi-mongodb/src/test/java/com/neo/repository/MuliDatabaseTest.java @@ -0,0 +1,45 @@ +package com.neo.repository; + +import com.neo.model.User; +import com.neo.repository.primary.PrimaryRepository; +import com.neo.repository.secondary.SecondaryRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MuliDatabaseTest { + + @Autowired + private PrimaryRepository primaryRepository; + + @Autowired + private SecondaryRepository secondaryRepository; + + @Test + public void TestSave() { + System.out.println("************************************************************"); + System.out.println("测试开始"); + System.out.println("************************************************************"); + this.primaryRepository.save(new User("小张", "123456")); + this.secondaryRepository.save(new User("小王", "654321")); + List primaries = this.primaryRepository.findAll(); + for (User primary : primaries) { + System.out.println(primary.toString()); + } + List secondaries = this.secondaryRepository.findAll(); + for (User secondary : secondaries) { + System.out.println(secondary.toString()); + } + System.out.println("************************************************************"); + System.out.println("测试完成"); + System.out.println("************************************************************"); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml new file mode 100644 index 000000000..bc725bc84 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-annotation-mulidatasource + 1.0.0 + jar + + spring-boot-mybatis-annotation-mulidatasource + Demo project for Spring Boot and mybatis with annotation + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java new file mode 100644 index 000000000..a77fe795e --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/MAMApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MAMApplication { + + public static void main(String[] args) { + SpringApplication.run(MAMApplication.class, args); + } +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java new file mode 100644 index 000000000..2db7d6533 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java @@ -0,0 +1,51 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate") +public class DataSource1Config { + + @Bean(name = "test1DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test1") + @Primary + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test1SqlSessionFactory") + @Primary + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + return bean.getObject(); + } + + @Bean(name = "test1TransactionManager") + @Primary + public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test1SqlSessionTemplate") + @Primary + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java new file mode 100644 index 000000000..e52928c43 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java @@ -0,0 +1,46 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test2", sqlSessionTemplateRef = "test2SqlSessionTemplate") +public class DataSource2Config { + + @Bean(name = "test2DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test2") + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test2SqlSessionFactory") + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + return bean.getObject(); + } + + @Bean(name = "test2TransactionManager") + public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test2SqlSessionTemplate") + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java new file mode 100644 index 000000000..6ab2e6a09 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java @@ -0,0 +1,35 @@ +package com.neo.mapper.test1; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import org.apache.ibatis.annotations.*; + +import java.util.List; + +public interface User1Mapper { + + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java new file mode 100644 index 000000000..50c5c855d --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java @@ -0,0 +1,35 @@ +package com.neo.mapper.test2; + +import java.util.List; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import org.apache.ibatis.annotations.*; + +public interface User2Mapper { + + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..c92c15d66 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,50 @@ +package com.neo.web; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import com.neo.model.User; +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.RestController; + +import com.neo.mapper.test2.User2Mapper; + +@RestController +public class UserController { + + @Autowired + private User1Mapper user1Mapper; + + @Autowired + private User2Mapper user2Mapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=user1Mapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=user2Mapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + user2Mapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + user2Mapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + user1Mapper.delete(id); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties new file mode 100644 index 000000000..819d06c92 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/main/resources/application.properties @@ -0,0 +1,12 @@ +mybatis.type-aliases-package=com.neo.model + +spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test1.username=root +spring.datasource.test1.password=root +spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test2.username=root +spring.datasource.test2.password=root +spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver + diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java new file mode 100644 index 000000000..8b7bbef35 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/MAMApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MAMApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java new file mode 100644 index 000000000..a20004939 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java @@ -0,0 +1,51 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User1MapperTest { + + @Autowired + private User1Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.size()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(30l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(30l).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java new file mode 100644 index 000000000..af610f6b6 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java @@ -0,0 +1,50 @@ +package com.neo.mapper; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import com.neo.mapper.test2.User2Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User2MapperTest { + + @Autowired + private User2Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + System.out.println(userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(30l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(30l).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation-mulidatasource/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml b/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml new file mode 100644 index 000000000..052042284 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-annotation + 1.0.0 + jar + + spring-boot-mybatis-annotation + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java new file mode 100644 index 000000000..ebac358ad --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/MybatisAnnotationApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.neo.mapper") +public class MybatisAnnotationApplication { + + public static void main(String[] args) { + SpringApplication.run(MybatisAnnotationApplication.class, args); + } +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java new file mode 100644 index 000000000..0189ea95c --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/mapper/UserMapper.java @@ -0,0 +1,40 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Results; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import com.neo.enums.UserSexEnum; + +public interface UserMapper { + + @Select("SELECT * FROM users") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + List getAll(); + + @Select("SELECT * FROM users WHERE id = #{id}") + @Results({ + @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), + @Result(property = "nickName", column = "nick_name") + }) + User getOne(Long id); + + @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})") + void insert(User user); + + @Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}") + void update(User user); + + @Delete("DELETE FROM users WHERE id =#{id}") + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..25144b362 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,47 @@ +package com.neo.web; + +import java.util.List; + +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.UserMapper; + +@RestController +public class UserController { + + @Autowired + private UserMapper userMapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=userMapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=userMapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + userMapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + userMapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + userMapper.delete(id); + } + + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties new file mode 100644 index 000000000..06400e91a --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/main/resources/application.properties @@ -0,0 +1,6 @@ +mybatis.type-aliases-package=com.neo.model + +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java new file mode 100644 index 000000000..9a9777482 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/MybatisAnnotationApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MybatisAnnotationApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java new file mode 100644 index 000000000..0e12f6fd3 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/src/test/java/com/neo/mapper/UserMapperTest.java @@ -0,0 +1,47 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserMapperTest { + + @Autowired + private UserMapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa1", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb1", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc1", "b123456", UserSexEnum.WOMAN)); + + Assert.assertEquals(3, userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + System.out.println(users.toString()); + } + + + @Test + public void testUpdate() throws Exception { + User user = userMapper.getOne(30l); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(30l).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql b/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-annotation/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml new file mode 100644 index 000000000..a371ebb89 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-xml-mulidatasource + 1.0.0 + jar + + spring-boot-mybatis-xml-mulidatasource + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java new file mode 100644 index 000000000..ad7b9d9d7 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/MXMApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MXMApplication { + + public static void main(String[] args) { + SpringApplication.run(MXMApplication.class, args); + } +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java new file mode 100644 index 000000000..40bcf28d5 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource1Config.java @@ -0,0 +1,53 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +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 org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test1", sqlSessionTemplateRef = "test1SqlSessionTemplate") +public class DataSource1Config { + + @Bean(name = "test1DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test1") + @Primary + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test1SqlSessionFactory") + @Primary + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml")); + return bean.getObject(); + } + + @Bean(name = "test1TransactionManager") + @Primary + public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test1SqlSessionTemplate") + @Primary + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java new file mode 100644 index 000000000..67864089a --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/datasource/DataSource2Config.java @@ -0,0 +1,48 @@ +package com.neo.datasource; + +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionFactoryBean; +import org.mybatis.spring.SqlSessionTemplate; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; + +import javax.sql.DataSource; + +/** + * Created by summer on 2016/11/25. + */ +@Configuration +@MapperScan(basePackages = "com.neo.mapper.test2", sqlSessionTemplateRef = "test2SqlSessionTemplate") +public class DataSource2Config { + + @Bean(name = "test2DataSource") + @ConfigurationProperties(prefix = "spring.datasource.test2") + public DataSource testDataSource() { + return DataSourceBuilder.create().build(); + } + + @Bean(name = "test2SqlSessionFactory") + public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test2/*.xml")); + return bean.getObject(); + } + + @Bean(name = "test2TransactionManager") + public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) { + return new DataSourceTransactionManager(dataSource); + } + + @Bean(name = "test2SqlSessionTemplate") + public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java new file mode 100644 index 000000000..d9502822f --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test1/User1Mapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper.test1; + +import com.neo.model.User; + +import java.util.List; + +public interface User1Mapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java new file mode 100644 index 000000000..d5c91ebf1 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/mapper/test2/User2Mapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper.test2; + +import java.util.List; + +import com.neo.model.User; + +public interface User2Mapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..a608500f1 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,51 @@ +package com.neo.web; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.test2.User2Mapper; + +@RestController +public class UserController { + + @Autowired + private User1Mapper user1Mapper; + + @Autowired + private User2Mapper user2Mapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=user1Mapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=user2Mapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + user2Mapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + user2Mapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + user1Mapper.delete(id); + } + + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties new file mode 100644 index 000000000..e2e0f4a74 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/application.properties @@ -0,0 +1,11 @@ +mybatis.config-location=classpath:mybatis/mybatis-config.xml + +spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test1.username=root +spring.datasource.test1.password=root +spring.datasource.test1.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.test2.username=root +spring.datasource.test2.password=root +spring.datasource.test2.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml new file mode 100644 index 000000000..0a2ced2ce --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test1/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml new file mode 100644 index 000000000..da3dc2e7c --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mapper/test2/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 000000000..56097ffb9 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java new file mode 100644 index 000000000..422edba96 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/MXMApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MXMApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java new file mode 100644 index 000000000..77d2accdf --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User1MapperTest.java @@ -0,0 +1,53 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.mapper.test1.User1Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User1MapperTest { + + @Autowired + private User1Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + System.out.println(userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.size()); + } + } + + + @Test + public void testUpdate() throws Exception { + Long id =30l; + User user = userMapper.getOne(id); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(id).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java new file mode 100644 index 000000000..32a5da0a2 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/src/test/java/com/neo/mapper/User2MapperTest.java @@ -0,0 +1,52 @@ +package com.neo.mapper; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; +import com.neo.mapper.test2.User2Mapper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class User2MapperTest { + + @Autowired + private User2Mapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + System.out.println(userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + Long id =30l; + User user = userMapper.getOne(id); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(id).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml-mulidatasource/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml b/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml new file mode 100644 index 000000000..c78823202 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + com.neo + spring-boot-mybatis-xml + 1.0.0 + jar + + spring-boot-mybatis-xml + Demo project for Spring Boot and mybatis + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.0 + + + mysql + mysql-connector-java + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java new file mode 100644 index 000000000..863b95aba --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/MybatisXmlApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.neo.mapper") +public class MybatisXmlApplication { + + public static void main(String[] args) { + SpringApplication.run(MybatisXmlApplication.class, args); + } +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java new file mode 100644 index 000000000..0b8be4453 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/enums/UserSexEnum.java @@ -0,0 +1,5 @@ +package com.neo.enums; + +public enum UserSexEnum { + MAN, WOMAN +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java new file mode 100644 index 000000000..f08f70bf3 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/mapper/UserMapper.java @@ -0,0 +1,19 @@ +package com.neo.mapper; + +import java.util.List; + +import com.neo.model.User; + +public interface UserMapper { + + List getAll(); + + User getOne(Long id); + + void insert(User user); + + void update(User user); + + void delete(Long id); + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..de501655b --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/model/User.java @@ -0,0 +1,73 @@ +package com.neo.model; + +import java.io.Serializable; + +import com.neo.enums.UserSexEnum; + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String passWord; + private UserSexEnum userSex; + private String nickName; + + public User() { + super(); + } + + public User(String userName, String passWord, UserSexEnum userSex) { + super(); + this.passWord = passWord; + this.userName = userName; + this.userSex = userSex; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassWord() { + return passWord; + } + + public void setPassWord(String passWord) { + this.passWord = passWord; + } + + public UserSexEnum getUserSex() { + return userSex; + } + + public void setUserSex(UserSexEnum userSex) { + this.userSex = userSex; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return "userName " + this.userName + ", pasword " + this.passWord + "sex " + userSex.name(); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..25144b362 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,47 @@ +package com.neo.web; + +import java.util.List; + +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.RestController; + +import com.neo.model.User; +import com.neo.mapper.UserMapper; + +@RestController +public class UserController { + + @Autowired + private UserMapper userMapper; + + @RequestMapping("/getUsers") + public List getUsers() { + List users=userMapper.getAll(); + return users; + } + + @RequestMapping("/getUser") + public User getUser(Long id) { + User user=userMapper.getOne(id); + return user; + } + + @RequestMapping("/add") + public void save(User user) { + userMapper.insert(user); + } + + @RequestMapping(value="update") + public void update(User user) { + userMapper.update(user); + } + + @RequestMapping(value="/delete/{id}") + public void delete(@PathVariable("id") Long id) { + userMapper.delete(id); + } + + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties new file mode 100644 index 000000000..0e2bea577 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.properties @@ -0,0 +1,8 @@ +mybatis.config-location=classpath:mybatis/mybatis-config.xml +mybatis.mapper-locations=classpath:mybatis/mapper/*.xml +mybatis.type-aliases-package=com.neo.model + +spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=root +spring.datasource.password=root +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml new file mode 100644 index 000000000..b84731b11 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + id, userName, passWord, user_sex, nick_name + + + + + + + + INSERT INTO + users + (userName,passWord,user_sex) + VALUES + (#{userName}, #{passWord}, #{userSex}) + + + + UPDATE + users + SET + userName = #{userName}, + passWord = #{passWord}, + nick_name = #{nickName} + WHERE + id = #{id} + + + + DELETE FROM + users + WHERE + id =#{id} + + + \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 000000000..56097ffb9 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java new file mode 100644 index 000000000..3938dfde3 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/MybatisXmlApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class MybatisXmlApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java new file mode 100644 index 000000000..689ee9374 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/mapper/UserMapperTest.java @@ -0,0 +1,53 @@ +package com.neo.mapper; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import com.neo.model.User; +import com.neo.enums.UserSexEnum; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserMapperTest { + + @Autowired + private UserMapper userMapper; + + @Test + public void testInsert() throws Exception { + userMapper.insert(new User("aa", "a123456", UserSexEnum.MAN)); + userMapper.insert(new User("bb", "b123456", UserSexEnum.WOMAN)); + userMapper.insert(new User("cc", "b123456", UserSexEnum.WOMAN)); + + System.out.println(userMapper.getAll().size()); + } + + @Test + public void testQuery() throws Exception { + List users = userMapper.getAll(); + if(users==null || users.size()==0){ + System.out.println("is null"); + }else{ + System.out.println(users.toString()); + } + } + + + @Test + public void testUpdate() throws Exception { + + Long id =30l; + User user = userMapper.getOne(id); + System.out.println(user.toString()); + user.setNickName("neo"); + userMapper.update(user); + Assert.assertTrue(("neo".equals(userMapper.getOne(id).getNickName()))); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java new file mode 100644 index 000000000..2fd5fa943 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/src/test/java/com/neo/web/UserControllerTest.java @@ -0,0 +1,37 @@ +package com.neo.web; + + + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserControllerTest { + @Autowired + private WebApplicationContext wac; + private MockMvc mockMvc; + + @Before + public void setUp() throws Exception { + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 + } + + @Test + public void getUsers() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post("/getUsers") + .accept(MediaType.APPLICATION_JSON_UTF8)).andDo(print()); + } + +} \ No newline at end of file diff --git a/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql b/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql new file mode 100644 index 000000000..c8a2769d5 --- /dev/null +++ b/spring-boot-mybatis/spring-boot-mybatis-xml/users.sql @@ -0,0 +1,30 @@ +/* +Navicat MySQL Data Transfer + +Source Server : 本地 +Source Server Version : 50505 +Source Host : localhost:3306 +Source Database : test1 + +Target Server Type : MYSQL +Target Server Version : 50505 +File Encoding : 65001 + +Date: 2016-11-05 21:17:33 +*/ + +SET FOREIGN_KEY_CHECKS=0; + +-- ---------------------------- +-- Table structure for `users` +-- ---------------------------- +DROP TABLE IF EXISTS `users`; +CREATE TABLE `users` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id', + `userName` varchar(32) DEFAULT NULL COMMENT '用户名', + `passWord` varchar(32) DEFAULT NULL COMMENT '密码', + `user_sex` varchar(32) DEFAULT NULL, + `nick_name` varchar(32) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8; + diff --git a/spring-boot-package/spring-boot-package-war/pom.xml b/spring-boot-package/spring-boot-package-war/pom.xml new file mode 100644 index 000000000..208250094 --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + com.neo + spring-boot-package-war + 0.0.1-SNAPSHOT + war + + spring-boot-package-war + Demo project for Spring Boot package war + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/Application.java b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/Application.java new file mode 100644 index 000000000..6cda50c81 --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/Application.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java new file mode 100644 index 000000000..8becd385d --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/ServletInitializer.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * Created by summer on 2017/5/8. + */ +public class ServletInitializer extends SpringBootServletInitializer { + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(Application.class); + } +} diff --git a/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java new file mode 100644 index 000000000..7d0256b4a --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/main/java/com/neo/controller/HelloWorldController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package-war/src/main/resources/application.properties b/spring-boot-package/spring-boot-package-war/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java new file mode 100644 index 000000000..457f6d8ad --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/ApplicationTests.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +public class ApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..582eade98 --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,36 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..46457724b --- /dev/null +++ b/spring-boot-package/spring-boot-package-war/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,35 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloWorldController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/pom.xml b/spring-boot-package/spring-boot-package/pom.xml new file mode 100644 index 000000000..0b26e52a0 --- /dev/null +++ b/spring-boot-package/spring-boot-package/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.neo + spring-boot-package + 1.0.0 + jar + + spring-boot-package + Demo project for Spring Boot package war + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-package/spring-boot-package/src/main/java/com/neo/PackageApplication.java b/spring-boot-package/spring-boot-package/src/main/java/com/neo/PackageApplication.java new file mode 100644 index 000000000..6611164fa --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/java/com/neo/PackageApplication.java @@ -0,0 +1,19 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class PackageApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(PackageApplication.class); + } + + public static void main(String[] args) { + SpringApplication.run(PackageApplication.class, args); + } +} diff --git a/spring-boot-package/spring-boot-package/src/main/java/com/neo/controller/HelloController.java b/spring-boot-package/spring-boot-package/src/main/java/com/neo/controller/HelloController.java new file mode 100644 index 000000000..5e93f0dda --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/java/com/neo/controller/HelloController.java @@ -0,0 +1,13 @@ +package com.neo.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloController { + + @RequestMapping("/hello") + public String index() { + return "Hello World"; + } +} \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/main/resources/application-dev.properties b/spring-boot-package/spring-boot-package/src/main/resources/application-dev.properties new file mode 100644 index 000000000..c83a6aaa9 --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/resources/application-dev.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-test +info.app.version= 1.0.0 \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/main/resources/application-pro.properties b/spring-boot-package/spring-boot-package/src/main/resources/application-pro.properties new file mode 100644 index 000000000..5bc6c5ce3 --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/resources/application-pro.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-pro +info.app.version= 1.0.0 \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/main/resources/application-test.properties b/spring-boot-package/spring-boot-package/src/main/resources/application-test.properties new file mode 100644 index 000000000..995c6d213 --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/resources/application-test.properties @@ -0,0 +1,2 @@ +info.app.name=spring-boot-uat +info.app.version= 1.0.0 \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/main/resources/application.properties b/spring-boot-package/spring-boot-package/src/main/resources/application.properties new file mode 100644 index 000000000..bba9dfd9a --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/main/resources/application.properties @@ -0,0 +1,26 @@ +# \u9879\u76EEcontextPath\uFF0C\u4E00\u822C\u4E0D\u914D\u7F6E +#server.servlet.context-path=/myspringboot +# \u9519\u8BEF\u9875\uFF0C\u6307\u5B9A\u53D1\u751F\u9519\u8BEF\u65F6\uFF0C\u8DF3\u8F6C\u7684URL\u3002 +server.error.path=/error +# \u670D\u52A1\u7AEF\u53E3 +server.port=8080 +# session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 +server.session-timeout=60 +# \u8BE5\u670D\u52A1\u7ED1\u5B9AIP\u5730\u5740\uFF0C\u542F\u52A8\u670D\u52A1\u5668\u65F6\u5982\u672C\u673A\u4E0D\u662F\u8BE5IP\u5730\u5740\u5219\u629B\u51FA\u5F02\u5E38\u542F\u52A8\u5931\u8D25\uFF0C\u53EA\u6709\u7279\u6B8A\u9700\u6C42\u7684\u60C5\u51B5\u4E0B\u624D\u914D\u7F6E +#server.address=192.168.0.6 + +# tomcat \u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 +server.tomcat.max-threads=600 +# tomcat\u7684URI\u7F16\u7801 +server.tomcat.uri-encoding=UTF-8 +# \u5B58\u653ETomcat\u7684\u65E5\u5FD7\u3001Dump\u7B49\u6587\u4EF6\u7684\u4E34\u65F6\u6587\u4EF6\u5939\uFF0C\u9ED8\u8BA4\u4E3A\u7CFB\u7EDF\u7684tmp\u6587\u4EF6\u5939 +server.tomcat.basedir=/tmp/log +# \u6253\u5F00Tomcat\u7684Access\u65E5\u5FD7\uFF0C\u5E76\u53EF\u4EE5\u8BBE\u7F6E\u65E5\u5FD7\u683C\u5F0F +#server.tomcat.access-log-enabled=true +#server.tomcat.access-log-pattern= +# accesslog\u76EE\u5F55\uFF0C\u9ED8\u8BA4\u5728basedir/logs +#server.tomcat.accesslog.directory= +# \u65E5\u5FD7\u6587\u4EF6\u76EE\u5F55 +logging.path=/tmp/log +# \u65E5\u5FD7\u6587\u4EF6\u540D\u79F0\uFF0C\u9ED8\u8BA4\u4E3Aspring.log +logging.file=myapp.log \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java b/spring-boot-package/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java new file mode 100644 index 000000000..ff737b922 --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/test/java/com/neo/PackageApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class PackageApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java b/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java new file mode 100644 index 000000000..149543930 --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloTests.java @@ -0,0 +1,36 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import static org.hamcrest.Matchers.equalTo; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloTests { + + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().string(equalTo("Hello World"))); + } + +} \ No newline at end of file diff --git a/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java b/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java new file mode 100644 index 000000000..d8b01a50d --- /dev/null +++ b/spring-boot-package/spring-boot-package/src/test/java/com/neo/controller/HelloWorldControlerTests.java @@ -0,0 +1,34 @@ +package com.neo.controller; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class HelloWorldControlerTests { + + private MockMvc mvc; + + @Before + public void setUp() throws Exception { + mvc = MockMvcBuilders.standaloneSetup(new HelloController()).build(); + } + + @Test + public void getHello() throws Exception { + mvc.perform(MockMvcRequestBuilders.get("/hello").accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo(MockMvcResultHandlers.print()) + .andReturn(); + } + +} \ No newline at end of file diff --git a/spring-boot-rabbitmq/pom.xml b/spring-boot-rabbitmq/pom.xml index b4de1e355..4a472c465 100644 --- a/spring-boot-rabbitmq/pom.xml +++ b/spring-boot-rabbitmq/pom.xml @@ -14,33 +14,34 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 3.0.0 UTF-8 - 1.8 + 17 org.springframework.boot - spring-boot-starter + spring-boot-starter-amqp org.springframework.boot spring-boot-starter-test - test - org.springframework.boot - spring-boot-starter-amqp - - - org.springframework.boot - spring-boot-devtools - true + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + @@ -49,9 +50,6 @@ org.springframework.boot spring-boot-maven-plugin - - true - diff --git a/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java b/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java new file mode 100644 index 000000000..15d177f39 --- /dev/null +++ b/spring-boot-rabbitmq/src/main/java/com/neo/RabbitMQApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RabbitMQApplication { + + public static void main(String[] args) { + SpringApplication.run(RabbitMQApplication.class, args); + } +} diff --git a/spring-boot-rabbitmq/src/main/resources/application.properties b/spring-boot-rabbitmq/src/main/resources/application.properties index da5cc5ed0..dcaf54273 100644 --- a/spring-boot-rabbitmq/src/main/resources/application.properties +++ b/spring-boot-rabbitmq/src/main/resources/application.properties @@ -1,6 +1,7 @@ -spring.application.name=spirng-boot-rabbitmq-example +spring.application.name=spring-boot-rabbitmq -spring.rabbitmq.host=192.168.0.86 +spring.rabbitmq.host=192.0.0.6 spring.rabbitmq.port=5672 spring.rabbitmq.username=admin -spring.rabbitmq.password=123456 +spring.rabbitmq.password=admin + diff --git a/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java b/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java new file mode 100644 index 000000000..2bec30988 --- /dev/null +++ b/spring-boot-rabbitmq/src/test/java/com/neo/RabbitMQApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RabbitMQApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-redis/pom.xml b/spring-boot-redis/pom.xml new file mode 100644 index 000000000..a358286ae --- /dev/null +++ b/spring-boot-redis/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + com.neo + spring-boot-redis + 3.0.0-SNAPSHOT + jar + + spring-boot-redis + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.apache.commons + commons-pool2 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.session + spring-session-data-redis + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-redis/src/main/java/com/neo/RedisApplication.java b/spring-boot-redis/src/main/java/com/neo/RedisApplication.java new file mode 100644 index 000000000..9c41bedc0 --- /dev/null +++ b/spring-boot-redis/src/main/java/com/neo/RedisApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RedisApplication { + + public static void main(String[] args) { + SpringApplication.run(RedisApplication.class, args); + } +} diff --git a/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java b/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java new file mode 100644 index 000000000..f26748985 --- /dev/null +++ b/spring-boot-redis/src/main/java/com/neo/config/RedisConfig.java @@ -0,0 +1,34 @@ +package com.neo.config; + +import java.lang.reflect.Method; + +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.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.core.RedisTemplate; + + +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport{ + + @Bean + public KeyGenerator keyGenerator() { + return new KeyGenerator() { + @Override + public Object generate(Object target, Method method, Object... 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(); + } + }; + } +} \ No newline at end of file diff --git a/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java b/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java new file mode 100644 index 000000000..400f03fd7 --- /dev/null +++ b/spring-boot-redis/src/main/java/com/neo/config/SessionConfig.java @@ -0,0 +1,9 @@ +package com.neo.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; + +@Configuration +@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30) +public class SessionConfig { +} \ No newline at end of file diff --git a/spring-boot-redis/src/main/java/com/neo/model/User.java b/spring-boot-redis/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..045748877 --- /dev/null +++ b/spring-boot-redis/src/main/java/com/neo/model/User.java @@ -0,0 +1,88 @@ +package com.neo.model; + +import java.io.Serializable; + + + +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + private Long id; + private String userName; + private String password; + private String email; + private String nickname; + private String regTime; + + public User() { + super(); + } + public User(String email, String nickname, String password, String userName, String regTime) { + super(); + this.email = email; + this.nickname = nickname; + this.password = password; + this.userName = userName; + this.regTime = regTime; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = 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 getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getRegTime() { + return regTime; + } + + public void setRegTime(String regTime) { + this.regTime = regTime; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", nickname='" + nickname + '\'' + + ", regTime='" + regTime + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/spring-boot-redis/src/main/java/com/neo/web/UserController.java b/spring-boot-redis/src/main/java/com/neo/web/UserController.java new file mode 100644 index 000000000..99166a0df --- /dev/null +++ b/spring-boot-redis/src/main/java/com/neo/web/UserController.java @@ -0,0 +1,33 @@ +package com.neo.web; + +import jakarta.servlet.http.HttpSession; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.neo.model.User; + +import java.util.UUID; + +@RestController +public class UserController { + + @RequestMapping("/getUser") + @Cacheable(value="user-key") + public User getUser() { + User user=new User("aa@126.com", "aa", "aa123456", "aa","123"); + System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); + return user; + } + + + @RequestMapping("/uid") + String uid(HttpSession session) { + UUID uid = (UUID) session.getAttribute("uid"); + if (uid == null) { + uid = UUID.randomUUID(); + } + session.setAttribute("uid", uid); + return session.getId(); + } +} \ No newline at end of file diff --git a/spring-boot-redis/src/main/resources/application.properties b/spring-boot-redis/src/main/resources/application.properties new file mode 100644 index 000000000..2d4d7e89b --- /dev/null +++ b/spring-boot-redis/src/main/resources/application.properties @@ -0,0 +1,17 @@ +# REDIS +# Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09 +spring.redis.database=0 +# Redis\u670D\u52A1\u5668\u5730\u5740 +spring.redis.host=localhost +# 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 \u9ED8\u8BA4 8 +spring.redis.lettuce.pool.max-active=8 +# \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 \u9ED8\u8BA4 -1 +spring.redis.lettuce.pool.max-wait=-1 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 \u9ED8\u8BA4 8 +spring.redis.lettuce.pool.max-idle=8 +# \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 \u9ED8\u8BA4 0 +spring.redis.lettuce.pool.min-idle=0 diff --git a/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java b/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java new file mode 100644 index 000000000..c92da71f7 --- /dev/null +++ b/spring-boot-redis/src/test/java/com/neo/RedisApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class RedisApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello web"); + } + +} diff --git a/spring-boot-redis/src/test/java/com/neo/TestRedis.java b/spring-boot-redis/src/test/java/com/neo/TestRedis.java new file mode 100644 index 000000000..fe8f86e5f --- /dev/null +++ b/spring-boot-redis/src/test/java/com/neo/TestRedis.java @@ -0,0 +1,49 @@ +package com.neo; + +import com.neo.model.User; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.concurrent.TimeUnit; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TestRedis { + + @Autowired + private StringRedisTemplate stringRedisTemplate; + + @Autowired + private RedisTemplate redisTemplate; + + @Test + public void test() throws Exception { + stringRedisTemplate.opsForValue().set("aaa", "111"); + Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa")); + } + + @Test + public void testObj() throws Exception { + User user=new User("aa@126.com", "aa", "aa123456", "aa","123"); + ValueOperations operations=redisTemplate.opsForValue(); + operations.set("com.neox", user); + operations.set("com.neo.f", user,1, TimeUnit.SECONDS); + Thread.sleep(1000); + //redisTemplate.delete("com.neo.f"); + boolean exists=redisTemplate.hasKey("com.neo.f"); + if(exists){ + System.out.println("exists is true"); + }else{ + System.out.println("exists is false"); + } + // Assert.assertEquals("aa", operations.get("com.neo.f").getUserName()); + } +} \ No newline at end of file diff --git a/spring-boot-scheduler/pom.xml b/spring-boot-scheduler/pom.xml index b3d18365d..e956d21ab 100644 --- a/spring-boot-scheduler/pom.xml +++ b/spring-boot-scheduler/pom.xml @@ -14,13 +14,13 @@ org.springframework.boot spring-boot-starter-parent - 1.4.2.RELEASE + 3.0.0 UTF-8 - 1.8 + 17 @@ -31,12 +31,17 @@ org.springframework.boot spring-boot-starter-test - test - - org.springframework.boot - spring-boot-devtools - true + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + @@ -45,9 +50,6 @@ org.springframework.boot spring-boot-maven-plugin - - true - diff --git a/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java b/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java new file mode 100644 index 000000000..1fd012d24 --- /dev/null +++ b/spring-boot-scheduler/src/main/java/com/neo/SchedulerApplication.java @@ -0,0 +1,14 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class SchedulerApplication { + + public static void main(String[] args) { + SpringApplication.run(SchedulerApplication.class, args); + } +} diff --git a/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java b/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java new file mode 100644 index 000000000..9a627ba57 --- /dev/null +++ b/spring-boot-scheduler/src/test/java/com/neo/SchedulerApplicationTests.java @@ -0,0 +1,17 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SchedulerApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello world"); + } + +} diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml new file mode 100644 index 000000000..6677f5207 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + + com.neo + spring-boot-thymeleaf-layout + 0.0.1-SNAPSHOT + jar + + spring-boot-thymeleaf-layout + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + nz.net.ultraq.thymeleaf + thymeleaf-layout-dialect + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + + diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java new file mode 100644 index 000000000..0e4e29af2 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/TLayoutApplication.java @@ -0,0 +1,13 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TLayoutApplication { + + public static void main(String[] args) { + SpringApplication.run(TLayoutApplication.class, args); + } + +} diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java new file mode 100644 index 000000000..3b2554172 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/java/com/neo/web/IndexController.java @@ -0,0 +1,31 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class IndexController { + + @RequestMapping("/index") + public String index() { + return "index"; + } + + @RequestMapping("/fragment") + public String fragment() { + return "fragment"; + } + + @RequestMapping("/layout") + public String layout() { + return "layout"; + } + + @RequestMapping("/home") + public String home() { + return "home"; + } + + +} \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties new file mode 100644 index 000000000..975a5172a --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/application.properties @@ -0,0 +1,2 @@ +com.neo.title=\u7EAF\u6D01\u7684\u5FAE\u7B11 +com.neo.description=\u5206\u4EAB\u751F\u6D3B\u548C\u6280\u672F \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html new file mode 100644 index 000000000..6a491191e --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/base.html @@ -0,0 +1,15 @@ + + + + comm title + + + + + + + + + + + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html new file mode 100644 index 000000000..bb65abe2e --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/fragment.html @@ -0,0 +1,11 @@ + + + + Fragment - Page + + + + + + + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html new file mode 100644 index 000000000..bd0de8076 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/home.html @@ -0,0 +1,11 @@ + + + + Home + + +
+

个性化的内容

+
+ + diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html new file mode 100644 index 000000000..40d36573a --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/index.html @@ -0,0 +1,11 @@ + + + + + Index + + +
+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html new file mode 100644 index 000000000..4bc09f3c9 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout.html @@ -0,0 +1,15 @@ + + + + + Layout + + +
+
+
+
content
+
+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html new file mode 100644 index 000000000..223de9f3e --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/copyright.html @@ -0,0 +1,12 @@ + + + + + Title + + + + © 2018 + + + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html new file mode 100644 index 000000000..48a9c7def --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/footer.html @@ -0,0 +1,12 @@ + + + + + footer + + +
+

我是 尾部

+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html new file mode 100644 index 000000000..adc6b8c67 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/header.html @@ -0,0 +1,12 @@ + + + + + header + + +
+

我是 头部

+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html new file mode 100644 index 000000000..04d887574 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/main/resources/templates/layout/left.html @@ -0,0 +1,12 @@ + + + + + left + + + +

我是 左侧

+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java new file mode 100644 index 000000000..3e1b0ab0c --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf-layout/src/test/java/com/neo/TLayoutApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class TLayoutApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml b/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml new file mode 100644 index 000000000..03aea7c39 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + com.neo + spring-boot-thymeleaf + 0.0.1-SNAPSHOT + jar + + spring-boot-thymeleaf + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java new file mode 100644 index 000000000..e194e8686 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/ThymeleafApplication.java @@ -0,0 +1,13 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ThymeleafApplication { + + public static void main(String[] args) { + SpringApplication.run(ThymeleafApplication.class, args); + } + +} diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..55fabd5eb --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/model/User.java @@ -0,0 +1,44 @@ +package com.neo.model; + + + +public class User { + private String name; + private int age; + private String pass; + + public User(String name, int age, String pass) { + this.name = name; + this.age = age; + this.pass = pass; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPass() { + return pass; + } + + public void setPass(String pass) { + this.pass = pass; + } + + @Override + public String toString() { + return ("name=" + this.name + ",age=" + this.age + ",pass=" + this.pass); + } +} diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java new file mode 100644 index 000000000..112760366 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/ExampleController.java @@ -0,0 +1,66 @@ +package com.neo.web; + +import com.neo.model.User; +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +@Controller +public class ExampleController { + + @RequestMapping("/string") + public String string(ModelMap map) { + map.addAttribute("userName", "ityouknow"); + return "string"; + } + + @RequestMapping("/if") + public String ifunless(ModelMap map) { + map.addAttribute("flag", "yes"); + return "if"; + } + + @RequestMapping("/list") + public String list(ModelMap map) { + map.addAttribute("users", getUserList()); + return "list"; + } + + @RequestMapping("/url") + public String url(ModelMap map) { + map.addAttribute("type", "link"); + map.addAttribute("pageId", "springcloud/2017/09/11/"); + map.addAttribute("img", "http://www.ityouknow.com/assets/images/neo.jpg"); + return "url"; + } + + @RequestMapping("/eq") + public String eq(ModelMap map) { + map.addAttribute("name", "neo"); + map.addAttribute("age", 30); + map.addAttribute("flag", "yes"); + return "eq"; + } + + @RequestMapping("/switch") + public String switchcase(ModelMap map) { + map.addAttribute("sex", "woman"); + return "switch"; + } + + private List getUserList(){ + List list=new ArrayList(); + User user1=new User("大牛",12,"123456"); + User user2=new User("小牛",6,"123563"); + User user3=new User("纯洁的微笑",66,"666666"); + list.add(user1); + list.add(user2); + list.add(user3); + return list; + } + +} \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..2eac4e8a9 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,16 @@ +package com.neo.web; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class HelloController { + + @RequestMapping("/") + public String index(ModelMap map) { + map.addAttribute("message", "http://www.ityouknow.com"); + return "hello"; + } + +} \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties new file mode 100644 index 000000000..4b9333aa3 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.thymeleaf.cache=false \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html new file mode 100644 index 000000000..70e65a9fa --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/eq.html @@ -0,0 +1,17 @@ + + + + + Example gt eq + + +
+

EQ

+ +
+ +
+ favorites +
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html new file mode 100644 index 000000000..28c51163e --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/hello.html @@ -0,0 +1,10 @@ + + + + + Hello + + +

Hello World

+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html new file mode 100644 index 000000000..9127c233c --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/if.html @@ -0,0 +1,15 @@ + + + + + Example If/Unless + + +
+

If/Unless

+ home +
+ ityouknow +
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html new file mode 100644 index 000000000..017c65e96 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/list.html @@ -0,0 +1,20 @@ + + + + + Example If/Unless + + +
+

for 循环

+ + + + + + + +
neo6213index
+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html new file mode 100644 index 000000000..7a2e3f66d --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/string.html @@ -0,0 +1,16 @@ + + + + + Example String + + +
+

text

+

neo

+ +
+ +
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html new file mode 100644 index 000000000..aef5a3031 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/switch.html @@ -0,0 +1,17 @@ + + + + + Example switch + + +
+
+

她是一个姑娘...

+

这是一个爷们!

+ +

未知性别的一个家伙。

+
+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html new file mode 100644 index 000000000..ded52686f --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/main/resources/templates/url.html @@ -0,0 +1,19 @@ + + + + + Example If/Unless + + +
+

URL

+ link1 +
+ view +
+
+


+
+
+ + \ No newline at end of file diff --git a/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java new file mode 100644 index 000000000..3ccf7f4b9 --- /dev/null +++ b/spring-boot-thymeleaf/spring-boot-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ThymeleafApplicationTests { + + @Test + public void contextLoads() { + } + +} diff --git a/spring-boot-web-thymeleaf/pom.xml b/spring-boot-web-thymeleaf/pom.xml index 29d75f28c..503ce5495 100644 --- a/spring-boot-web-thymeleaf/pom.xml +++ b/spring-boot-web-thymeleaf/pom.xml @@ -6,12 +6,18 @@ Spring Boot Web thymeleaf Sample Spring Boot Web thymeleaf Sample - + org.springframework.boot spring-boot-starter-parent - 2.0.0.RELEASE + 3.0.0 + + + UTF-8 + 17 + + @@ -22,11 +28,24 @@ org.springframework.boot spring-boot-starter-thymeleaf - + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine test + + + org.hamcrest + hamcrest-core + + diff --git a/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java b/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java index 0f5b33d0b..e9d09b4a4 100644 --- a/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java +++ b/spring-boot-web-thymeleaf/src/main/java/com/neo/controller/MessageController.java @@ -1,7 +1,7 @@ package com.neo.controller; -import javax.validation.Valid; +import jakarta.validation.Valid; import com.neo.model.Message; import com.neo.repository.MessageRepository; diff --git a/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java b/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java index d4f09e648..c3a36113b 100644 --- a/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java +++ b/spring-boot-web-thymeleaf/src/main/java/com/neo/model/Message.java @@ -1,9 +1,8 @@ package com.neo.model; -import java.util.Calendar; - -import javax.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotEmpty; +import java.util.Calendar; public class Message { diff --git a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html index 1d564bfba..80f8adea0 100644 --- a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html +++ b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/form.html @@ -1,11 +1,11 @@ - + Messages : Create
-
+
diff --git a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html index 88f00a8fd..a1aef8ad0 100644 --- a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html +++ b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/list.html @@ -1,11 +1,11 @@ - + Messages : View all
-
+
diff --git a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html index e32cb74e0..0181b9afb 100644 --- a/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html +++ b/spring-boot-web-thymeleaf/src/main/resources/templates/messages/view.html @@ -1,11 +1,11 @@ - + Messages : View
-
+
diff --git a/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java b/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java index e97547773..5bb188086 100644 --- a/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java +++ b/spring-boot-web-thymeleaf/src/test/java/com/neo/ThymeleafApplicationTests.java @@ -10,7 +10,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; @@ -26,8 +26,7 @@ public class ThymeleafApplicationTests { @Autowired private TestRestTemplate restTemplate; - @LocalServerPort - private int port; + private int port=8080; @Test public void testHome() { @@ -50,8 +49,16 @@ public void testCreate() { public void testCss() { ResponseEntity entity = this.restTemplate.getForEntity( "http://localhost:" + this.port + "/css/bootstrap.min.css", String.class); + + ResponseEntity response = restTemplate.exchange( + createURLWithPort("/students/Student1/courses"), + HttpMethod.POST, entity, String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("body"); } + private String createURLWithPort(String uri) { + return "http://localhost:" + port + uri; + } + } diff --git a/spring-boot-web/pom.xml b/spring-boot-web/pom.xml index ebeec70a0..d09cd4a99 100644 --- a/spring-boot-web/pom.xml +++ b/spring-boot-web/pom.xml @@ -5,8 +5,8 @@ com.neo spring-boot-web - 0.0.1-SNAPSHOT - jar + 3.0.0-SNAPSHOT + war spring-boot-web Demo project for Spring Boot @@ -14,63 +14,57 @@ org.springframework.boot spring-boot-starter-parent - 1.5.6.RELEASE + 3.0.0 UTF-8 - 1.8 + 17 org.springframework.boot - spring-boot-starter + spring-boot-starter-web org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-thymeleaf + + + org.springframework.boot + spring-boot-starter-data-jpa + + + mysql + mysql-connector-java - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-data-jpa - - - mysql - mysql-connector-java - - - org.springframework.boot - spring-boot-devtools - true + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + - - org.springframework.boot - spring-boot-starter-thymeleaf - - org.webjars.bower - jquery - 2.0.3 - + org.webjars.bower + jquery + 3.6.2 + - org.webjars.bower - bootstrap - 3.0.3 + org.webjars.bowergithub.twbs + bootstrap + 5.2.3 - - org.springframework.boot - spring-boot-starter-redis - - org.springframework.session - spring-session-data-redis + org.springframework.boot + spring-boot-starter-test + test @@ -79,9 +73,6 @@ org.springframework.boot spring-boot-maven-plugin - - true - diff --git a/spring-boot-web/src/main/java/com/neo/WebApplication.java b/spring-boot-web/src/main/java/com/neo/WebApplication.java new file mode 100644 index 000000000..ede8e479f --- /dev/null +++ b/spring-boot-web/src/main/java/com/neo/WebApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebApplication { + + public static void main(String[] args) { + SpringApplication.run(WebApplication.class, args); + } +} diff --git a/spring-boot-web/src/main/java/com/neo/WebConfiguration.java b/spring-boot-web/src/main/java/com/neo/WebConfiguration.java index cbf7177fd..604679b1c 100644 --- a/spring-boot-web/src/main/java/com/neo/WebConfiguration.java +++ b/spring-boot-web/src/main/java/com/neo/WebConfiguration.java @@ -2,13 +2,13 @@ import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import org.apache.catalina.filters.RemoteIpFilter; import org.springframework.boot.web.servlet.FilterRegistrationBean; diff --git a/spring-boot-web/src/main/java/com/neo/model/User.java b/spring-boot-web/src/main/java/com/neo/model/User.java new file mode 100644 index 000000000..9914cd6e1 --- /dev/null +++ b/spring-boot-web/src/main/java/com/neo/model/User.java @@ -0,0 +1,72 @@ +package com.neo.model; + +import java.io.Serializable; +import jakarta.persistence.*; + +@Entity +public class User implements Serializable { + + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue + private Long id; + @Column(nullable = false, unique = true, length = 20) + private String userName; + @Column(nullable = false) + private String passWord; + @Column(nullable = false, unique = true, length = 30) + private String email; + @Column(nullable = true, unique = true, length = 30) + private String nickName; + @Column(nullable = false) + private String regTime; + + public User() { + super(); + } + public User(String nickName,String email,String userName, String passWord, String regTime) { + super(); + this.email = email; + this.nickName = nickName; + this.passWord = passWord; + this.userName = userName; + this.regTime = regTime; + } + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = 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 getNickName() { + return nickName; + } + public void setNickName(String nickName) { + this.nickName = nickName; + } + public String getRegTime() { + return regTime; + } + public void setRegTime(String regTime) { + this.regTime = regTime; + } + +} \ No newline at end of file diff --git a/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java b/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java new file mode 100644 index 000000000..b5c0c63ec --- /dev/null +++ b/spring-boot-web/src/main/java/com/neo/repository/UserRepository.java @@ -0,0 +1,12 @@ +package com.neo.repository; + +import com.neo.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + + User findByUserName(String userName); + + User findByUserNameOrEmail(String username, String email); + +} \ No newline at end of file diff --git a/spring-boot-web/src/main/java/com/neo/web/HelloController.java b/spring-boot-web/src/main/java/com/neo/web/HelloController.java index 5fd95a062..a24d50706 100644 --- a/spring-boot-web/src/main/java/com/neo/web/HelloController.java +++ b/spring-boot-web/src/main/java/com/neo/web/HelloController.java @@ -3,8 +3,9 @@ import java.util.Locale; import java.util.UUID; -import javax.servlet.http.HttpSession; +import jakarta.servlet.http.HttpSession; +import com.neo.model.User; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -14,17 +15,15 @@ public class HelloController { @RequestMapping("/hello") public String hello(Locale locale, Model model) { - return "hello world"; + return "Hello World"; + } + + @RequestMapping("/getUser") + public User getUser() { + User user=new User(); + user.setUserName("小明"); + user.setPassWord("xxxx"); + return user; } - - @RequestMapping("/uid") - String uid(HttpSession session) { - UUID uid = (UUID) session.getAttribute("uid"); - if (uid == null) { - uid = UUID.randomUUID(); - } - session.setAttribute("uid", uid); - return session.getId(); - } } \ No newline at end of file diff --git a/spring-boot-web/src/main/java/com/neo/web/UserController.java b/spring-boot-web/src/main/java/com/neo/web/UserController.java index 983617cce..92ff3323b 100644 --- a/spring-boot-web/src/main/java/com/neo/web/UserController.java +++ b/spring-boot-web/src/main/java/com/neo/web/UserController.java @@ -3,29 +3,38 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.Cacheable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.neo.domain.User; -import com.neo.domain.UserRepository; +import com.neo.model.User; +import com.neo.repository.UserRepository; @RestController public class UserController { @Autowired private UserRepository userRepository; + + @RequestMapping("/add") + public User saveUser(String key) { + User user=new User(); + user.setUserName("aa"+key); + user.setEmail("ityouknow@126.com"+key); + user.setNickName("微笑"+key); + user.setPassWord("123456"+key); + user.setRegTime("2022-12-20"+key); + userRepository.save(user); + return user; + } - @RequestMapping("/getUser") - @Cacheable(value="user-key") - public User getUser() { + @RequestMapping("/getUserByName") + public User getUserByName() { User user=userRepository.findByUserName("aa"); System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); return user; } @RequestMapping("/getUsers") - @Cacheable(value="key-Users") public List getUsers() { List users=userRepository.findAll(); System.out.println("若下面没出现“无缓存的时候调用”字样且能打印出数据表示测试成功"); diff --git a/spring-boot-web/src/main/resources/application.properties b/spring-boot-web/src/main/resources/application.properties index 16fed3698..d9a963273 100644 --- a/spring-boot-web/src/main/resources/application.properties +++ b/spring-boot-web/src/main/resources/application.properties @@ -1,32 +1,16 @@ -spring.datasource.url=jdbc:mysql://localhost:3306/test -spring.datasource.username=root -spring.datasource.password=root -spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.datasource.url=jdbc:mysql://1.1.4.3:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true +spring.datasource.username=xx +spring.datasource.password=exxx +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.hikari.maxLifeTime=600000 spring.jpa.properties.hibernate.hbm2ddl.auto=update -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect -spring.jpa.show-sql= true - -com.neo.title=\u7eaf\u6d01\u7684\u5fae\u7b11 -com.neo.description=\u5206\u4eab\u751f\u6d3b\u548c\u6280\u672f - -# REDIS (RedisProperties) -# Redis\u6570\u636e\u5e93\u7d22\u5f15\uff08\u9ed8\u8ba4\u4e3a0\uff09 -spring.redis.database=0 -# Redis\u670d\u52a1\u5668\u5730\u5740 -spring.redis.host=192.168.0.71 -# 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.pool.max-active=8 -# \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.pool.max-wait=-1 -# \u8fde\u63a5\u6c60\u4e2d\u7684\u6700\u5927\u7a7a\u95f2\u8fde\u63a5 -spring.redis.pool.max-idle=8 -# \u8fde\u63a5\u6c60\u4e2d\u7684\u6700\u5c0f\u7a7a\u95f2\u8fde\u63a5 -spring.redis.pool.min-idle=0 -# \u8fde\u63a5\u8d85\u65f6\u65f6\u95f4\uff08\u6beb\u79d2\uff09 -spring.redis.timeout=0 +#sql\u8F93\u51FA +spring.jpa.show-sql=true +#format\u4E00\u4E0Bsql\u8FDB\u884C\u8F93\u51FA +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect +spring.jpa.open-in-view=true +com.neo.title=\u7EAF\u6D01\u7684\u5FAE\u7B11 +com.neo.description=\u5206\u4EAB\u751F\u6D3B\u548C\u6280\u672F \ No newline at end of file diff --git a/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java b/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java new file mode 100644 index 000000000..cd4cb770c --- /dev/null +++ b/spring-boot-web/src/test/java/com/neo/WebApplicationTests.java @@ -0,0 +1,18 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class WebApplicationTests { + + @Test + public void contextLoads() { + System.out.println("hello web"); + } + +} diff --git a/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java b/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java new file mode 100644 index 000000000..3b7d8ea33 --- /dev/null +++ b/spring-boot-web/src/test/java/com/neo/model/UserRepositoryTests.java @@ -0,0 +1,38 @@ +package com.neo.model; + +import java.text.DateFormat; +import java.util.Date; + +import com.neo.repository.UserRepository; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import org.springframework.test.context.junit4.SpringRunner; + + +@RunWith(SpringRunner.class) +@SpringBootTest +public class UserRepositoryTests { + + @Autowired + private UserRepository userRepository; + + @Test + public void test() throws Exception { + Date date = new Date(); + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG); + String formattedDate = dateFormat.format(date); + + userRepository.save(new User("aa1", "aa@126.com", "aa", "aa123456",formattedDate)); + userRepository.save(new User("bb2", "bb@126.com", "bb", "bb123456",formattedDate)); + userRepository.save(new User("cc3", "cc@126.com", "cc", "cc123456",formattedDate)); + +// Assert.assertEquals(9, userRepository.findAll().size()); + Assert.assertEquals("bb2", userRepository.findByUserNameOrEmail("bb", "xxx126.com").getNickName()); + userRepository.delete(userRepository.findByUserName("aa")); + } + +} \ No newline at end of file diff --git a/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java b/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java index ae0b39960..2d76b350a 100644 --- a/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java +++ b/spring-boot-web/src/test/java/com/neo/web/ProPertiesTest.java @@ -8,9 +8,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.neo.Application; import com.neo.util.NeoProperties; import org.springframework.test.context.junit4.SpringRunner; @@ -18,11 +16,9 @@ @SpringBootTest public class ProPertiesTest { - @Autowired private NeoProperties neoProperties; - @Test public void getHello() throws Exception { System.out.println(neoProperties.getTitle()); @@ -30,11 +26,10 @@ public void getHello() throws Exception { Assert.assertEquals(neoProperties.getDescription(), "分享生活和技术"); } - @Test public void testMap() throws Exception { Map orderMinTime=new HashMap(); - long xx=orderMinTime.get("123"); + orderMinTime.get("123"); } } \ No newline at end of file diff --git a/spring-boot-webflux/pom.xml b/spring-boot-webflux/pom.xml new file mode 100644 index 000000000..16b66ab36 --- /dev/null +++ b/spring-boot-webflux/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.neo + spring-boot-webflux + 1.0.0-SNAPSHOT + jar + + spring-boot-webflux + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + + + UTF-8 + 17 + + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-test + + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java b/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java new file mode 100644 index 000000000..b89527d35 --- /dev/null +++ b/spring-boot-webflux/src/main/java/com/neo/WebFluxApplication.java @@ -0,0 +1,12 @@ +package com.neo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class WebFluxApplication { + + public static void main(String[] args) { + SpringApplication.run(WebFluxApplication.class, args); + } +} diff --git a/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java b/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java new file mode 100644 index 000000000..681a1542f --- /dev/null +++ b/spring-boot-webflux/src/main/java/com/neo/web/HelloController.java @@ -0,0 +1,14 @@ +package com.neo.web; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class HelloController { + + @GetMapping("/hello") + public Mono hello() { + return Mono.just("Welcome to reactive world ~"); + } +} diff --git a/spring-boot-webflux/src/main/resources/application.properties b/spring-boot-webflux/src/main/resources/application.properties new file mode 100644 index 000000000..e69de29bb diff --git a/spring-boot-webflux/src/test/java/com/neo/HelloTests.java b/spring-boot-webflux/src/test/java/com/neo/HelloTests.java new file mode 100644 index 000000000..aa9389c5f --- /dev/null +++ b/spring-boot-webflux/src/test/java/com/neo/HelloTests.java @@ -0,0 +1,21 @@ +package com.neo; + +import com.neo.web.HelloController; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; + +@RunWith(SpringRunner.class) +@WebFluxTest(controllers = HelloController.class) +public class HelloTests { + @Autowired + WebTestClient client; + + @Test + public void getHello() { + client.get().uri("/hello").exchange().expectStatus().isOk(); + } +} diff --git a/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java b/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java new file mode 100644 index 000000000..b7b4ed765 --- /dev/null +++ b/spring-boot-webflux/src/test/java/com/neo/WebFluxApplicationTests.java @@ -0,0 +1,16 @@ +package com.neo; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class WebFluxApplicationTests { + + @Test + public void contextLoads() { + } + +}