├── .gitattributes ├── .gitignore ├── README.md ├── logs ├── error.log └── springboot.log ├── springboot-jpa-thymeleaf ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── cy │ │ │ ├── Application.java │ │ │ ├── config │ │ │ ├── AuthCustomRealm.java │ │ │ └── ShiroConfig.java │ │ │ ├── controller │ │ │ ├── LoginController.java │ │ │ └── UserController.java │ │ │ ├── entity │ │ │ ├── NutritionFacts.java │ │ │ ├── SysPermission.java │ │ │ ├── SysRole.java │ │ │ └── UserInfo.java │ │ │ ├── repository │ │ │ └── UserRepository.java │ │ │ ├── service │ │ │ ├── UserService.java │ │ │ └── impl │ │ │ │ └── UserServiceImpl.java │ │ │ └── test │ │ │ └── Test.java │ └── resources │ │ ├── application.properties │ │ ├── ehcache.xml │ │ ├── static │ │ ├── css │ │ │ └── bootstrap.css │ │ └── index.html │ │ └── templates │ │ ├── 500.html │ │ ├── error.html │ │ ├── errors.html │ │ ├── index.html │ │ ├── login.html │ │ └── user │ │ ├── userAdd.html │ │ ├── userEdit.html │ │ └── userList.html │ └── test │ └── java │ └── com │ └── cy │ └── ApplicationTests.java ├── springboot-mybatis-thymeleaf ├── .gitignore ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── cy │ │ ├── Application.java │ │ ├── Swagger.java │ │ ├── api │ │ └── UserAPI.java │ │ ├── config │ │ ├── OneDataSourceConfig.java │ │ ├── SecurityConfig.java │ │ ├── SslConfig.java │ │ └── TowDataSourceConfig.java │ │ ├── controller │ │ └── UserController.java │ │ ├── dao │ │ └── UserMapper.java │ │ ├── entity │ │ ├── Result.java │ │ └── User.java │ │ ├── enums │ │ └── ResultEnum.java │ │ ├── exception │ │ ├── AllException.java │ │ └── AllExceptionHandle.java │ │ ├── filter │ │ └── DruidStatFilter.java │ │ ├── service │ │ ├── UserService.java │ │ └── impl │ │ │ ├── LoginService.java │ │ │ └── UserServiceImpl.java │ │ ├── servlet │ │ └── DruidStatViewServlet.java │ │ ├── task │ │ ├── AsyncTask.java │ │ └── Task.java │ │ └── util │ │ ├── HttpUtils.java │ │ ├── InstallCert.java │ │ ├── JsoupDemo.java │ │ ├── ResultUtil.java │ │ └── SendMail.java │ └── resources │ ├── application.propertiess │ ├── application.yml │ ├── banner.txt │ ├── log4j2.yml │ ├── mybatis │ └── mapper │ │ └── UserMapper.xml │ ├── ocly.jks │ ├── static │ ├── css │ │ ├── AdminLTE.min.css │ │ ├── _all-skins.min.css │ │ ├── bootstrap.min.css │ │ ├── dataTables.bootstrap.min.css │ │ ├── font-awesome.min.css │ │ └── ionicons.min.css │ ├── img │ │ ├── user.jpg │ │ └── user3-128x128.jpg │ ├── index.html │ └── js │ │ ├── adminlte.min.js │ │ ├── bootstrap.min.js │ │ ├── dataTables.bootstrap.min.js │ │ ├── demo.js │ │ ├── fastclick.js │ │ ├── icheck.min.js │ │ ├── jquery.dataTables.min.js │ │ ├── jquery.min.js │ │ └── jquery.slimscroll.min.js │ └── templates │ ├── data.html │ ├── login.html │ └── user │ ├── userAdd.html │ ├── userEdit.html │ └── userList.html ├── springboot-rabbitmq ├── .gitignore ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ocly │ │ │ ├── Application.java │ │ │ ├── RabbitConfig.java │ │ │ ├── controller │ │ │ ├── GlobalExceptionHandler.java │ │ │ └── UploadController.java │ │ │ ├── generic │ │ │ └── GenericTest.java │ │ │ ├── io │ │ │ ├── IOUtils.java │ │ │ └── ThreadCopy.java │ │ │ ├── modle │ │ │ ├── SingletonA.java │ │ │ ├── SingletonB.java │ │ │ ├── SingletonC.java │ │ │ ├── SingletonD.java │ │ │ ├── SingletonE.java │ │ │ └── User.java │ │ │ ├── rabbit │ │ │ ├── FanoutReceiverA.java │ │ │ ├── FanoutReceiverB.java │ │ │ ├── FanoutReceiverC.java │ │ │ ├── ObjReceive.java │ │ │ ├── ObjSender.java │ │ │ ├── Receiver.java │ │ │ ├── Receivertow.java │ │ │ ├── Sender.java │ │ │ ├── TopicOneReceive.java │ │ │ └── TopicTwoReceive.java │ │ │ ├── task │ │ │ ├── Crawl.java │ │ │ └── Weibo.java │ │ │ ├── test │ │ │ └── Test.java │ │ │ ├── thread │ │ │ └── Ocly.java │ │ │ └── util │ │ │ ├── RuoKuai.java │ │ │ └── SendMail.java │ └── resources │ │ ├── application.yml │ │ ├── banner.txt │ │ ├── out.dat │ │ ├── out.txt │ │ ├── static │ │ └── img │ │ │ └── QQ图片20171214160014.png │ │ └── templates │ │ ├── emailTemplate.html │ │ ├── upload.html │ │ └── uploadStatus.html │ └── test │ └── java │ └── com │ └── ocly │ ├── ApplicationTests.java │ └── util │ └── sendMailTest.java └── test.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=Java 2 | *.css linguist-language=Java 3 | *.html linguist-language=Java -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | out 9 | gen 10 | /.gitignore 11 | /.gitattributes 12 | /springboot-mybatis-web/src/test/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Springboot--Study 2 | ## springboot-jpa-thymeleaf 3 | * 实现增删改查功能 4 | * 加入redis缓存(简单) 5 | * 2017-12-15 :整合Shiro 6 | * 2018-07-01 :Builder模式构造类 7 | * 2018-07-01 :要优先使用基本类型而不是装箱基本类型,要担心无意识的自动装箱 8 | 9 | ## springboot-mybatis-thymeleaf 10 | * 基于xml配置整合mybatis 11 | * 加入redis缓存(简单) 12 | * 整合Druid及监控页面 13 | * Druid添加多数据源 14 | * 使用yml格式更改配置文件 15 | * 增加https协议,使用undertow容器 16 | * 增加log4j2日志记录,使用lombok简化代码 17 | * 基于注解配置mapper 18 | * 2017-12-05 :将error级别日志单独记录,添加控制台高亮 19 | * 2017-12-06 :添加登录界面,使用spring security简单的内存控制 20 | * 2017-12-06 :使用spring security由数据库控制 21 | * 2017-12-07 :定时任务@Scheduled,开启异步Async 22 | * 2017-12-07 :添加swagger接口文档生成器 23 | * 2017-12-08 :统一异常 24 | * 2017-12-11 :运用Jsoup爬取今日热点事件(代理IP爬取) 25 | * 2017-12-19 :Jsoup各种运用 26 | * 2017-12-20 :httpclient忽略SSL 27 | 28 | 29 | ## springboot-rabbit 30 | * 2017-12-12 :整合rabbit以及基本模式的使用 31 | * 2017-12-13 :JavaMail的使用 32 | * 2017-12-14 :JavaMail,发送带模板、附件、图片的邮件 33 | * 2017-12-25 :thread,io 34 | * 2017-12-29 :实现微博带验证码登录 35 | * 2018-01-07 :Docker学习 36 | 37 | ## 打卡 38 | * 2018-01-19 :[Docker创建nginx+tomcat集群+redis版session共享](https://www.jianshu.com/p/c0901ff9b4ff) 39 | * 2018-01-20 :[Jsoup爬取心灵毒鸡汤](https://www.jianshu.com/p/94ff20103ddf) 40 | * 2018-01-21 :docker搭建prometheus+grafana,及ELK 41 | * 2018-01-22 :[hexo-yilia主题博客搭建](http://111.231.86.225/) 42 | * 2018-01-24 :[zing-gallery](http://111.231.86.225:3000/) 43 | * 2018-01-25 :SpringClound初探 44 | * 2018-01-30 :百度文字识别API调用 45 | * 2018-01-31 :[vue2初探](https://github.com/yy1193889747/vue-webpack-todo) 46 | * 2018-02-08 :[即时通讯](http://111.231.86.225:8888/) 47 | * 2018-02-13 :手机抓包 48 | -------------------------------------------------------------------------------- /logs/error.log: -------------------------------------------------------------------------------- 1 | 2017-12-07 11:31:41,316:ERROR main (TestContextManager.java:234) - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@6057aebb] to prepare test instance [com.cy.task.AsyncTaskTest@63eef88a] 2 | org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.cy.task.AsyncTaskTest': Unsatisfied dependency expressed through field 'task'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cy.task.AsyncTask' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 3 | at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 4 | at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 5 | at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 6 | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 7 | at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:386) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 8 | at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 9 | at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 10 | at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 11 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 12 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 13 | at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12] 14 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 15 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 16 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 17 | at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] 18 | at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] 19 | at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] 20 | at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] 21 | at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] 22 | at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 23 | at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 24 | at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12] 25 | at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 26 | at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12] 27 | at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:?] 28 | at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51) [junit-rt.jar:?] 29 | at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:?] 30 | at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:?] 31 | Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.cy.task.AsyncTask' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 32 | at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 33 | at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 34 | at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 35 | at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) ~[spring-beans-4.3.12.RELEASE.jar:4.3.12.RELEASE] 36 | ... 27 more 37 | -------------------------------------------------------------------------------- /logs/springboot.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/logs/springboot.log -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Example user template template 3 | ### Example user template 4 | 5 | # IntelliJ project files 6 | .idea 7 | *.iml 8 | out 9 | gen 10 | target 11 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/README.md: -------------------------------------------------------------------------------- 1 | # 问题与思考 2 | 1. @Controller和@RestController的区别 :lollipop: 3 | ``` 4 | @RestController相当于@ResponseBody and @Controller. 5 | 当要返回前台页面时只能用@Controller 6 | ``` 7 | 2. 为什么新增用户页面不是直接打开,而是通过controller返回 8 | ``` 9 | 实测发现在templates下的页面不能直接访问,而在static下的页面时可以访问到 10 | ``` 11 | 3. @NotEmpty、@NotBlank、@NotNull的区别 :lollipop: 12 | ``` 13 | @NotEmpty 用在集合类上面 14 | @NotBlank 用在String上面 15 | @NotNull 用在基本类型上 16 | ``` 17 | 4. jpa事务管理@Transactional :lollipop: 18 | ``` 19 | 在执行删除操作的时候如果没加事务管理会报错:cannot reliably process 'remove' call 20 | 那加到哪里呢,通过百度学习,我加到了service的实现里面。 21 | ``` 22 | # Thymeleaf知识点分享 23 | [官方文档----五分钟学会使用Thymeleaf](http://www.thymeleaf.org/doc/articles/standarddialect5minutes.html "官方文档") 24 | 1. pom.xml中加入依赖 25 | ``` 26 | 27 | org.springframework.boot 28 | spring-boot-starter-thymeleaf 29 | 30 | ``` 31 | 2. Html页面需添加th的命名空间`` 32 | 3. 常用的表达式 33 | ##### `@{...} : 链接表达式.` 34 | ##### `${...} : 变量表达式.` 35 | ##### `*{...} : 选择表达式.` 36 | # jpa 知识点分享 37 | 1. hibernate.hbm2ddl.aut参数的作用 :lollipop: 38 | ```` 39 | validate 加载hibernate时,验证创建数据库表结构 40 | create 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。 41 | create-drop 加载hibernate时创建,退出是删除表结构 42 | update 加载hibernate自动更新数据库结构(一般使用) 43 | ```` 44 | # redis 最简单的集成方法 45 | 1. 首先实体类要实现序列化方法 46 | 2. 在业务层注入RedisTemplate对象 47 | 3. 调用相应的方法实现缓存 48 | ``` 49 | String key = "user_" + id; 50 | ValueOperations operations = redisTemplate.opsForValue(); 51 | 52 | // 缓存存在 53 | boolean hasKey = redisTemplate.hasKey(key); 54 | if (hasKey) { 55 | User user = operations.get(key); 56 | LOGGER.info("从缓存中获取用户信息>> " + user.toString()); 57 | return user; 58 | } 59 | // 插入缓存 60 | User user = userRepository.findByid(id); 61 | operations.set(key, user, 100, TimeUnit.SECONDS); 62 | //删除缓存 63 | if (hasKey) { 64 | redisTemplate.delete(key); 65 | LOGGER.info("从缓存中获取用户信息>> " + user.toString()); 66 | return user; 67 | } 68 | 69 | ``` 70 | 4. 注意缓存的key保持一致,以及缓存时间设定 71 | 72 | # Shiro 学习 73 | 74 | 1. 新增密码错误限制 75 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.cy 7 | springboot-jpa-thymeleaf 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | springboot-jpa-thymeleaf 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.8.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-logging 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-log4j2 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-thymeleaf 55 | 56 | 57 | 58 | 59 | mysql 60 | mysql-connector-java 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-starter-data-jpa 67 | 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-starter-data-redis 73 | 74 | 75 | 76 | 77 | 78 | org.apache.shiro 79 | shiro-spring 80 | 1.4.0 81 | 82 | 83 | 84 | org.crazycake 85 | shiro-redis 86 | 2.4.2.1-RELEASE 87 | 88 | 89 | 90 | 91 | org.apache.shiro 92 | shiro-ehcache 93 | 1.4.0 94 | 95 | 96 | 97 | com.github.theborakompanioni 98 | thymeleaf-extras-shiro 99 | 2.0.0 100 | 101 | 102 | 103 | 104 | org.projectlombok 105 | lombok 106 | 1.16.14 107 | 108 | 109 | 110 | 111 | 112 | 113 | org.springframework.boot 114 | spring-boot-maven-plugin 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/Application.java: -------------------------------------------------------------------------------- 1 | package com.cy; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | 9 | @SpringBootApplication 10 | public class Application { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(Application.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/config/AuthCustomRealm.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | 3 | import com.cy.entity.UserInfo; 4 | import com.cy.service.UserService; 5 | import org.apache.shiro.authc.AuthenticationException; 6 | import org.apache.shiro.authc.AuthenticationInfo; 7 | import org.apache.shiro.authc.AuthenticationToken; 8 | import org.apache.shiro.authc.SimpleAuthenticationInfo; 9 | import org.apache.shiro.authz.AuthorizationInfo; 10 | import org.apache.shiro.authz.SimpleAuthorizationInfo; 11 | import org.apache.shiro.realm.AuthorizingRealm; 12 | import org.apache.shiro.subject.PrincipalCollection; 13 | import org.apache.shiro.util.ByteSource; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | 17 | /** 18 | * Created by cy 19 | * 2017/12/14 20:15 20 | */ 21 | public class AuthCustomRealm extends AuthorizingRealm { 22 | @Autowired 23 | private UserService userService; 24 | 25 | @Override 26 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { 27 | System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()"); 28 | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 29 | UserInfo userInfo = (UserInfo)principalCollection.getPrimaryPrincipal(); 30 | authorizationInfo.addRole("aa"); 31 | return authorizationInfo; 32 | } 33 | 34 | /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/ 35 | @Override 36 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 37 | System.out.println("MyShiroRealm.doGetAuthenticationInfo()"); 38 | //获取用户的输入的账号. 39 | String username = (String)token.getPrincipal(); 40 | System.out.println(token.getCredentials()); 41 | //通过username从数据库中查找 User对象,如果找到,没找到. 42 | //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 43 | UserInfo userInfo = userService.findByUsername(username); 44 | System.out.println("----->>userInfo="+userInfo); 45 | if(userInfo == null){ 46 | return null; 47 | } 48 | SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( 49 | userInfo, //用户名 50 | userInfo.getPassword(), //密码 51 | ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt 52 | getName() //realm name 53 | ); 54 | return authenticationInfo; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/config/ShiroConfig.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | 3 | import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 4 | import org.apache.shiro.authc.credential.HashedCredentialsMatcher; 5 | import org.apache.shiro.cache.ehcache.EhCacheManager; 6 | import org.apache.shiro.codec.Base64; 7 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; 8 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 9 | import org.apache.shiro.web.mgt.CookieRememberMeManager; 10 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 11 | import org.apache.shiro.web.servlet.SimpleCookie; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.apache.shiro.mgt.SecurityManager; 15 | 16 | import java.util.LinkedHashMap; 17 | import java.util.Map; 18 | 19 | /** 20 | * Created by cy 21 | * 2017/12/14 19:53 22 | */ 23 | 24 | /** 25 | * Shiro 配置 Apache Shiro 核心通过 Filter 来实现,就好像SpringMvc 通过DispachServlet 来主控制一样。 26 | * 既然是使用 Filter 一般也就能猜到,是通过URL规则来进行过滤和权限校验,所以我们需要定义一系列关于URL的规则和访问权限。 27 | */ 28 | @Configuration 29 | public class ShiroConfig { 30 | 31 | @Bean 32 | public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { 33 | System.out.println("ShiroConfiguration.shirFilter()"); 34 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 35 | // 必须设置 SecurityManager 36 | shiroFilterFactoryBean.setSecurityManager(securityManager); 37 | 38 | // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 39 | shiroFilterFactoryBean.setLoginUrl("/login"); 40 | // 未授权界面; 41 | shiroFilterFactoryBean.setUnauthorizedUrl("/403"); 42 | // 登录成功后要跳转的链接 43 | shiroFilterFactoryBean.setSuccessUrl("/index"); 44 | 45 | // 拦截器. 46 | Map filterChainDefinitionMap = new LinkedHashMap(); 47 | // 配置不会被拦截的链接 顺序判断 48 | filterChainDefinitionMap.put("/static/**", "anon"); 49 | // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 50 | filterChainDefinitionMap.put("/logout", "logout"); 51 | // 配置记住我或认证通过可以访问的地址 52 | // filterChainDefinitionMap.put("/index", "user"); 53 | // filterChainDefinitionMap.put("/", "user"); 54 | // :这是一个坑呢,一不小心代码就不好使了; 55 | // 56 | filterChainDefinitionMap.put("/**", "authc"); 57 | 58 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); 59 | 60 | return shiroFilterFactoryBean; 61 | 62 | 63 | } 64 | 65 | @Bean 66 | public SecurityManager securityManager(){ 67 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 68 | // 设置realm. 69 | securityManager.setRealm(customRealm()); 70 | // 注入记住我管理器; 71 | securityManager.setRememberMeManager(rememberMeManager()); 72 | // //设置sessionManager 73 | // securityManager.setSessionManager(defaultWebSessionManager()); 74 | // //设置缓存 75 | securityManager.setCacheManager(cacheManager()); 76 | return securityManager; 77 | } 78 | 79 | @Bean 80 | public AuthCustomRealm customRealm(){ 81 | AuthCustomRealm customRealm = new AuthCustomRealm(); 82 | customRealm.setCredentialsMatcher(hashedCredentialsMatcher()); 83 | return customRealm; 84 | } 85 | 86 | /** 87 | * 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 88 | * 所以我们需要修改下doGetAuthenticationInfo中的代码; ) 89 | * @return 90 | */ 91 | @Bean 92 | public HashedCredentialsMatcher hashedCredentialsMatcher() { 93 | HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); 94 | hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法; 95 | hashedCredentialsMatcher.setHashIterations(3);// 散列的次数,比如散列两次,相当于md5(md5("")); 96 | hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); 97 | return hashedCredentialsMatcher; 98 | } 99 | 100 | /** 101 | * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持; 102 | * @param securityManager 103 | * @return 104 | */ 105 | @Bean 106 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { 107 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 108 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); 109 | return authorizationAttributeSourceAdvisor; 110 | } 111 | 112 | /** 113 | * cookie对象; 114 | * 115 | * @return 116 | */ 117 | @Bean 118 | public SimpleCookie rememberMeCookie() { 119 | // 这个参数是cookie的名称,对应前端的checkbox 的name = rememberMe 120 | SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); 121 | // 122 | simpleCookie.setMaxAge(259200); 123 | return simpleCookie; 124 | } 125 | /** 126 | * cookie管理对象; 127 | * 128 | * @return 129 | */ 130 | @Bean 131 | public CookieRememberMeManager rememberMeManager() { 132 | CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); 133 | cookieRememberMeManager.setCookie(rememberMeCookie()); 134 | //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) 135 | cookieRememberMeManager.setCipherKey(Base64.decode("ztLX7sun")); 136 | return cookieRememberMeManager; 137 | } 138 | 139 | /** 140 | * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean 141 | * 142 | * @return 143 | */ 144 | // @Bean 145 | // public ShiroDialect shiroDialect() { 146 | // return new ShiroDialect(); 147 | // } 148 | 149 | 150 | @Bean 151 | public EhCacheManager cacheManager() { 152 | EhCacheManager cacheManager = new EhCacheManager(); 153 | cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml"); 154 | return cacheManager; 155 | } 156 | 157 | // @Bean(name="simpleMappingExceptionResolver") 158 | // public SimpleMappingExceptionResolver 159 | // createSimpleMappingExceptionResolver() { 160 | // SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver(); 161 | // Properties mappings = new Properties(); 162 | // mappings.setProperty("DatabaseException", "500");//数据库异常处理 163 | // mappings.setProperty("UnauthorizedException","errors"); //设置已认证未授权的页面 164 | // r.setExceptionMappings(mappings); // None by default 165 | // r.setDefaultErrorView("500"); // No default 166 | // r.setExceptionAttribute("ex"); // Default is "exception" 167 | // //r.setWarnLogCategory("example.MvcLogger"); // No default 168 | // return r; 169 | // } 170 | } 171 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/controller/LoginController.java: -------------------------------------------------------------------------------- 1 | package com.cy.controller; 2 | 3 | import com.cy.entity.UserInfo; 4 | import lombok.extern.log4j.Log4j2; 5 | import org.apache.shiro.SecurityUtils; 6 | import org.apache.shiro.authc.*; 7 | import org.apache.shiro.subject.Subject; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.redis.core.StringRedisTemplate; 10 | import org.springframework.data.redis.core.ValueOperations; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.ui.ModelMap; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 16 | 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.concurrent.TimeUnit; 19 | 20 | /** 21 | * Created by cy 22 | * 2017/12/15 17:22 23 | */ 24 | @Controller 25 | @Log4j2 26 | public class LoginController { 27 | @Autowired 28 | private StringRedisTemplate stringRedisTemplate; 29 | 30 | /** 31 | * 登录页面 32 | * 33 | * @return 34 | */ 35 | @RequestMapping(value = "/login", method = RequestMethod.GET) 36 | public String login(String message, ModelMap modelMap) { 37 | if (!"".equals(message)) { 38 | modelMap.addAttribute("message", message); 39 | } 40 | return "login"; 41 | } 42 | 43 | /** 44 | * 登录动作 45 | * 46 | * @param user 47 | * @return 48 | */ 49 | @RequestMapping(value = "/login", method = RequestMethod.POST) 50 | public String login(HttpServletRequest req, UserInfo user, RedirectAttributes attr) { 51 | if ("".equals(user.getUsername()) || "".equals(user.getPassword())) { 52 | attr.addAttribute("message", "用户名或密码不能为空"); 53 | return "redirect:/login"; 54 | } 55 | String userName = user.getUsername(); 56 | String pwd = user.getPassword(); 57 | System.out.println(userName + pwd); 58 | //计数大于5时,设置用户被锁定一小时 59 | ValueOperations opsForValue = stringRedisTemplate.opsForValue(); 60 | if ("LOCK".equals(opsForValue.get("SHIRO_IS_LOCK" + userName))) { 61 | attr.addAttribute("message", "由于密码输入错误次数大于5次,帐号已经禁止登录!"); 62 | return "redirect:/login"; 63 | } 64 | if(stringRedisTemplate.hasKey("SHIRO_LOGIN_COUNT" + userName)) { 65 | if (Integer.parseInt(opsForValue.get("SHIRO_LOGIN_COUNT" + userName)) >= 5) { 66 | opsForValue.set("SHIRO_IS_LOCK" + userName, "LOCK"); 67 | stringRedisTemplate.expire("SHIRO_IS_LOCK" + userName, 1, TimeUnit.HOURS); 68 | } 69 | } 70 | //开始调用shiro验证 71 | UsernamePasswordToken token = new UsernamePasswordToken(userName, pwd, "login"); 72 | //获取当前的subject 73 | Subject currentUser = SecurityUtils.getSubject(); 74 | System.out.println("asdasd"); 75 | try { 76 | //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查 77 | //每个Realm都能在必要时对提交的AuthenticationTokens作出反应 78 | //所以这一步在调用login(token)方法时,它会走到doGetAuthenticationInfo()方法中,具体验证方式详见此方法 79 | log.info("对用户[" + userName + "]进行登录验证..验证开始"); 80 | currentUser.login(token); 81 | opsForValue.set("SHIRO_LOGIN_COUNT"+userName, "0"); 82 | log.info("对用户[" + userName + "]进行登录验证..验证通过"); 83 | } catch (UnknownAccountException uae) { 84 | log.info("对用户[" + userName + "]进行登录验证..验证未通过,未知账户"); 85 | attr.addAttribute("message", "用户名不存在"); 86 | } catch (IncorrectCredentialsException ice) { 87 | stringRedisTemplate.opsForValue().increment("SHIRO_LOGIN_COUNT"+userName,1); 88 | log.info("对用户[" + userName + "]进行登录验证..验证未通过,错误的凭证"); 89 | attr.addAttribute("message", "密码不正确"); 90 | } catch (LockedAccountException lae) { 91 | log.info("对用户[" + userName + "]进行登录验证..验证未通过,账户已锁定"); 92 | attr.addAttribute("message", "账户已锁定"); 93 | } catch (ExcessiveAttemptsException eae) { 94 | log.info("对用户[" + userName + "]进行登录验证..验证未通过,错误次数过多"); 95 | attr.addAttribute("message", "用户名或密码错误次数过多"); 96 | } catch (AuthenticationException ae) { 97 | //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景 98 | log.info("对用户[" + userName + "]进行登录验证..验证未通过,堆栈轨迹如下"); 99 | ae.printStackTrace(); 100 | attr.addAttribute("message", "用户名或密码不正确"); 101 | } 102 | if (req.getParameter("forceLogout") != null) { 103 | attr.addAttribute("error", "您已经被管理员强制退出,请重新登录"); 104 | return "redirect:/login"; 105 | } 106 | //验证是否登录成功 107 | if (currentUser.isAuthenticated()) { 108 | return "redirect:/index"; 109 | } else { 110 | token.clear(); 111 | return "redirect:/login"; 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.cy.controller; 2 | 3 | import com.cy.entity.UserInfo; 4 | import com.cy.service.UserService; 5 | import org.apache.shiro.authc.IncorrectCredentialsException; 6 | import org.apache.shiro.authc.UnknownAccountException; 7 | import org.apache.shiro.authz.annotation.RequiresPermissions; 8 | import org.apache.shiro.authz.annotation.RequiresRoles; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Controller; 11 | import org.springframework.ui.Model; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.ResponseBody; 16 | 17 | import javax.servlet.http.HttpServletRequest; 18 | import java.util.Map; 19 | 20 | /** 21 | * Created by cy 22 | * 2017/11/22 17:07 23 | */ 24 | @Controller 25 | public class UserController { 26 | @Autowired 27 | private UserService userService; 28 | 29 | @GetMapping(value = "/userInfo/userList") 30 | public String userList(Model model) { 31 | model.addAttribute("userList", userService.userList()); 32 | return "user/userList"; 33 | } 34 | 35 | @GetMapping(value = "/toEdit") 36 | public String getUser(int id, Model model) { 37 | model.addAttribute("user", userService.getUser(id)); 38 | return "user/userEdit"; 39 | } 40 | 41 | @PostMapping(value = "/edit") 42 | public String editUser(UserInfo user) { 43 | System.out.println(user.getName()); 44 | userService.editUser(user); 45 | return "redirect:/list"; 46 | } 47 | 48 | @GetMapping(value = "/delete") 49 | public String deleteUser(int id) { 50 | userService.deleteUser(id); 51 | return "redirect:/list"; 52 | } 53 | 54 | @PostMapping(value = "/add") 55 | public String addUser(UserInfo user) { 56 | userService.saveUser(user); 57 | return "redirect:/list"; 58 | } 59 | 60 | @GetMapping(value = "/toAdd") 61 | public String addUser() { 62 | return "user/userAdd"; 63 | } 64 | 65 | 66 | @RequestMapping("/403") 67 | public @ResponseBody String unauthorizedRole(){ 68 | System.out.println("------没有权限-------"); 69 | return "403"; 70 | } 71 | @RequestMapping({"/","/index"}) 72 | public String index(){ 73 | return"/index"; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/entity/NutritionFacts.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | /** 4 | * 营养成分 Builder模式 5 | * 6 | * @author congyang.guo 7 | */ 8 | public class NutritionFacts { 9 | 10 | private final int servingSize; 11 | private final int servings; 12 | private final int calories; 13 | private final int fat; 14 | 15 | public static class Builder { 16 | private final int servingSize; 17 | private final int servings; 18 | 19 | private int calories = 0; 20 | private int fat = 0; 21 | 22 | 23 | public Builder(int servingSize, int servings) { 24 | this.servingSize = servingSize; 25 | this.servings = servings; 26 | } 27 | 28 | public Builder calories(int val) { 29 | calories = val; 30 | return this; 31 | } 32 | 33 | public Builder fat(int val) { 34 | fat = val; 35 | return this; 36 | } 37 | 38 | public NutritionFacts build() { 39 | return new NutritionFacts(this); 40 | } 41 | } 42 | 43 | private NutritionFacts(Builder builder) { 44 | servingSize = builder.servingSize; 45 | servings = builder.servings; 46 | calories = builder.calories; 47 | fat = builder.fat; 48 | } 49 | 50 | 51 | public static void main(String[] args) { 52 | 53 | NutritionFacts fat = new NutritionFacts.Builder(240, 100).calories(20).fat(100).build(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/entity/SysPermission.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by cy 11 | * 2017/12/14 19:10 12 | */ 13 | @Data 14 | @Entity 15 | public class SysPermission implements Serializable { 16 | @Id@GeneratedValue 17 | private Integer id;//主键. 18 | private String name;//名称. 19 | @Column(columnDefinition="enum('menu','button')") 20 | private String resourceType;//资源类型,[menu|button] 21 | private String url;//资源路径. 22 | private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view 23 | private Long parentId; //父编号 24 | private String parentIds; //父编号列表 25 | private Boolean available = Boolean.FALSE; 26 | @ManyToMany 27 | @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")}) 28 | private List roles; 29 | } -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/entity/SysRole.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | import lombok.Data; 4 | 5 | import javax.persistence.*; 6 | import java.util.List; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/12/14 19:10 11 | */ 12 | @Data 13 | @Entity 14 | public class SysRole { 15 | @Id@GeneratedValue 16 | private Integer id; // 编号 17 | private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的: 18 | private String description; // 角色描述,UI界面显示使用 19 | private Boolean available = Boolean.FALSE; // 是否可用,如果不可用将不会添加给用户 20 | 21 | //角色 -- 权限关系:多对多关系; 22 | @ManyToMany(fetch= FetchType.EAGER) 23 | @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")}) 24 | private List permissions; 25 | 26 | // 用户 - 角色关系定义; 27 | @ManyToMany 28 | @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")}) 29 | private List userInfos;// 一个角色对应多个用户 30 | 31 | } 32 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/entity/UserInfo.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | import lombok.Data; 4 | import org.hibernate.validator.constraints.NotBlank; 5 | 6 | import javax.persistence.*; 7 | import java.io.Serializable; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by cy 12 | * 2017/11/22 14:05 13 | */ 14 | @Data 15 | @Entity 16 | public class UserInfo implements Serializable { 17 | @Id 18 | @GeneratedValue 19 | private Integer uid; 20 | @Column(unique =true) 21 | private String username;//帐号 22 | private String name;//名称(昵称或者真实姓名,不同系统不同定义) 23 | private String password; //密码; 24 | private String salt;//加密密码的盐 25 | private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定. 26 | 27 | /** 28 | * 密码盐. 29 | * @return 30 | */ 31 | public String getCredentialsSalt(){ 32 | return this.username+this.salt; 33 | } 34 | //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解 35 | } 36 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.cy.repository; 2 | 3 | import com.cy.entity.UserInfo; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * Created by cy 8 | * 2017/11/22 16:45 9 | */ 10 | 11 | public interface UserRepository extends JpaRepository{ 12 | 13 | UserInfo findByUid(int uid); 14 | 15 | UserInfo findByUsername(String username); 16 | 17 | int deleteByUid(int uid); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.cy.service; 2 | 3 | import com.cy.entity.UserInfo; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/11/22 16:47 10 | */ 11 | public interface UserService { 12 | 13 | List userList(); 14 | 15 | UserInfo getUser(int id); 16 | 17 | int deleteUser(int id); 18 | 19 | UserInfo saveUser(UserInfo user); 20 | 21 | UserInfo editUser(UserInfo user); 22 | 23 | UserInfo findByUsername(String username); 24 | } 25 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cy.service.impl; 2 | 3 | import com.cy.entity.UserInfo; 4 | import com.cy.repository.UserRepository; 5 | import com.cy.service.UserService; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.redis.core.RedisTemplate; 10 | import org.springframework.data.redis.core.ValueOperations; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import java.util.List; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | /** 18 | * Created by cy 19 | * 2017/11/22 16:50 20 | */ 21 | @Service 22 | 23 | public class UserServiceImpl implements UserService { 24 | 25 | @Autowired 26 | private UserRepository userRepository; 27 | @Autowired 28 | private RedisTemplate redisTemplate; 29 | 30 | private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); 31 | 32 | @Override 33 | public List userList() { 34 | return userRepository.findAll(); 35 | } 36 | 37 | @Override 38 | public UserInfo getUser(int uid) { 39 | String key = "UserInfo_" + uid; 40 | ValueOperations operations = redisTemplate.opsForValue(); 41 | // 缓存存在 42 | boolean hasKey = redisTemplate.hasKey(key); 43 | if (hasKey) { 44 | UserInfo UserInfo = operations.get(key); 45 | LOGGER.info("从缓存中获取用户信息>> " + UserInfo.toString()); 46 | return UserInfo; 47 | } 48 | // 插入缓存 49 | UserInfo UserInfo = userRepository.findByUid(uid); 50 | operations.set(key, UserInfo, 100, TimeUnit.SECONDS); 51 | LOGGER.info("用户信息插入缓存 >> " + UserInfo.toString()); 52 | return UserInfo; 53 | } 54 | 55 | @Transactional 56 | @Override 57 | public int deleteUser(int id) { 58 | int ret = userRepository.deleteByUid(id); 59 | String key = "UserInfo_" + id; 60 | boolean hasKey = redisTemplate.hasKey(key); 61 | if (hasKey) { 62 | redisTemplate.delete(key); 63 | LOGGER.info("从缓存中删除用户 >> " + id); 64 | } 65 | return ret; 66 | } 67 | 68 | @Override 69 | public UserInfo saveUser(UserInfo UserInfo) { 70 | return userRepository.save(UserInfo); 71 | } 72 | 73 | @Override 74 | public UserInfo editUser(UserInfo UserInfo) { 75 | UserInfo UserInfo1 = userRepository.save(UserInfo); 76 | String key = "UserInfo_" + UserInfo.getUid(); 77 | boolean hasKey = redisTemplate.hasKey(key); 78 | if (hasKey) { 79 | redisTemplate.delete(key); 80 | LOGGER.info("从缓存中删除用户 >> " + UserInfo1.toString()); 81 | } 82 | return UserInfo1; 83 | } 84 | 85 | @Override 86 | public UserInfo findByUsername(String username) { 87 | return userRepository.findByUsername(username); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/java/com/cy/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.cy.test; 2 | 3 | /** 4 | * 要优先使用基本类型而不是装箱基本类型,要担心无意识的自动装箱 5 | *

6 | * Long 2305843005992468481--Use:8414 7 | * long 2305843005992468481--Use:744 8 | * 9 | * @author congyang.guo 10 | */ 11 | public class Test { 12 | public static void main(String[] args) { 13 | long l = System.currentTimeMillis(); 14 | 15 | long sum = 0L; 16 | for (int i = 0; i < Integer.MAX_VALUE; i++) { 17 | sum += i; 18 | } 19 | System.out.println(sum + "--Use:" + (System.currentTimeMillis() - l)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-jpa-thymeleaf/src/main/resources/application.properties -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/ehcache.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 31 | 32 | 39 | 40 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

This is a static page

9 | 10 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

数据库异常

9 | 10 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

页面不存在

9 | 10 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/errors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

403没有权限

9 | 10 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello Thymeleaf! 6 | 7 | 8 |

9 | 10 | 11 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 错误信息:

9 |
10 |

账号:

11 |

密码:

12 |

13 |
14 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/user/userAdd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | user 6 | 7 | 8 | 9 |
10 |

添加用户

11 |

12 |
13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 |
25 |
26 |
27 | 28 |
29 | 30 |
31 |
32 |
33 |
34 | 35 |       36 | 37 |
38 | 39 |
40 |
41 |
42 | 43 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/user/userEdit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | user 6 | 7 | 8 | 9 |
10 |

修改用户

11 |

12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 |
28 | 29 |
30 | 31 |
32 |
33 |
34 |
35 | 36 |       37 | Back 38 |
39 | 40 |
41 |
42 |
43 | 44 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/main/resources/templates/user/userList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | userList 6 | 7 | 8 | 9 |
10 |

用户列表

11 |

12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
#UserNameNamePasswordSaltStateEditDelete
1neoneoOtto66editdelete
39 |
40 |
41 |
42 | add 43 |
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /springboot-jpa-thymeleaf/src/test/java/com/cy/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.cy; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ 25 | /src/test/ 26 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/README.md: -------------------------------------------------------------------------------- 1 | # 索引 2 | * [springboot整合mybatis](#springboot整合mybatis) 3 | * [springboot整合druid加监控页面](#springboot整合druid加监控页面) 4 | * [springboot整合druid多数据源](#springboot整合druid多数据源) 5 | * [定制启动页面banner](#定制启动页面banner) 6 | * [开启HTTPS协议](#开启HTTPS协议) 7 | * [log4j2配置文件介绍](#log4j2配置文件介绍) 8 | * [spring-security简单的使用](#spring-security简单的使用) 9 | * [Scheduled定时任务](#scheduled定时任务) 10 | * [Async异步执行](#async异步执行) 11 | * [Swagger接口文档生成](#swagger接口文档生成) 12 | * [jsoup简单爬取代理ip](#jsoup简单爬取代理ip) 13 | * [jsoup使用](#jsoup使用) 14 | * [java安装网站ssl证书](#java安装网站ssl证书) 15 | 16 | # springboot整合mybatis 17 | 1. 首先pom文件引入包 18 | ```` 19 | 20 | 21 | org.mybatis.spring.boot 22 | mybatis-spring-boot-starter 23 | 1.3.0 24 | 25 | ```` 26 | 2. 启动类加入注解`@MapperScan("com.cy.dao")` 27 | 3. 配置文件加入mybatis的相关配置 28 | ``` 29 | #mybatis 配置 30 | mybatis.type-aliases-package=com.cy.dao 31 | mybatis.mapper-locations=classpath:mybatis/mapper/*.xml 32 | ``` 33 | 4. 利用mybatis generator工具生成xml 34 | 5. 注意修改namespace,等路径 35 | 36 | # springboot整合druid加监控页面 37 | [Alibaba官方整合文档](https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter "官方文档") 38 | 1. maven导入springboot的依赖 39 | ``` 40 | 41 | 42 | com.alibaba 43 | druid-spring-boot-starter 44 | 1.1.5 45 | 46 | ``` 47 | 2. 配置Druid 48 | ``` 49 | # druid配置 50 | # 初始化大小,最小,最大链接数 51 | spring.datasource.druid.initial-size=3 52 | spring.datasource.druid.min-idle=3 53 | spring.datasource.druid.max-active=10 54 | # 连接超时时间 55 | spring.datasource.druid.max-wait=60000 56 | # 后台登录用户名密码 57 | spring.datasource.druid.stat-view-servlet.login-username=admin 58 | spring.datasource.druid.stat-view-servlet.login-password=admin 59 | # 配置StatFilter 60 | spring.datasource.druid.filter.stat.log-slow-sql=true 61 | spring.datasource.druid.filter.stat.slow-sql-millis=2000 62 | ``` 63 | 3. 启动类加入`@ServletComponentScan`注解,以便访问监控页面 64 | 4. 新建两个类,DruidStatViewServlet,DruidStatFilter 65 | 66 | # springboot整合druid多数据源 67 | 1. maven导入springboot的依赖 68 | ``` 69 | 70 | 71 | com.alibaba 72 | druid-spring-boot-starter 73 | 1.1.5 74 | 75 | ``` 76 | 2. 配置多数据源Druid 77 | ``` 78 | #数据库连接1 79 | spring.datasource.druid.one.url=jdbc:mysql://127.0.0.1/springbootdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true 80 | spring.datasource.druid.one.username=root 81 | spring.datasource.druid.one.password=0.0001 82 | spring.datasource.druid.one.driver-class-name=com.mysql.jdbc.Driver 83 | #数据库连接2 84 | spring.datasource.druid.tow.url=jdbc:mysql://127.0.0.1/springbootdb2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true 85 | spring.datasource.druid.tow.username=root 86 | spring.datasource.druid.tow.password=0.0001 87 | spring.datasource.druid.tow.driver-class-name=com.mysql.jdbc.Driver 88 | # druid配置 89 | # 初始化大小,最小,最大链接数 90 | spring.datasource.druid.initial-size=3 91 | spring.datasource.druid.min-idle=3 92 | spring.datasource.druid.max-active=10 93 | # 连接超时时间 94 | spring.datasource.druid.max-wait=60000 95 | # 后台登录用户名密码 96 | spring.datasource.druid.stat-view-servlet.login-username=admin 97 | spring.datasource.druid.stat-view-servlet.login-password=admin 98 | # 配置StatFilter 99 | spring.datasource.druid.filter.stat.log-slow-sql=true 100 | spring.datasource.druid.filter.stat.slow-sql-millis=2000 101 | # Druid 数据源 1 配置,继承spring.datasource.druid.* 配置,相同则覆盖 102 | spring.datasource.druid.one.max-active=20 103 | spring.datasource.druid.one.max-wait=10000 104 | # Druid 数据源 2 配置,继承spring.datasource.druid.* 配置,相同则覆盖 105 | spring.datasource.druid.two.max-active=30 106 | spring.datasource.druid.two.max-wait=20000 107 | ``` 108 | 3. 添加各自配置类对DataSource、DataSourceTransactionManager、SqlSessionFactory 、SqlSessionTemplate四个数据项进行配置 109 | 4. 对主数据源使用`@Primary`修饰,必须有且只有一个 110 | 111 | # 定制启动页面banner 112 | 1. [打开页面](http://patorjk.com/software/taag/),制作文字图片 113 | 2. 在resource目录下添加banner.txt文件 114 | 3. 复制制作好的图片到banner文件里面 115 | 4. 可以根据喜好,为自己的图案添加控制台输出颜色 [详细配置](/springboot-mybatis-thymeleaf/src/main/resources/banner.txt) 116 | 117 | # yml文件的使用注意 118 | 1. yml格式比较严格,当你启动就报错,就要细心检查yml格式是否有误 119 | 120 | # 开启HTTPS协议 121 | 1. 需要一个ssl证书,我们使用keytool生产(记住密码) 122 | ``` 123 | keytool -keystore ocly.jks -genkey -alias tomcat -keyalg RSA 124 | ``` 125 | 2. 将ocly.jks文件添加到resource目录下 126 | 3. 添加配置文件 127 | ``` 128 | server: 129 | port: 8443 # https 端口号,正式 443;测试 8443 130 | sslPort: 8080 # http 端口号,正式 80;测试 8080 131 | ssl: 132 | key-store: classpath:ocly.jks 133 | key-password: 704739362 134 | ``` 135 | 4. 添加http端口的监听sslconfig 136 | 5. 实现端口转发http到https (使用的undertow目前没解决) 137 | 138 | # log4j2配置文件介绍 139 | [官方文档](http://logging.apache.org/log4j/2.x/manual/configuration.html#YAML) 140 | 1. 通用的6种日志记录级别(低到高) 141 | * trace:追踪,就是程序推进一下,可以写个trace输出 142 | * **debug**:调试,一般作为最低级别,trace基本不用。 143 | * **info**:输出重要的信息,使用较多 144 | * **warn**:警告,有些信息不是错误信息,但也要给程序员一些提示。 145 | * **error**:错误信息。用的也很多。 146 | * fatal:致命错误。 147 | 2. 输出源:CONSOLE(输出到控制台)、FILE(输出到文件)、RollingFile(循环输出到文件) 148 | 3. 布局方式 149 | * SimpleLayout:以简单的形式显示 150 | * HTMLLayout:以HTML表格显示 151 | * PatternLayout:自定义形式显示(首选) 152 | 153 | | 自定义格式|说明 | 154 | | ------------- |:-------------:| 155 | | %t | 线程名称 | 156 | | %p | 日志级别 | 157 | | %c | 日志消息所在类名 | 158 | | %m | 消息内容 | 159 | | %M | 输出执行方法 | 160 | | %d | 日志生产时间 | 161 | | %x | 输出线程上下文堆栈 | 162 | | %L | 代码中的行数 | 163 | | %n | 换行 | 164 | 165 | 4. 编写配置文件yml版(注意pom文件引入包)[详细配置](/springboot-mybatis-thymeleaf/src/main/resources/log4j2.yml) 166 | 5. 为控制台输出添加代码高亮 167 | 6. log记录统一使用占位符形式 168 | 169 | # spring-security简单的使用 170 | 实现内存中验证,只有验证通过才能访问/list页面 171 | 1. 首先pom文件引入包 172 | ```` 173 | 174 | 175 | org.springfragmework.boot 176 | spring-boot-starter-security 177 | 178 | ```` 179 | 2. 添加类SecurityConfig 180 | 3. 使用内存中的身份验证 181 | 4. 使用数据库验证: 182 | * 用户类实现UserDetails,并重写方法(没对角色处理) 183 | * 新建LoginService继承UserDetailsService类,重写方法 184 | * 对类[SecurityConfig](/springboot-mybatis-thymeleaf/src/main/java/com/cy/config/SecurityConfig.java)进行修改 185 | 5. 注意:之前配置的Druid监控页面类会失效 186 | # Scheduled定时任务 187 | 1. 启动类加入@EnableScheduling注解 188 | 2. 编写定时任务,必须是无返回方法 189 | 3. 定时任务参数设置 190 | * fixedRate = 5 * 1000 上一次开始执行时间点之后5秒再执行 191 | * fixedDelay = 5 * 1000 上一次执行完毕时间点之后5秒再执行 192 | * initialDelay = 1000, fixedRate = 5000 第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次 193 | * cron="*/5 * * * * *" 每5秒执行一次 [在线cron表达式生成](http://cron.qqe2.com/) 194 | 195 | # Async异步执行 196 | 1. 启动类加入@EnableAsync注解,开启异步功能 197 | 2. 类方法加入@Async注解:注:(不能定义为static类型 198 | 3. 如果需要判断异步是否执行完成,需要使用Future来返回异步调用的结果 199 | 200 | # Swagger接口文档生成 201 | 1. pom文件引入包(ui版本尽量和swagger版本相同) 202 | ```` 203 | 204 | io.springfox 205 | springfox-swagger2 206 | 2.6.1 207 | 208 | 209 | io.springfox 210 | springfox-swagger-ui 211 | 2.6.1 212 | 213 | ```` 214 | 2. 添加[Swagger](/springboot-mybatis-thymeleaf/src/main/java/com/cy/Swagger.java)配置类 215 | 3. 给Api接口添加注解 注:(/user/{id} ,参数设置加入paramType = "path" 216 | 217 | # jsoup简单爬取代理ip 218 | 1. 简单看看jsoup[入门教程](http://www.open-open.com/jsoup/) 219 | 220 | 2. 新建一个springboot项目 221 | 222 | 3. maven引入依赖 223 | 224 | 225 | org.jsoup 226 | jsoup 227 | 1.10.2 228 | 229 | 230 | 4. 寻找爬取目标,百度代理ip即可 `http://www.data5u.com/` 231 | 232 | 5. 分析网页,模拟请求,发现只需User-Agent即可访问到页面内容 233 | 234 | 6. 创建dom对象,通过select选择器完成爬取 235 | ``` 236 | public void ipProxy() throws Exception { 237 | Document doc = Jsoup.connect(URL_IP).userAgent(USER_AGENT).get(); 238 | Elements ips = doc.select("body > div:nth-child(8) > ul > li:nth-child(2) > ul.l2").next(); 239 | for (int i = 0; i <= ips.size(); i++) { 240 | String ipaddr = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(1) > li").text(); 241 | String proxy = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(2) > li").text(); 242 | String speed = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(8) > li").text(); 243 | log.info("ip: {}----端口: {} ----速度:{} ", ipaddr, proxy, speed); 244 | } 245 | } 246 | ``` 247 | 7. select选择器使用技巧,Chrome浏览器F12>选中元素>右键>copy selector即可 248 | 249 | 8. 代理ip的设置, .proxy("地址",端口)即可,注意捕获异常 250 | 251 | # jsoup使用 252 | 253 | ``` 254 | /** 255 | * 关闭TSL SSL认证 256 | */ 257 | Jsoup.connect("").validateTLSCertificates(false).execute(); 258 | /** 259 | * 关闭重定向 260 | */ 261 | Jsoup.connect("").followRedirects(false).execute(); 262 | /** 263 | * get请求 execute默认就是get请求 返回Document 264 | */ 265 | Document parse = Jsoup.connect("").execute().parse(); 266 | Document parse1 = Jsoup.connect("").get(); 267 | /** 268 | * get请求 返回json 269 | */ 270 | String data1 = Jsoup.connect("").ignoreContentType(true).execute().body(); 271 | /** 272 | * post请求 execute设置为post 273 | */ 274 | Map data = new HashMap(); 275 | data.put("username", ""); 276 | Document post = Jsoup.connect("").data(data).post(); 277 | Document post1 = Jsoup.connect("").data("","").method(Connection.Method.POST).execute().parse(); 278 | 279 | /** 280 | * post请求 json数据 281 | */ 282 | JSONObject jsonObject = new JSONObject(); 283 | jsonObject.put("", ""); 284 | Document post2 = Jsoup.connect("").requestBody(jsonObject.toString()).post(); 285 | /** 286 | * 提交cookie 可以用map 287 | */ 288 | Jsoup.connect("").cookie("","").execute(); 289 | /** 290 | * 提交协议头 可以用map 291 | */ 292 | Jsoup.connect("").header("","").execute(); 293 | /** 294 | * 返回协议头 协议头居然没有cookie 295 | */ 296 | Jsoup.connect("").execute().headers(); 297 | /** 298 | * 返回cookie 因为map类型 同名的cookie只返回一个,这个比较坑 299 | */ 300 | Jsoup.connect("").execute().cookies(); 301 | 302 | ``` 303 | # java安装网站ssl证书 304 | 1. 下载网站证书,访问网站>chrom按F12 305 | 2. 点击Security>点击view certificate>详细信息>复制到文件 306 | 3. 点击下一步>选择Base64编码>选择路径保存>D://abc.cer 307 | 4. cmd切换到java/jre的/lib/security/下 308 | 5. `keytool -import -alias abc -keystore cacerts -file D://abc.cer` 309 | 6. 库密钥口令输入:changeit 310 | 7. 是 311 | 8. 查看证书`keytool -list -keystore cacerts -alias abc` 312 | 9. 删除证书`keytool -delete -alias abc -keystore cacerts ` 313 | 10. 可以使用InatallCert直接从网站生成文件 -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.cy 7 | springboot-mybatis-thymeleaf 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | springboot-mybatis-thymeleaf 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.8.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-logging 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-tomcat 40 | 41 | 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-undertow 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-log4j2 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-thymeleaf 59 | 60 | 61 | 62 | 63 | mysql 64 | mysql-connector-java 65 | 66 | 67 | 68 | 69 | org.mybatis.spring.boot 70 | mybatis-spring-boot-starter 71 | 1.3.0 72 | 73 | 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-starter-data-redis 78 | 79 | 80 | 81 | 82 | com.alibaba 83 | druid-spring-boot-starter 84 | 1.1.5 85 | 86 | 87 | 88 | org.springframework.boot 89 | spring-boot-devtools 90 | true 91 | 92 | 93 | org.springframework 94 | spring-jdbc 95 | 4.3.3.RELEASE 96 | 97 | 98 | 99 | com.fasterxml.jackson.dataformat 100 | jackson-dataformat-yaml 101 | 102 | 103 | 104 | org.projectlombok 105 | lombok 106 | 1.16.14 107 | 108 | 109 | 110 | org.springframework.boot 111 | spring-boot-starter-security 112 | 113 | 114 | 115 | io.springfox 116 | springfox-swagger2 117 | 2.2.2 118 | 119 | 120 | io.springfox 121 | springfox-swagger-ui 122 | 2.2.2 123 | 124 | 125 | 126 | org.jsoup 127 | jsoup 128 | 1.10.2 129 | 130 | 131 | 132 | net.sourceforge.nekohtml 133 | nekohtml 134 | 1.9.22 135 | 136 | 137 | 138 | 139 | org.apache.httpcomponents 140 | httpclient 141 | 4.5.2 142 | 143 | 144 | 145 | com.alibaba 146 | fastjson 147 | 1.2.41 148 | 149 | 150 | 151 | 152 | 153 | 154 | org.springframework.boot 155 | spring-boot-maven-plugin 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/Application.java: -------------------------------------------------------------------------------- 1 | package com.cy; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.annotation.EnableScheduling; 7 | 8 | 9 | @SpringBootApplication 10 | @EnableScheduling 11 | @EnableAsync 12 | public class Application { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(Application.class, args); 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/Swagger.java: -------------------------------------------------------------------------------- 1 | package com.cy; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import springfox.documentation.builders.ApiInfoBuilder; 6 | import springfox.documentation.builders.PathSelectors; 7 | import springfox.documentation.builders.RequestHandlerSelectors; 8 | import springfox.documentation.service.ApiInfo; 9 | import springfox.documentation.spi.DocumentationType; 10 | import springfox.documentation.spring.web.plugins.Docket; 11 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 12 | 13 | /** 14 | * Created by cy 15 | * 2017/12/7 16:25 16 | */ 17 | @EnableSwagger2 18 | @Configuration 19 | public class Swagger { 20 | @Bean 21 | public Docket createRestApi() { 22 | return new Docket(DocumentationType.SWAGGER_2) 23 | .apiInfo(apiInfo()) 24 | .select() 25 | .apis(RequestHandlerSelectors.basePackage("com.cy.api")) 26 | .paths(PathSelectors.any()) 27 | .build(); 28 | } 29 | 30 | private ApiInfo apiInfo() { 31 | return new ApiInfoBuilder() 32 | .title("OclyAPI文档") 33 | .termsOfServiceUrl("http://blog.didispace.com/") 34 | .contact("Ocly") 35 | .version("1.0") 36 | .build(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/api/UserAPI.java: -------------------------------------------------------------------------------- 1 | package com.cy.api; 2 | 3 | import com.cy.entity.User; 4 | import com.cy.service.UserService; 5 | import io.swagger.annotations.ApiImplicitParam; 6 | import io.swagger.annotations.ApiOperation; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Created by cy 17 | * 2017/12/7 10:31 18 | */ 19 | @RestController 20 | public class UserAPI { 21 | @Autowired 22 | private UserService userService; 23 | 24 | @ApiOperation(value = "获取用户列表", notes = "获取用户列表所有信息") 25 | @GetMapping("/api/user") 26 | public List getAll() { 27 | return userService.userList(); 28 | } 29 | 30 | @ApiOperation(value = "通过Id获取用户信息", notes = "通过Id获取用户信息") 31 | @ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long", paramType = "path") 32 | @GetMapping("/api/user/{id}") 33 | public User getById(@PathVariable Long id) { 34 | return userService.getUser(id); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/config/OneDataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | 3 | import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.mybatis.spring.SqlSessionFactoryBean; 9 | import org.mybatis.spring.SqlSessionTemplate; 10 | import org.springframework.beans.factory.annotation.Qualifier; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.context.annotation.Primary; 13 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 14 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 15 | 16 | import javax.sql.DataSource; 17 | 18 | 19 | /** 20 | * Created by cy 21 | * 2017/12/1 10:39 22 | */ 23 | @Configuration 24 | @MapperScan(basePackages = "com.cy.dao", sqlSessionTemplateRef = "oneSqlSessionTemplate") 25 | public class OneDataSourceConfig { 26 | 27 | @Bean(name = "oneDataSource") 28 | @ConfigurationProperties(prefix = "spring.datasource.one") 29 | @Primary 30 | public DataSource oneDataSource() { 31 | return DruidDataSourceBuilder.create().build(); 32 | } 33 | 34 | @Bean(name = "oneTransactionManager") 35 | @Primary 36 | public DataSourceTransactionManager oneTransactionManager(@Qualifier("oneDataSource") DataSource dataSource) { 37 | return new DataSourceTransactionManager(dataSource); 38 | } 39 | 40 | @Bean(name = "oneSqlSessionFactory") 41 | @Primary 42 | public SqlSessionFactory oneSqlSessionFactory(@Qualifier("oneDataSource") DataSource dataSource) throws Exception { 43 | SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); 44 | bean.setDataSource(dataSource); 45 | //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/*.xml")); 46 | return bean.getObject(); 47 | } 48 | 49 | @Bean(name = "oneSqlSessionTemplate") 50 | @Primary 51 | public SqlSessionTemplate oneSqlSessionTemplate(@Qualifier("oneSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { 52 | return new SqlSessionTemplate(sqlSessionFactory); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | import com.cy.service.impl.LoginService; 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 9 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | 13 | /** 14 | * 安全控制 15 | * Created by cy 16 | * 2017/12/6 15:51 17 | */ 18 | @EnableWebSecurity 19 | @Configuration 20 | public class SecurityConfig extends WebSecurityConfigurerAdapter{ 21 | 22 | @Bean 23 | UserDetailsService loginService() { 24 | return new LoginService(); 25 | } 26 | @Override 27 | public void configure(WebSecurity web) throws Exception { 28 | web.ignoring().antMatchers("/druid/**"); 29 | } 30 | @Override 31 | protected void configure(AuthenticationManagerBuilder auth) throws Exception { 32 | auth.userDetailsService(loginService()); 33 | } 34 | @Override 35 | protected void configure(HttpSecurity http) throws Exception { 36 | http 37 | .authorizeRequests() 38 | .antMatchers("/list","/api/**").authenticated() 39 | .anyRequest().permitAll() 40 | .and() 41 | .formLogin() 42 | .loginPage("/login") 43 | .defaultSuccessUrl("/list").failureUrl("/?error") 44 | .permitAll() 45 | .and() 46 | .logout() 47 | .permitAll() 48 | .and().portMapper().http(80).mapsTo(443) 49 | .and().csrf().disable(); 50 | http.rememberMe().alwaysRemember(true); 51 | 52 | // //设置默认登录成功跳转页面 53 | // .defaultSuccessUrl("/index").failureUrl("/login?error").permitAll() 54 | // .and() 55 | // //开启cookie保存用户数据 56 | // .rememberMe() 57 | // //设置cookie有效期 58 | // .tokenValiditySeconds(60 * 60 * 24 * 7) 59 | // //设置cookie的私钥 60 | // .key("") 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/config/SslConfig.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; 5 | import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | @Configuration 10 | public class SslConfig { 11 | 12 | @Value("${server.sslPort}") 13 | private int port; 14 | 15 | /** 16 | * 增加 80 端口的监听 17 | */ 18 | @Bean 19 | public EmbeddedServletContainerFactory servletContainer() { 20 | UndertowEmbeddedServletContainerFactory undertowFactory = new UndertowEmbeddedServletContainerFactory(); 21 | undertowFactory.addBuilderCustomizers(builder -> builder.addHttpListener(port, "0.0.0.0")); 22 | return undertowFactory; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/config/TowDataSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.cy.config; 2 | 3 | import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; 4 | import org.apache.ibatis.session.SqlSessionFactory; 5 | import org.mybatis.spring.SqlSessionFactoryBean; 6 | import org.mybatis.spring.SqlSessionTemplate; 7 | import org.mybatis.spring.annotation.MapperScan; 8 | import org.springframework.beans.factory.annotation.Qualifier; 9 | import org.springframework.boot.context.properties.ConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 13 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 14 | import javax.sql.DataSource; 15 | 16 | 17 | /** 18 | * Created by cy 19 | * 2017/12/1 10:39 20 | */ 21 | @Configuration 22 | @MapperScan(basePackages = "com.cy.daos", sqlSessionTemplateRef = "towSqlSessionTemplate") 23 | public class TowDataSourceConfig { 24 | 25 | @Bean(name = "towDataSource") 26 | @ConfigurationProperties(prefix = "spring.datasource.tow") 27 | public DataSource setDataSource() { 28 | return DruidDataSourceBuilder.create().build(); 29 | } 30 | 31 | @Bean(name = "towTransactionManager") 32 | public DataSourceTransactionManager testTransactionManager(@Qualifier("towDataSource") DataSource dataSource) { 33 | return new DataSourceTransactionManager(dataSource); 34 | } 35 | 36 | @Bean(name = "towSqlSessionFactory") 37 | public SqlSessionFactory testSqlSessionFactory(@Qualifier("towDataSource") DataSource dataSource) throws Exception { 38 | SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); 39 | bean.setDataSource(dataSource); 40 | // bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/*.xml")); 41 | return bean.getObject(); 42 | } 43 | 44 | @Bean(name = "towSqlSessionTemplate") 45 | public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("towSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { 46 | return new SqlSessionTemplate(sqlSessionFactory); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.cy.controller; 2 | 3 | import com.cy.entity.User; 4 | import com.cy.service.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.ui.Model; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | 12 | /** 13 | * Created by cy 14 | * 2017/11/22 17:07 15 | */ 16 | @Controller 17 | public class UserController { 18 | @Autowired 19 | private UserService userService; 20 | 21 | @GetMapping(value = "/") 22 | public String loginpage() { 23 | return "login"; 24 | } 25 | 26 | @RequestMapping(value = "/login") 27 | public String login() { 28 | return "login"; 29 | } 30 | 31 | @GetMapping(value = "/list") 32 | public String userList(Model model) { 33 | model.addAttribute("userList", userService.userList()); 34 | return "data"; 35 | } 36 | 37 | @GetMapping(value = "/toEdit") 38 | public String getUser(Long id, Model model) { 39 | model.addAttribute("user", userService.getUser(id)); 40 | return "user/userEdit"; 41 | } 42 | 43 | @PostMapping(value = "/edit") 44 | public String editUser(User user) { 45 | userService.editUser(user); 46 | return "redirect:/list"; 47 | } 48 | 49 | @GetMapping(value = "/delete") 50 | public String deleteUser(Long id) { 51 | userService.deleteUser(id); 52 | return "redirect:/list"; 53 | } 54 | 55 | @PostMapping(value = "/add") 56 | public String addUser(User user) { 57 | userService.saveUser(user); 58 | return "redirect:/list"; 59 | } 60 | 61 | @GetMapping(value = "/toAdd") 62 | public String addUser() { 63 | return "user/userAdd"; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/dao/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.cy.dao; 2 | 3 | import com.cy.entity.User; 4 | import org.apache.ibatis.annotations.*; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/11/30 15:08 11 | */ 12 | public interface UserMapper { 13 | @Delete("DELETE FROM user WHERE `id` = #{id}") 14 | int deleteById(@Param("id") Long id); 15 | 16 | @Insert("INSERT INTO user(`id`, `name`, `password`, `age`) VALUES (#{id}, #{name}, #{password}, #{age})") 17 | int insert(User user); 18 | 19 | @Select("SELECT * FROM user") 20 | List findAll(); 21 | 22 | @Select("SELECT * FROM user WHERE `id` = #{id}") 23 | User findById(@Param("id") Long id); 24 | 25 | @Update("UPDATE user SET name = #{name}, password = #{password}, age = #{age} WHERE id = #{id}") 26 | int update(User user); 27 | 28 | @Select("SELECT * FROM user WHERE `name` = #{name} AND `password` = #{password}") 29 | User findByUser(User user); 30 | 31 | @Select("SELECT * FROM user WHERE `name` = #{name}") 32 | User findByUsername(@Param("name") String name); 33 | } 34 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/entity/Result.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * Created by cy 7 | * 2017/12/8 17:29 8 | */ 9 | @Data 10 | public class Result { 11 | 12 | /** 13 | * 返回错误码 14 | */ 15 | private Integer code; 16 | /** 17 | * 返回提示信息 18 | */ 19 | private String msg; 20 | /** 21 | * 具体内容 22 | */ 23 | private T data; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.cy.entity; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | import java.io.Serializable; 7 | import java.util.Collection; 8 | 9 | /** 10 | * Created by cy 11 | * 2017/11/22 14:05 12 | */ 13 | public class User implements Serializable,UserDetails { 14 | private Long id; 15 | private String name; 16 | private String password; 17 | private String age; 18 | 19 | public Long getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Long id) { 24 | this.id = id; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | @Override 36 | public Collection getAuthorities() { 37 | return null; 38 | } 39 | 40 | public String getPassword() { 41 | return this.password; 42 | } 43 | 44 | @Override 45 | public String getUsername() { 46 | return this.name; 47 | } 48 | 49 | @Override 50 | public boolean isAccountNonExpired() { 51 | return true; 52 | } 53 | 54 | @Override 55 | public boolean isAccountNonLocked() { 56 | return true; 57 | } 58 | 59 | @Override 60 | public boolean isCredentialsNonExpired() { 61 | return true; 62 | } 63 | 64 | @Override 65 | public boolean isEnabled() { 66 | return true; 67 | } 68 | 69 | public void setPassword(String password) { 70 | this.password = password; 71 | } 72 | 73 | public String getAge() { 74 | return age; 75 | } 76 | 77 | public void setAge(String age) { 78 | this.age = age; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "User{" + 84 | "id=" + id + 85 | ", name='" + name + '\'' + 86 | ", password='" + password + '\'' + 87 | ", age='" + age + '\'' + 88 | '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/enums/ResultEnum.java: -------------------------------------------------------------------------------- 1 | package com.cy.enums; 2 | 3 | 4 | /** 5 | * Created by cy 6 | * 2017/12/8 17:39 7 | */ 8 | public enum ResultEnum { 9 | 10 | SUCCESS(200,"成功"),//成功 11 | FAIL(400,"失败"),//失败 12 | UNAUTHORIZED(401,"未认证(签名错误)"),//未认证(签名错误) 13 | NOT_FOUND(404,"接口不存在"),//接口不存在 14 | INTERNAL_SERVER_ERROR(500,"服务器内部错误");//服务器内部错误 15 | 16 | 17 | private Integer code; 18 | 19 | private String msg; 20 | 21 | ResultEnum(Integer code, String msg) { 22 | this.code = code; 23 | this.msg = msg; 24 | } 25 | 26 | public Integer getCode() { 27 | return code; 28 | } 29 | 30 | public String getMsg() { 31 | return msg; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/exception/AllException.java: -------------------------------------------------------------------------------- 1 | package com.cy.exception; 2 | 3 | import com.cy.enums.ResultEnum; 4 | 5 | /** 6 | * Created by cy 7 | * 2017/12/11 8:31 8 | */ 9 | public class AllException extends RuntimeException { 10 | 11 | private Integer code; 12 | 13 | public AllException (ResultEnum resultEnum){ 14 | super(resultEnum.getMsg()); 15 | this.code = resultEnum.getCode(); 16 | } 17 | public AllException (String message){ 18 | super(message); 19 | } 20 | 21 | public Integer getCode() { 22 | return code; 23 | } 24 | 25 | public void setCode(Integer code) { 26 | this.code = code; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/exception/AllExceptionHandle.java: -------------------------------------------------------------------------------- 1 | package com.cy.exception; 2 | 3 | import com.cy.entity.Result; 4 | import com.cy.util.ResultUtil; 5 | import lombok.extern.log4j.Log4j2; 6 | import org.springframework.web.bind.annotation.ControllerAdvice; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | import org.springframework.web.bind.annotation.ResponseBody; 9 | import org.springframework.web.bind.annotation.RestControllerAdvice; 10 | 11 | /** 12 | * Created by cy 13 | * 2017/12/11 8:37 14 | */ 15 | @RestControllerAdvice 16 | @Log4j2 17 | public class AllExceptionHandle { 18 | 19 | /** 20 | * 处理全局异常 21 | */ 22 | @ExceptionHandler(Exception.class) 23 | public Result handlerGlobalException(Exception exception){ 24 | if (exception instanceof AllException) { 25 | AllException allException = (AllException) exception; 26 | return ResultUtil.error(allException.getCode(), allException.getMessage()); 27 | }else { 28 | log.error("【系统异常】{}", exception.getMessage()); 29 | return ResultUtil.error(-1, "未知错误"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/filter/DruidStatFilter.java: -------------------------------------------------------------------------------- 1 | package com.cy.filter; 2 | 3 | import com.alibaba.druid.support.http.WebStatFilter; 4 | 5 | import javax.servlet.annotation.WebFilter; 6 | import javax.servlet.annotation.WebInitParam; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/11/30 20:40 11 | */ 12 | @WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", 13 | initParams={ 14 | @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 15 | }) 16 | public class DruidStatFilter extends WebStatFilter { 17 | } 18 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.cy.service; 2 | 3 | import com.cy.entity.User; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/11/22 16:47 10 | */ 11 | public interface UserService { 12 | 13 | List userList(); 14 | 15 | User getUser(Long id); 16 | 17 | int deleteUser(Long id); 18 | 19 | int saveUser(User user); 20 | 21 | int editUser(User user); 22 | 23 | User login(User user); 24 | } 25 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/service/impl/LoginService.java: -------------------------------------------------------------------------------- 1 | package com.cy.service.impl; 2 | 3 | import com.cy.dao.UserMapper; 4 | import com.cy.entity.User; 5 | import lombok.extern.log4j.Log4j2; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | 11 | /** 12 | * Created by cy 13 | * 2017/12/6 18:44 14 | */ 15 | @Log4j2 16 | public class LoginService implements UserDetailsService { 17 | @Autowired 18 | private UserMapper userMapper; 19 | 20 | @Override 21 | public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { 22 | User user = userMapper.findByUsername(s); 23 | if (user == null) { 24 | throw new UsernameNotFoundException("用户名不存在"); 25 | } 26 | log.info("LoginService: username: {}, password: {}", user.getName(), user.getPassword()); 27 | return user; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.cy.service.impl; 2 | 3 | import com.cy.dao.UserMapper; 4 | import com.cy.entity.User; 5 | import com.cy.enums.ResultEnum; 6 | import com.cy.exception.AllException; 7 | import com.cy.service.UserService; 8 | import lombok.extern.log4j.Log4j2; 9 | import org.apache.logging.log4j.LogManager; 10 | import org.apache.logging.log4j.Logger; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.data.redis.core.RedisTemplate; 13 | import org.springframework.data.redis.core.ValueOperations; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | import java.util.concurrent.TimeUnit; 19 | 20 | /** 21 | * Created by cy 22 | * 2017/11/22 16:50 23 | */ 24 | @Service 25 | @Log4j2 26 | public class UserServiceImpl implements UserService { 27 | 28 | @Autowired 29 | private UserMapper userMapper; 30 | @Autowired 31 | private RedisTemplate redisTemplate; 32 | 33 | 34 | @Override 35 | public List userList() { 36 | return userMapper.findAll(); 37 | } 38 | 39 | @Override 40 | public User getUser(Long id) { 41 | String key = "user_" + id; 42 | ValueOperations operations = redisTemplate.opsForValue(); 43 | // 缓存存在 44 | boolean hasKey = redisTemplate.hasKey(key); 45 | if (hasKey) { 46 | User user = operations.get(key); 47 | log.info("从缓存中获取用户信息>>{} ", user.toString()); 48 | return user; 49 | } 50 | // 插入缓存 51 | User user = userMapper.findById(id); 52 | operations.set(key, user, 100, TimeUnit.SECONDS); 53 | log.info("用户信息插入缓存 >>{} ", user.toString()); 54 | return user; 55 | } 56 | 57 | @Override 58 | @Transactional 59 | public int deleteUser(Long id) { 60 | int ret = userMapper.deleteById(id); 61 | String key = "user_" + id; 62 | boolean hasKey = redisTemplate.hasKey(key); 63 | if (hasKey) { 64 | redisTemplate.delete(key); 65 | log.error("从缓存中删除用户 >>{} ", id); 66 | } 67 | return ret; 68 | } 69 | 70 | @Override 71 | @Transactional 72 | public int saveUser(User user) { 73 | return userMapper.insert(user); 74 | } 75 | 76 | @Override 77 | @Transactional 78 | public int editUser(User user) { 79 | int i = userMapper.update(user); 80 | String key = "user_" + user.getId(); 81 | boolean hasKey = redisTemplate.hasKey(key); 82 | if (hasKey) { 83 | redisTemplate.delete(key); 84 | log.error("从缓存中删除用户 >> {}", user.toString()); 85 | } 86 | return i; 87 | } 88 | 89 | @Override 90 | public User login(User user) { 91 | log.info("用户名:{},密码:{}",user.getName(),user.getPassword()); 92 | return userMapper.findByUser(user); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/servlet/DruidStatViewServlet.java: -------------------------------------------------------------------------------- 1 | package com.cy.servlet; 2 | 3 | import com.alibaba.druid.support.http.StatViewServlet; 4 | 5 | import javax.servlet.annotation.WebInitParam; 6 | import javax.servlet.annotation.WebServlet; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/11/30 20:38 11 | */ 12 | @SuppressWarnings("serial") 13 | @WebServlet(urlPatterns = "/druid/*", 14 | initParams={ 15 | @WebInitParam(name="allow",value="127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) 16 | @WebInitParam(name="deny",value=""),// IP黑名单 (存在共同时,deny优先于allow) 17 | @WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能 18 | }) 19 | public class DruidStatViewServlet extends StatViewServlet { 20 | } 21 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/task/AsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.cy.task; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.scheduling.annotation.Async; 6 | import org.springframework.scheduling.annotation.AsyncResult; 7 | import org.springframework.scheduling.annotation.Scheduled; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Date; 11 | import java.util.concurrent.Future; 12 | 13 | /** 14 | * 异步执行测试学习 15 | * 16 | * Created by cy 17 | * 2017/12/7 10:53 18 | */ 19 | @Component 20 | @Log4j2 21 | public class AsyncTask { 22 | 23 | @Async 24 | public Future taskOne() throws Exception { 25 | log.info("taskOne开始睡觉"); 26 | Thread.sleep(5000); 27 | log.info("taskOne睡完觉"); 28 | return new AsyncResult<>("完成"); 29 | } 30 | @Async 31 | public Future taskTwo() throws Exception { 32 | log.info("taskTwo开始睡觉"); 33 | Thread.sleep(5000); 34 | log.info("taskTwo睡完觉"); 35 | return new AsyncResult<>("完成"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/task/Task.java: -------------------------------------------------------------------------------- 1 | package com.cy.task; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.jsoup.Jsoup; 5 | import org.jsoup.nodes.Document; 6 | import org.jsoup.nodes.Element; 7 | import org.jsoup.select.Elements; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * Created by cy 15 | * 2017/12/7 13:34 16 | */ 17 | @Component 18 | @Log4j2 19 | public class Task { 20 | 21 | @Autowired 22 | private AsyncTask asyncTask; 23 | 24 | private final static String URL = "http://top.baidu.com/buzz?b=341&c=513&fr=topbuzz_b1"; 25 | private final static String URL_IP = "http://www.data5u.com/"; 26 | private final static String URL_BLOG = "http://blog.csdn.net/yy1193889747/article/details/78785776"; 27 | private final static String USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Mobile Safari/537.36"; 28 | 29 | /** 30 | * 测试 31 | */ 32 | //@Scheduled(fixedRate = 60 * 60 * 1000) 33 | public void reportCurrentTime() throws Exception { 34 | long start = System.currentTimeMillis(); 35 | asyncTask.taskOne(); 36 | asyncTask.taskTwo(); 37 | long end = System.currentTimeMillis(); 38 | log.info("总耗时:{} 毫秒", end - start); 39 | } 40 | 41 | /** 42 | * 代理Ip爬取 43 | */ 44 | // @Scheduled(fixedRate = 10 * 60 * 1000) 45 | public void ipProxy() throws IOException { 46 | Document doc = Jsoup.connect(URL_IP).userAgent(USER_AGENT).get(); 47 | Elements ips = doc.select("body > div:nth-child(8) > ul > li:nth-child(2) > ul.l2").next(); 48 | log.info("ip个数:{}", ips.size()); 49 | for (int i = 0; i <= ips.size(); i++) { 50 | String ipaddr = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(1) > li").text(); 51 | String proxy = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(2) > li").text(); 52 | String speed = ips.select("ul:nth-child(" + (i + 2) + ") > span:nth-child(8) > li").text(); 53 | log.info("ip: {}----端口: {} ----速度:{} ", ipaddr, proxy, speed); 54 | if (!"".equals(proxy)) { 55 | try { 56 | Jsoup.connect(URL_BLOG).proxy(ipaddr, Integer.parseInt(proxy)).ignoreHttpErrors(false).timeout(3000).get(); 57 | } catch (IOException e) { 58 | log.info("不能用"); 59 | } 60 | } 61 | } 62 | } 63 | 64 | /** 65 | * 百度今日热点爬取 66 | */ 67 | //@Scheduled(fixedRate = 60 * 60 * 1000) 68 | public void baidu() throws Exception { 69 | Document doc = Jsoup.connect(URL).get(); 70 | Elements news = doc.select("#main > div.mainBody > div > table > tbody > tr").next(); 71 | for (Element newa : news) { 72 | String flag = newa.select("td.keyword > a.list-title").text(); 73 | String url = newa.select("td.keyword > a.list-title").attr("href"); 74 | String hot = newa.select("td.last > span").text(); 75 | 76 | log.info("关键字: {}----地址: {} ----热度:{} ", flag, url, hot); 77 | 78 | } 79 | } 80 | 81 | 82 | public static void main(String[] args) throws Exception { 83 | Task task = new Task(); 84 | task.baidu(); 85 | 86 | } 87 | // @Scheduled(cron="0/5 * * * * ? ") //每5秒执行一次 88 | // "0 0 12 * * ?" 每天中午十二点触发 89 | // "0 15 10 ? * *" 每天早上10:15触发 90 | // "0 15 10 * * ?" 每天早上10:15触发 91 | // "0 15 10 * * ? *" 每天早上10:15触发 92 | // "0 15 10 * * ? 2005" 2005年的每天早上10:15触发 93 | // "0 * 14 * * ?" 每天从下午2点开始到2点59分每分钟一次触发 94 | // "0 0/5 14 * * ?" 每天从下午2点开始到2:55分结束每5分钟一次触发 95 | // "0 0/5 14,18 * * ?" 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发 96 | // "0 0-5 14 * * ?" 每天14:00至14:05每分钟一次触发 97 | // "0 10,44 14 ? 3 WED" 三月的每周三的14:10和14:44触发 98 | // "0 15 10 ? * MON-FRI" 每个周一、周二、周三、周四、周五的10:15触发 99 | } 100 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/util/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.cy.util; 2 | 3 | import org.apache.http.Header; 4 | import org.apache.http.HeaderIterator; 5 | import org.apache.http.client.ClientProtocolException; 6 | import org.apache.http.client.CookieStore; 7 | import org.apache.http.client.config.RequestConfig; 8 | import org.apache.http.client.entity.UrlEncodedFormEntity; 9 | import org.apache.http.client.methods.CloseableHttpResponse; 10 | import org.apache.http.client.methods.HttpPost; 11 | import org.apache.http.config.Registry; 12 | import org.apache.http.config.RegistryBuilder; 13 | import org.apache.http.conn.socket.ConnectionSocketFactory; 14 | import org.apache.http.conn.socket.PlainConnectionSocketFactory; 15 | import org.apache.http.conn.ssl.NoopHostnameVerifier; 16 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 17 | import org.apache.http.conn.ssl.TrustStrategy; 18 | import org.apache.http.cookie.Cookie; 19 | import org.apache.http.impl.client.BasicCookieStore; 20 | import org.apache.http.impl.client.CloseableHttpClient; 21 | import org.apache.http.impl.client.HttpClients; 22 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 23 | import org.apache.http.message.BasicNameValuePair; 24 | import org.apache.http.ssl.SSLContextBuilder; 25 | 26 | import java.io.*; 27 | import java.net.HttpURLConnection; 28 | import java.net.URL; 29 | import java.security.KeyManagementException; 30 | import java.security.KeyStoreException; 31 | import java.security.NoSuchAlgorithmException; 32 | import java.security.cert.CertificateException; 33 | import java.security.cert.X509Certificate; 34 | import java.util.ArrayList; 35 | import java.util.HashMap; 36 | import java.util.List; 37 | import java.util.Map; 38 | 39 | /** 40 | * Created by cy 41 | * 2017/12/20 18:42 42 | */ 43 | public class HttpUtils { 44 | private static final String HTTP = "http"; 45 | private static final String HTTPS = "https"; 46 | private static SSLConnectionSocketFactory sslsf = null; 47 | private static PoolingHttpClientConnectionManager cm = null; 48 | private static SSLContextBuilder builder = null; 49 | static { 50 | try { 51 | builder = new SSLContextBuilder(); 52 | // 全部信任 不做身份鉴定 53 | builder.loadTrustMaterial(null, new TrustStrategy() { 54 | @Override 55 | public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 56 | return true; 57 | } 58 | }); 59 | sslsf = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE); 60 | Registry registry = RegistryBuilder.create() 61 | .register(HTTP, new PlainConnectionSocketFactory()) 62 | .register(HTTPS, sslsf) 63 | .build(); 64 | cm = new PoolingHttpClientConnectionManager(registry); 65 | cm.setMaxTotal(200);//max connection 66 | } catch (Exception e) { 67 | e.printStackTrace(); 68 | } 69 | } 70 | /** 71 | * java net 包 发送post请求 72 | * 73 | * @param path url 74 | * @param post xx=xx&yy=yy 75 | * @return 根据需要返回 页面 或者协议头 76 | */ 77 | 78 | public static String netpost(String path, String post) { 79 | URL url = null; 80 | try { 81 | url = new URL(path); 82 | HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 83 | // 设置禁止重定向 84 | httpURLConnection.setInstanceFollowRedirects(false); 85 | httpURLConnection.setRequestMethod("POST");// 提交模式 86 | // conn.setConnectTimeout(10000);//连接超时 单位毫秒 87 | // conn.setReadTimeout(2000);//读取超时 单位毫秒 88 | // 发送POST请求必须设置如下两行 89 | httpURLConnection.setDoOutput(true); 90 | httpURLConnection.setDoInput(true); 91 | // 获取URLConnection对象对应的输出流 92 | PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); 93 | // 发送请求参数 94 | printWriter.write(post);// post的参数 xx=xx&yy=yy 95 | // flush输出流的缓冲 96 | printWriter.flush(); 97 | // 开始获取数据 98 | Map> ss = httpURLConnection.getHeaderFields(); 99 | List cookie = ss.get("Set-Cookie"); 100 | for (int i = 0; i < cookie.size(); i++) { 101 | System.out.println(cookie.get(i).toString()); 102 | } 103 | String cc = cookie.get(2).toString().substring(21, 53); 104 | System.out.println(cc); 105 | 106 | BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream()); 107 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 108 | int len; 109 | byte[] arr = new byte[1024]; 110 | while ((len = bis.read(arr)) != -1) { 111 | bos.write(arr, 0, len); 112 | bos.flush(); 113 | } 114 | bos.close(); 115 | System.out.println(bos.toString()); 116 | // return bos.toString("utf-8"); 117 | return cc; 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | } 121 | return null; 122 | } 123 | 124 | public static Map getCookie() throws IOException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException { 125 | Map cookiemap = new HashMap(); 126 | RequestConfig config = RequestConfig.custom().setRedirectsEnabled(false).build();// 不允许重定向 127 | CookieStore cookieStore = new BasicCookieStore();// 整个cookiestore 128 | 129 | CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(config).setDefaultCookieStore(cookieStore).setSSLSocketFactory(sslsf).build(); 130 | // 创建httppost 131 | HttpPost httppost = new HttpPost(""); 132 | // 创建参数队列 133 | List formparams = new ArrayList(); 134 | formparams.add(new BasicNameValuePair("username", "cy")); 135 | System.out.println(formparams.toString()); 136 | UrlEncodedFormEntity uefEntity; 137 | try { 138 | uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); 139 | httppost.setEntity(uefEntity); 140 | System.out.println("executing request " + httppost.getURI()); 141 | CloseableHttpResponse response = httpClient.execute(httppost); 142 | try { 143 | HeaderIterator headerIterator = response.headerIterator(); 144 | if (headerIterator != null) { 145 | System.out.println("--------------------------------------"); 146 | while (headerIterator.hasNext()) { 147 | Header header = headerIterator.nextHeader(); 148 | System.out.println("Response header: " + header.getName() + "---" + header.getValue()); 149 | } 150 | System.out.println("--------------------------------------"); 151 | } 152 | List cookies = cookieStore.getCookies(); 153 | for (int i = 0; i < cookies.size(); i++) { 154 | System.out.println("cookie ---" + cookies.get(i).toString()); 155 | } 156 | return cookiemap; 157 | } finally { 158 | response.close(); 159 | } 160 | } catch (ClientProtocolException e) { 161 | e.printStackTrace(); 162 | } catch (UnsupportedEncodingException e1) { 163 | e1.printStackTrace(); 164 | } catch (IOException e) { 165 | e.printStackTrace(); 166 | } finally { 167 | // 关闭连接,释放资源 168 | try { 169 | httpClient.close(); 170 | } catch (IOException e) { 171 | e.printStackTrace(); 172 | } 173 | } 174 | return cookiemap; 175 | } 176 | public static void main(String[] args) throws KeyManagementException, CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException { 177 | getCookie(); 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/util/InstallCert.java: -------------------------------------------------------------------------------- 1 | package com.cy.util; 2 | 3 | /* 4 | * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * - Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 13 | * - Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * - Neither the name of Sun Microsystems nor the names of its 18 | * contributors may be used to endorse or promote products derived 19 | * from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | import java.io.BufferedReader; 35 | import java.io.File; 36 | import java.io.FileInputStream; 37 | import java.io.FileOutputStream; 38 | import java.io.InputStream; 39 | import java.io.InputStreamReader; 40 | import java.io.OutputStream; 41 | import java.security.KeyStore; 42 | import java.security.MessageDigest; 43 | import java.security.cert.CertificateException; 44 | import java.security.cert.X509Certificate; 45 | 46 | import javax.net.ssl.SSLContext; 47 | import javax.net.ssl.SSLException; 48 | import javax.net.ssl.SSLSocket; 49 | import javax.net.ssl.SSLSocketFactory; 50 | import javax.net.ssl.TrustManager; 51 | import javax.net.ssl.TrustManagerFactory; 52 | import javax.net.ssl.X509TrustManager; 53 | 54 | public class InstallCert { 55 | 56 | public static void main(String[] args) throws Exception { 57 | String host; 58 | int port; 59 | char[] passphrase; 60 | if ((args.length == 1) || (args.length == 2)) { 61 | String[] c = args[0].split(":"); 62 | host = c[0]; 63 | port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); 64 | String p = (args.length == 1) ? "changeit" : args[1]; 65 | passphrase = p.toCharArray(); 66 | } else { 67 | System.out 68 | .println("Usage: java InstallCert [:port] [passphrase]"); 69 | return; 70 | } 71 | 72 | File file = new File("jssecacerts"); 73 | if (file.isFile() == false) { 74 | char SEP = File.separatorChar; 75 | File dir = new File(System.getProperty("java.home") + SEP + "lib" 76 | + SEP + "security"); 77 | file = new File(dir, "jssecacerts"); 78 | if (file.isFile() == false) { 79 | file = new File(dir, "cacerts"); 80 | } 81 | } 82 | System.out.println("Loading KeyStore " + file + "..."); 83 | InputStream in = new FileInputStream(file); 84 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 85 | ks.load(in, passphrase); 86 | in.close(); 87 | 88 | SSLContext context = SSLContext.getInstance("TLS"); 89 | TrustManagerFactory tmf = TrustManagerFactory 90 | .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 91 | tmf.init(ks); 92 | X509TrustManager defaultTrustManager = (X509TrustManager) tmf 93 | .getTrustManagers()[0]; 94 | SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); 95 | context.init(null, new TrustManager[] { tm }, null); 96 | SSLSocketFactory factory = context.getSocketFactory(); 97 | 98 | System.out 99 | .println("Opening connection to " + host + ":" + port + "..."); 100 | SSLSocket socket = (SSLSocket) factory.createSocket(host, port); 101 | socket.setSoTimeout(10000); 102 | try { 103 | System.out.println("Starting SSL handshake..."); 104 | socket.startHandshake(); 105 | socket.close(); 106 | System.out.println(); 107 | System.out.println("No errors, certificate is already trusted"); 108 | } catch (SSLException e) { 109 | System.out.println(); 110 | e.printStackTrace(System.out); 111 | } 112 | 113 | X509Certificate[] chain = tm.chain; 114 | if (chain == null) { 115 | System.out.println("Could not obtain server certificate chain"); 116 | return; 117 | } 118 | 119 | BufferedReader reader = new BufferedReader(new InputStreamReader( 120 | System.in)); 121 | 122 | System.out.println(); 123 | System.out.println("Server sent " + chain.length + " certificate(s):"); 124 | System.out.println(); 125 | MessageDigest sha1 = MessageDigest.getInstance("SHA1"); 126 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 127 | for (int i = 0; i < chain.length; i++) { 128 | X509Certificate cert = chain[i]; 129 | System.out.println(" " + (i + 1) + " Subject " 130 | + cert.getSubjectDN()); 131 | System.out.println(" Issuer " + cert.getIssuerDN()); 132 | sha1.update(cert.getEncoded()); 133 | System.out.println(" sha1 " + toHexString(sha1.digest())); 134 | md5.update(cert.getEncoded()); 135 | System.out.println(" md5 " + toHexString(md5.digest())); 136 | System.out.println(); 137 | } 138 | 139 | System.out 140 | .println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); 141 | String line = reader.readLine().trim(); 142 | int k; 143 | try { 144 | k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; 145 | } catch (NumberFormatException e) { 146 | System.out.println("KeyStore not changed"); 147 | return; 148 | } 149 | 150 | X509Certificate cert = chain[k]; 151 | String alias = host + "-" + (k + 1); 152 | ks.setCertificateEntry(alias, cert); 153 | 154 | OutputStream out = new FileOutputStream("jssecacerts"); 155 | ks.store(out, passphrase); 156 | out.close(); 157 | 158 | System.out.println(); 159 | System.out.println(cert); 160 | System.out.println(); 161 | System.out 162 | .println("Added certificate to keystore 'jssecacerts' using alias '" 163 | + alias + "'"); 164 | } 165 | 166 | private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); 167 | 168 | private static String toHexString(byte[] bytes) { 169 | StringBuilder sb = new StringBuilder(bytes.length * 3); 170 | for (int b : bytes) { 171 | b &= 0xff; 172 | sb.append(HEXDIGITS[b >> 4]); 173 | sb.append(HEXDIGITS[b & 15]); 174 | sb.append(' '); 175 | } 176 | return sb.toString(); 177 | } 178 | 179 | private static class SavingTrustManager implements X509TrustManager { 180 | 181 | private final X509TrustManager tm; 182 | private X509Certificate[] chain; 183 | 184 | SavingTrustManager(X509TrustManager tm) { 185 | this.tm = tm; 186 | } 187 | 188 | public X509Certificate[] getAcceptedIssuers() { 189 | throw new UnsupportedOperationException(); 190 | } 191 | 192 | public void checkClientTrusted(X509Certificate[] chain, String authType) 193 | throws CertificateException { 194 | throw new UnsupportedOperationException(); 195 | } 196 | 197 | public void checkServerTrusted(X509Certificate[] chain, String authType) 198 | throws CertificateException { 199 | this.chain = chain; 200 | tm.checkServerTrusted(chain, authType); 201 | } 202 | } 203 | 204 | } -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/util/JsoupDemo.java: -------------------------------------------------------------------------------- 1 | package com.cy.util; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import org.jsoup.Connection; 5 | import org.jsoup.Jsoup; 6 | import org.jsoup.nodes.Document; 7 | 8 | import java.io.IOException; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by cy 14 | * 2017/12/20 18:51 15 | */ 16 | public class JsoupDemo { 17 | /** 18 | * Jsoup常用功能 19 | */ 20 | public static void demo() throws IOException { 21 | /** 22 | * 关闭TSL SSL认证 23 | */ 24 | Jsoup.connect("").validateTLSCertificates(false).execute(); 25 | /** 26 | * 关闭重定向 27 | */ 28 | Jsoup.connect("").followRedirects(false).execute(); 29 | /** 30 | * get请求 execute默认就是get请求 返回Document 31 | */ 32 | Document parse = Jsoup.connect("").execute().parse(); 33 | Document parse1 = Jsoup.connect("").get(); 34 | /** 35 | * get请求 返回json 36 | */ 37 | String data1 = Jsoup.connect("").ignoreContentType(true).execute().body(); 38 | /** 39 | * post请求 execute设置为post 40 | */ 41 | Map data = new HashMap(); 42 | data.put("username", ""); 43 | Document post = Jsoup.connect("").data(data).post(); 44 | Document post1 = Jsoup.connect("").data("","").method(Connection.Method.POST).execute().parse(); 45 | 46 | /** 47 | * post请求 json数据 48 | */ 49 | JSONObject jsonObject = new JSONObject(); 50 | jsonObject.put("", ""); 51 | Document post2 = Jsoup.connect("").requestBody(jsonObject.toString()).post(); 52 | /** 53 | * 提交cookie 可以用map 54 | */ 55 | Jsoup.connect("").cookie("","").execute(); 56 | /** 57 | * 提交协议头 可以用map 58 | */ 59 | Jsoup.connect("").header("","").execute(); 60 | /** 61 | * 返回协议头 协议头居然没有cookie 62 | */ 63 | Jsoup.connect("").execute().headers(); 64 | /** 65 | * 返回cookie 因为map类型 同名的cookie只返回一个,这个比较坑 66 | */ 67 | Jsoup.connect("").execute().cookies(); 68 | 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/util/ResultUtil.java: -------------------------------------------------------------------------------- 1 | package com.cy.util; 2 | 3 | import com.cy.entity.Result; 4 | 5 | /** 6 | * Created by cy 7 | * 2017/12/11 18:50 8 | */ 9 | public class ResultUtil { 10 | 11 | public static Result success(Object object) { 12 | Result result = new Result(); 13 | result.setCode(0); 14 | result.setMsg("成功"); 15 | result.setData(object); 16 | return result; 17 | } 18 | 19 | public static Result success() { 20 | return success(null); 21 | } 22 | 23 | public static Result error(Integer code, String msg) { 24 | Result result = new Result(); 25 | result.setCode(code); 26 | result.setMsg(msg); 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/java/com/cy/util/SendMail.java: -------------------------------------------------------------------------------- 1 | package com.cy.util; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.mail.SimpleMailMessage; 7 | import org.springframework.mail.javamail.JavaMailSender; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * Created by cy 12 | * 2017/12/13 19:57 13 | */ 14 | @Component 15 | @Log4j2 16 | public class SendMail { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/application.propertiess: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-mybatis-thymeleaf/src/main/resources/application.propertiess -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # 容器配置 2 | server: 3 | port: 8443 # https 端口号,正式 443;测试 8443 4 | sslPort: 8080 # http 端口号,正式 80;测试 8080 5 | ssl: 6 | key-store: classpath:ocly.jks 7 | key-password: 704739362 8 | undertow: 9 | worker-threads: 20 10 | buffer-size: 512 11 | io-threads: 2 12 | 13 | # 默认的profile为dev,其他环境通过指定启动参数使用不同的profile,比如: 14 | # 测试环境:java -jar my-spring-boot.jar --spring.profiles.active=test 15 | # 生产环境:java -jar my-spring-boot.jar --spring.profiles.active=prod 16 | 17 | spring: 18 | datasource: 19 | one: 20 | url: jdbc:mysql://127.0.0.1/springbootdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true 21 | username: root 22 | password: 0.0001 23 | driver-class-name: com.mysql.jdbc.Driver 24 | max-wait: 20000 # 修改各个数据库的超时时间 25 | max-active: 20 26 | tow: 27 | url: jdbc:mysql://127.0.0.1/springbootdb2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true 28 | username: root 29 | password: 0.0001 30 | driver-class-name: com.mysql.jdbc.Driver 31 | max-wait: 50000 32 | druid: 33 | max-active: 10 # 初始化大小,最小,最大链接数 34 | min-idle: 3 35 | initial-size: 3 36 | max-wait: 60000 # 连接超时时间 37 | stat-view-servlet: #监控平台设置 38 | login-username: admin 39 | login-password: admin 40 | filter: 41 | stat: # 显示慢sql 42 | log-slow-sql: true 43 | slow-sql-millis: 2000 44 | 45 | # 取消thymeleaf缓存 46 | thymeleaf: 47 | cache: false 48 | mode: LEGACYHTML5 49 | # Redis 配置 50 | redis: 51 | host: localhost 52 | password: 53 | 54 | mail: 55 | host: smtp.163.com 56 | username: xxoo@xxoo.com 57 | password: xxoo 58 | default-encoding: UTF-8 59 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.RED}${AnsiStyle.ITALIC}I'm Red and italic ${AnsiStyle.NORMAL}${AnsiColor.DEFAULT} 2 | ${AnsiColor.BLUE}${AnsiBackground.YELLOW}I'm Blue with yellow background${AnsiBackground.DEFAULT}${AnsiColor.DEFAULT} 3 | ${AnsiColor.GREEN}Powered by ${spring-boot.formatted-version}${AnsiColor.DEFAULT} 4 | 5 | ██████╗ ██████╗██╗ ██╗ ██╗ 6 | ██╔═══██╗██╔════╝██║ ╚██╗ ██╔╝ 7 | ██║ ██║██║ ██║ ╚████╔╝ 8 | ██║ ██║██║ ██║ ╚██╔╝ 9 | ╚██████╔╝╚██████╗███████╗██║ 10 | ╚═════╝ ╚═════╝╚══════╝╚═╝ 11 | 12 | Spring Boot>>>>> ${spring-boot.formatted-version} 13 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/log4j2.yml: -------------------------------------------------------------------------------- 1 | Configuration: 2 | appenders: # 定义输出源 3 | Console: # 输出到控制台 4 | name: CONSOLE # Appender命名 5 | target: SYSTEM_OUT 6 | PatternLayout: # 选用自定义配置方式 7 | pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS}: %highlight{%4p} %t (%style{%F:%L}{Cyan}) - %m%n{FATAL=white, ERROR=red, WARN=blue, INFO=black, DEBUG=green, TRACE=blue}" 8 | # "%highlight{%d{HH:mm:ss.SSS} %-5level %logger{36}.%M() @%L - %msg%n}{FATAL=Bright Red, ERROR=Bright Magenta, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White} 9 | RollingFile: # 输出到文件 10 | - 11 | name: ROLLING_FILE 12 | ignoreExceptions: false 13 | fileName: ..\\logs\\springboot.log #注意linux,windows路径设置 14 | filePattern: "..\\logs\\$${date:yyyy-MM}\\springboot-%d{yyyy-MM-dd}-%i.log.gz" 15 | PatternLayout: 16 | pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n" 17 | Policies: 18 | SizeBasedTriggeringPolicy: 19 | size: "256 MB" 20 | DefaultRolloverStrategy: # 默认值是7 达到7个256 都会删除 21 | max: 1000 22 | - 23 | name: ROLLING_FILE_ERROR 24 | ignoreExceptions: false 25 | Filters: # 将error级别的错误单独记录起来 26 | ThresholdFilter: 27 | level: error 28 | onMatch: ACCEPT 29 | onMismatch: DENY 30 | fileName: ..\\logs\\error.log #注意linux,windows路径设置 31 | filePattern: "..\\logs\\$${date:yyyy-MM}\\error-%d{yyyy-MM-dd}-%i.log.gz" 32 | PatternLayout: 33 | pattern: "%d{yyyy-MM-dd HH:mm:ss,SSS}:%4p %t (%F:%L) - %m%n" 34 | Policies: 35 | SizeBasedTriggeringPolicy: 36 | size: "256 MB" 37 | DefaultRolloverStrategy: # 默认值是7 达到7个256 都会删除 38 | max: 1000 39 | Loggers: 40 | Logger: # 为com.cy包配置特殊的error级别,记录到error.log 41 | - name: com.cy 42 | additivity: false 43 | level: info # 可以在这更改级别 44 | AppenderRef: 45 | - ref: CONSOLE 46 | - ref: ROLLING_FILE 47 | - ref: ROLLING_FILE_ERROR 48 | Root: 49 | level: error 50 | AppenderRef: 51 | - ref: CONSOLE 52 | - ref: ROLLING_FILE_ERROR -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/mybatis/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | id, age, name, password 12 | 13 | 18 | 23 | 24 | delete from user 25 | where id = #{id,jdbcType=BIGINT} 26 | 27 | 28 | insert into user 29 | 30 | 31 | id, 32 | 33 | 34 | age, 35 | 36 | 37 | name, 38 | 39 | 40 | password, 41 | 42 | 43 | 44 | 45 | #{id,jdbcType=BIGINT}, 46 | 47 | 48 | #{age,jdbcType=VARCHAR}, 49 | 50 | 51 | #{name,jdbcType=VARCHAR}, 52 | 53 | 54 | #{password,jdbcType=VARCHAR}, 55 | 56 | 57 | 58 | 59 | update user 60 | 61 | 62 | age = #{age,jdbcType=VARCHAR}, 63 | 64 | 65 | name = #{name,jdbcType=VARCHAR}, 66 | 67 | 68 | password = #{password,jdbcType=VARCHAR}, 69 | 70 | 71 | where id = #{id,jdbcType=BIGINT} 72 | 73 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/ocly.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-mybatis-thymeleaf/src/main/resources/ocly.jks -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/css/dataTables.bootstrap.min.css: -------------------------------------------------------------------------------- 1 | table.dataTable{clear:both;margin-top:6px !important;margin-bottom:6px !important;max-width:none !important;border-collapse:separate !important}table.dataTable td,table.dataTable th{-webkit-box-sizing:content-box;box-sizing:content-box}table.dataTable td.dataTables_empty,table.dataTable th.dataTables_empty{text-align:center}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}div.dataTables_wrapper div.dataTables_length label{font-weight:normal;text-align:left;white-space:nowrap}div.dataTables_wrapper div.dataTables_length select{width:75px;display:inline-block}div.dataTables_wrapper div.dataTables_filter{text-align:right}div.dataTables_wrapper div.dataTables_filter label{font-weight:normal;white-space:nowrap;text-align:left}div.dataTables_wrapper div.dataTables_filter input{margin-left:0.5em;display:inline-block;width:auto}div.dataTables_wrapper div.dataTables_info{padding-top:8px;white-space:nowrap}div.dataTables_wrapper div.dataTables_paginate{margin:0;white-space:nowrap;text-align:right}div.dataTables_wrapper div.dataTables_paginate ul.pagination{margin:2px 0;white-space:nowrap}div.dataTables_wrapper div.dataTables_processing{position:absolute;top:50%;left:50%;width:200px;margin-left:-100px;margin-top:-26px;text-align:center;padding:1em 0}table.dataTable thead>tr>th.sorting_asc,table.dataTable thead>tr>th.sorting_desc,table.dataTable thead>tr>th.sorting,table.dataTable thead>tr>td.sorting_asc,table.dataTable thead>tr>td.sorting_desc,table.dataTable thead>tr>td.sorting{padding-right:30px}table.dataTable thead>tr>th:active,table.dataTable thead>tr>td:active{outline:none}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after,table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after,table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{position:absolute;bottom:8px;right:8px;display:block;font-family:'Glyphicons Halflings';opacity:0.5}table.dataTable thead .sorting:after{opacity:0.2;content:"\e150"}table.dataTable thead .sorting_asc:after{content:"\e155"}table.dataTable thead .sorting_desc:after{content:"\e156"}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}div.dataTables_scrollHead table.dataTable{margin-bottom:0 !important}div.dataTables_scrollBody table{border-top:none;margin-top:0 !important;margin-bottom:0 !important}div.dataTables_scrollBody table thead .sorting:after,div.dataTables_scrollBody table thead .sorting_asc:after,div.dataTables_scrollBody table thead .sorting_desc:after{display:none}div.dataTables_scrollBody table tbody tr:first-child th,div.dataTables_scrollBody table tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{margin-top:0 !important;border-top:none}@media screen and (max-width: 767px){div.dataTables_wrapper div.dataTables_length,div.dataTables_wrapper div.dataTables_filter,div.dataTables_wrapper div.dataTables_info,div.dataTables_wrapper div.dataTables_paginate{text-align:center}}table.dataTable.table-condensed>thead>tr>th{padding-right:20px}table.dataTable.table-condensed .sorting:after,table.dataTable.table-condensed .sorting_asc:after,table.dataTable.table-condensed .sorting_desc:after{top:6px;right:6px}table.table-bordered.dataTable th,table.table-bordered.dataTable td{border-left-width:0}table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable th:last-child,table.table-bordered.dataTable td:last-child,table.table-bordered.dataTable td:last-child{border-right-width:0}table.table-bordered.dataTable tbody th,table.table-bordered.dataTable tbody td{border-bottom-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}div.table-responsive>div.dataTables_wrapper>div.row{margin:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:first-child{padding-left:0}div.table-responsive>div.dataTables_wrapper>div.row>div[class^="col-"]:last-child{padding-right:0} 2 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/img/user.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-mybatis-thymeleaf/src/main/resources/static/img/user.jpg -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/img/user3-128x128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-mybatis-thymeleaf/src/main/resources/static/img/user3-128x128.jpg -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 |

This is a static page

9 | 10 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/js/dataTables.bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | DataTables Bootstrap 3 integration 3 | ©2011-2015 SpryMedia Ltd - datatables.net/license 4 | */ 5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-6'l><'col-sm-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-5'i><'col-sm-7'p>>",renderer:"bootstrap"});b.extend(f.ext.classes, 6 | {sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm",sProcessing:"dataTables_processing panel panel-default"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();!b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")}; 7 | l=0;for(h=f.length;l",{"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#", 8 | "aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('
    ').children("ul"),s);i!==m&&b(h).find("[data-dt-idx="+i+"]").focus()};return f}); 9 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/js/icheck.min.js: -------------------------------------------------------------------------------- 1 | /*! iCheck v1.0.1 by Damir Sultanov, http://git.io/arlzeA, MIT Licensed */ 2 | (function(h){function F(a,b,d){var c=a[0],e=/er/.test(d)?m:/bl/.test(d)?s:l,f=d==H?{checked:c[l],disabled:c[s],indeterminate:"true"==a.attr(m)||"false"==a.attr(w)}:c[e];if(/^(ch|di|in)/.test(d)&&!f)D(a,e);else if(/^(un|en|de)/.test(d)&&f)t(a,e);else if(d==H)for(e in f)f[e]?D(a,e,!0):t(a,e,!0);else if(!b||"toggle"==d){if(!b)a[p]("ifClicked");f?c[n]!==u&&t(a,e):D(a,e)}}function D(a,b,d){var c=a[0],e=a.parent(),f=b==l,A=b==m,B=b==s,K=A?w:f?E:"enabled",p=k(a,K+x(c[n])),N=k(a,b+x(c[n]));if(!0!==c[b]){if(!d&& 3 | b==l&&c[n]==u&&c.name){var C=a.closest("form"),r='input[name="'+c.name+'"]',r=C.length?C.find(r):h(r);r.each(function(){this!==c&&h(this).data(q)&&t(h(this),b)})}A?(c[b]=!0,c[l]&&t(a,l,"force")):(d||(c[b]=!0),f&&c[m]&&t(a,m,!1));L(a,f,b,d)}c[s]&&k(a,y,!0)&&e.find("."+I).css(y,"default");e[v](N||k(a,b)||"");B?e.attr("aria-disabled","true"):e.attr("aria-checked",A?"mixed":"true");e[z](p||k(a,K)||"")}function t(a,b,d){var c=a[0],e=a.parent(),f=b==l,h=b==m,q=b==s,p=h?w:f?E:"enabled",t=k(a,p+x(c[n])), 4 | u=k(a,b+x(c[n]));if(!1!==c[b]){if(h||!d||"force"==d)c[b]=!1;L(a,f,p,d)}!c[s]&&k(a,y,!0)&&e.find("."+I).css(y,"pointer");e[z](u||k(a,b)||"");q?e.attr("aria-disabled","false"):e.attr("aria-checked","false");e[v](t||k(a,p)||"")}function M(a,b){if(a.data(q)){a.parent().html(a.attr("style",a.data(q).s||""));if(b)a[p](b);a.off(".i").unwrap();h(G+'[for="'+a[0].id+'"]').add(a.closest(G)).off(".i")}}function k(a,b,d){if(a.data(q))return a.data(q).o[b+(d?"":"Class")]}function x(a){return a.charAt(0).toUpperCase()+ 5 | a.slice(1)}function L(a,b,d,c){if(!c){if(b)a[p]("ifToggled");a[p]("ifChanged")[p]("if"+x(d))}}var q="iCheck",I=q+"-helper",u="radio",l="checked",E="un"+l,s="disabled",w="determinate",m="in"+w,H="update",n="type",v="addClass",z="removeClass",p="trigger",G="label",y="cursor",J=/ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);h.fn[q]=function(a,b){var d='input[type="checkbox"], input[type="'+u+'"]',c=h(),e=function(a){a.each(function(){var a=h(this);c=a.is(d)? 6 | c.add(a):c.add(a.find(d))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(a))return a=a.toLowerCase(),e(this),c.each(function(){var c=h(this);"destroy"==a?M(c,"ifDestroyed"):F(c,!0,a);h.isFunction(b)&&b()});if("object"!=typeof a&&a)return this;var f=h.extend({checkedClass:l,disabledClass:s,indeterminateClass:m,labelHover:!0,aria:!1},a),k=f.handle,B=f.hoverClass||"hover",x=f.focusClass||"focus",w=f.activeClass||"active",y=!!f.labelHover,C=f.labelHoverClass|| 7 | "hover",r=(""+f.increaseArea).replace("%","")|0;if("checkbox"==k||k==u)d='input[type="'+k+'"]';-50>r&&(r=-50);e(this);return c.each(function(){var a=h(this);M(a);var c=this,b=c.id,e=-r+"%",d=100+2*r+"%",d={position:"absolute",top:e,left:e,display:"block",width:d,height:d,margin:0,padding:0,background:"#fff",border:0,opacity:0},e=J?{position:"absolute",visibility:"hidden"}:r?d:{position:"absolute",opacity:0},k="checkbox"==c[n]?f.checkboxClass||"icheckbox":f.radioClass||"i"+u,m=h(G+'[for="'+b+'"]').add(a.closest(G)), 8 | A=!!f.aria,E=q+"-"+Math.random().toString(36).replace("0.",""),g='
    ")[p]("ifCreated").parent().append(f.insert);d=h('').css(d).appendTo(g);a.data(q,{o:f,s:a.attr("style")}).css(e);f.inheritClass&&g[v](c.className||"");f.inheritID&&b&&g.attr("id",q+"-"+b);"static"==g.css("position")&&g.css("position","relative");F(a,!0,H); 9 | if(m.length)m.on("click.i mouseover.i mouseout.i touchbegin.i touchend.i",function(b){var d=b[n],e=h(this);if(!c[s]){if("click"==d){if(h(b.target).is("a"))return;F(a,!1,!0)}else y&&(/ut|nd/.test(d)?(g[z](B),e[z](C)):(g[v](B),e[v](C)));if(J)b.stopPropagation();else return!1}});a.on("click.i focus.i blur.i keyup.i keydown.i keypress.i",function(b){var d=b[n];b=b.keyCode;if("click"==d)return!1;if("keydown"==d&&32==b)return c[n]==u&&c[l]||(c[l]?t(a,l):D(a,l)),!1;if("keyup"==d&&c[n]==u)!c[l]&&D(a,l);else if(/us|ur/.test(d))g["blur"== 10 | d?z:v](x)});d.on("click mousedown mouseup mouseover mouseout touchbegin.i touchend.i",function(b){var d=b[n],e=/wn|up/.test(d)?w:B;if(!c[s]){if("click"==d)F(a,!1,!0);else{if(/wn|er|in/.test(d))g[v](e);else g[z](e+" "+w);if(m.length&&y&&e==B)m[/ut|nd/.test(d)?z:v](C)}if(J)b.stopPropagation();else return!1}})})}})(window.jQuery||window.Zepto); 11 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/static/js/jquery.slimscroll.min.js: -------------------------------------------------------------------------------- 1 | /*! Copyright (c) 2011 Piotr Rochala (http://rocha.la) 2 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 | * 5 | * Version: 1.3.8 6 | * 7 | */ 8 | (function(e){e.fn.extend({slimScroll:function(f){var a=e.extend({width:"auto",height:"250px",size:"7px",color:"#000",position:"right",distance:"1px",start:"top",opacity:.4,alwaysVisible:!1,disableFadeOut:!1,railVisible:!1,railColor:"#333",railOpacity:.2,railDraggable:!0,railClass:"slimScrollRail",barClass:"slimScrollBar",wrapperClass:"slimScrollDiv",allowPageScroll:!1,wheelStep:20,touchScrollStep:200,borderRadius:"7px",railBorderRadius:"7px"},f);this.each(function(){function v(d){if(r){d=d||window.event; 9 | var c=0;d.wheelDelta&&(c=-d.wheelDelta/120);d.detail&&(c=d.detail/3);e(d.target||d.srcTarget||d.srcElement).closest("."+a.wrapperClass).is(b.parent())&&n(c,!0);d.preventDefault&&!k&&d.preventDefault();k||(d.returnValue=!1)}}function n(d,g,e){k=!1;var f=b.outerHeight()-c.outerHeight();g&&(g=parseInt(c.css("top"))+d*parseInt(a.wheelStep)/100*c.outerHeight(),g=Math.min(Math.max(g,0),f),g=0=b.outerHeight()?k=!0:(c.stop(!0, 11 | !0).fadeIn("fast"),a.railVisible&&m.stop(!0,!0).fadeIn("fast"))}function p(){a.alwaysVisible||(B=setTimeout(function(){a.disableFadeOut&&r||y||z||(c.fadeOut("slow"),m.fadeOut("slow"))},1E3))}var r,y,z,B,A,u,l,C,k=!1,b=e(this);if(b.parent().hasClass(a.wrapperClass)){var q=b.scrollTop(),c=b.siblings("."+a.barClass),m=b.siblings("."+a.railClass);x();if(e.isPlainObject(f)){if("height"in f&&"auto"==f.height){b.parent().css("height","auto");b.css("height","auto");var h=b.parent().parent().height();b.parent().css("height", 12 | h);b.css("height",h)}else"height"in f&&(h=f.height,b.parent().css("height",h),b.css("height",h));if("scrollTo"in f)q=parseInt(a.scrollTo);else if("scrollBy"in f)q+=parseInt(a.scrollBy);else if("destroy"in f){c.remove();m.remove();b.unwrap();return}n(q,!1,!0)}}else if(!(e.isPlainObject(f)&&"destroy"in f)){a.height="auto"==a.height?b.parent().height():a.height;q=e("
    ").addClass(a.wrapperClass).css({position:"relative",overflow:"hidden",width:a.width,height:a.height});b.css({overflow:"hidden", 13 | width:a.width,height:a.height});var m=e("
    ").addClass(a.railClass).css({width:a.size,height:"100%",position:"absolute",top:0,display:a.alwaysVisible&&a.railVisible?"block":"none","border-radius":a.railBorderRadius,background:a.railColor,opacity:a.railOpacity,zIndex:90}),c=e("
    ").addClass(a.barClass).css({background:a.color,width:a.size,position:"absolute",top:0,opacity:a.opacity,display:a.alwaysVisible?"block":"none","border-radius":a.borderRadius,BorderRadius:a.borderRadius,MozBorderRadius:a.borderRadius, 14 | WebkitBorderRadius:a.borderRadius,zIndex:99}),h="right"==a.position?{right:a.distance}:{left:a.distance};m.css(h);c.css(h);b.wrap(q);b.parent().append(c);b.parent().append(m);a.railDraggable&&c.bind("mousedown",function(a){var b=e(document);z=!0;t=parseFloat(c.css("top"));pageY=a.pageY;b.bind("mousemove.slimscroll",function(a){currTop=t+a.pageY-pageY;c.css("top",currTop);n(0,c.position().top,!1)});b.bind("mouseup.slimscroll",function(a){z=!1;p();b.unbind(".slimscroll")});return!1}).bind("selectstart.slimscroll", 15 | function(a){a.stopPropagation();a.preventDefault();return!1});m.hover(function(){w()},function(){p()});c.hover(function(){y=!0},function(){y=!1});b.hover(function(){r=!0;w();p()},function(){r=!1;p()});b.bind("touchstart",function(a,b){a.originalEvent.touches.length&&(A=a.originalEvent.touches[0].pageY)});b.bind("touchmove",function(b){k||b.originalEvent.preventDefault();b.originalEvent.touches.length&&(n((A-b.originalEvent.touches[0].pageY)/a.touchScrollStep,!0),A=b.originalEvent.touches[0].pageY)}); 16 | x();"bottom"===a.start?(c.css({top:b.outerHeight()-c.outerHeight()}),n(0,!0)):"top"!==a.start&&(n(e(a.start).position().top,null,!0),a.alwaysVisible||c.hide());window.addEventListener?(this.addEventListener("DOMMouseScroll",v,!1),this.addEventListener("mousewheel",v,!1)):document.attachEvent("onmousewheel",v)}});return this}});e.fn.extend({slimscroll:e.fn.slimScroll})})(jQuery); -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | AdminLTE 2 | Log in 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 |
    69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/templates/user/userAdd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | user 6 | 7 | 8 | 9 |
    10 |

    添加用户

    11 |

    12 |
    13 |
    14 |
    15 | 16 |
    17 | 18 |
    19 |
    20 |
    21 | 22 |
    23 | 24 |
    25 |
    26 |
    27 | 28 |
    29 | 30 |
    31 |
    32 |
    33 |
    34 | 35 |       36 | 37 |
    38 | 39 |
    40 |
    41 |
    42 | 43 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/templates/user/userEdit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | user 6 | 7 | 8 | 9 |
    10 |

    修改用户

    11 |

    12 |
    13 |
    14 | 15 |
    16 | 17 |
    18 | 19 |
    20 |
    21 |
    22 | 23 |
    24 | 25 |
    26 |
    27 |
    28 | 29 |
    30 | 31 |
    32 |
    33 |
    34 |
    35 | 36 |       37 | Back 38 |
    39 | 40 |
    41 |
    42 |
    43 | 44 | -------------------------------------------------------------------------------- /springboot-mybatis-thymeleaf/src/main/resources/templates/user/userList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | userList 6 | 7 | 8 | 9 |
    10 |

    用户列表

    11 |

    12 |
    13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
    #User NamePasswordAgeEditDelete
    1neoOtto6editdelete
    35 |
    36 |
    37 |
    38 | add 39 |
    40 |
    41 | 42 | 43 | -------------------------------------------------------------------------------- /springboot-rabbitmq/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /springboot-rabbitmq/README.md: -------------------------------------------------------------------------------- 1 | # springboot整合RabbitMq 2 | 1. 下载并安装RabbitMq([下载地址](https://www.rabbitmq.com/download.html)) 3 | 2. 下载并安装Erland([下载地址](https://www.rabbitmq.com/download.html)) 4 | 3. 命令行进入RabbitMq目录的sbin目录 5 | 4. 执行`rabbitmq-plugins enable rabbitmq_management`开启web管理插件 6 | 5. 打开地址 http://localhost:15672/ guest guest 7 | 6. 添加新用户 并 Set permission 8 | 7. maven引入依赖包 9 | ``` 10 | 11 | org.springframework.boot 12 | spring-boot-starter-amqp 13 | 14 | ``` 15 | 8. 请求响应模式, **注:(** 一对多是平均消费 16 | 9. 发送对象时, **注:(** 对象实现序列化 17 | 10. 主题模式 18 | 11. 发布订阅模式(广播模式) 19 | 20 | # ico 21 | 将ico命名为favicon.ico 放到resources下即可 22 | 1. `spring.mvc.favicon.enabled = false` 23 | 2. `` 24 | 25 | # javaMail的使用 26 | 1. 先来展示下收到邮件的效果图: 27 | 28 | ![](/springboot-rabbitmq/src/main/resources/static/img/QQ图片20171214160014.png "邮件效果图") 29 | 2. 准备工作 30 | * 邮箱服务器地址:这里使用新浪邮箱,登录你的新浪邮箱,开启SMTP 31 | * 目标邮箱地址:可以是自己的qq邮箱,能接到邮件就行 32 | 3. maven引入依赖包,thymeleaf有提供htmlmail模板 33 | ``` 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-mail 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-thymeleaf 44 | 45 | ``` 46 | 4. 配置相关信息 47 | ``` 48 | spring: 49 | thymeleaf: 50 | cache: false 51 | mode: LEGACYHTML5 52 | mail: 53 | # 邮箱设置里可以找到 54 | host: smtp.sina.com 55 | # 去页面开启SMTP 56 | username: 57 | password: 58 | default-encoding: UTF-8 59 | ``` 60 | 5. 编写相关[代码](https://github.com/yy1193889747/springboot-demo/blob/master/springboot-rabbitmq/src/main/java/com/ocly/util/SendMail.java) 61 | 62 | # mvn命令 63 | `mvn install:install-file -Dfile=D:/jar/xxx.jar -DgroupId=org.csource -DartifactId=fastdfs-client-java -Dversion=1.25 -Dpackaging=jar` 64 | 65 | # Docker study 66 | /var/lib/docker/ docker默认路径 67 | 1. docker网络 68 | * `apt-get install bridge-utils` 安装桥接查看工具 69 | * `brctl show` 查看桥接信息 70 | * `ifconfig docker0 192.168.200.1 netmask 255.255.255.0` 修改默认ip段 71 | * `service docker restart` 修改完重启配置 72 | * `brctl addbr br0` 添加虚拟网桥 73 | * `同上` 设置br0ip段 74 | * `vi /etc/default/docker ` DOCKER_OPTS= "b=br0" 75 | * DOCKER_OPTS= " -icc=false -iptables=true" 允许link互联 76 | * `iptables -I DOCKER -s 172.17.0.5 -d 172.17.0.4 -p tcp --dport 80 -j DROP` 添加规则拒绝访问端口 77 | * `iptables -nL --line-numbers`查看行号 78 | * `iptables -D DOCKER 1` 删除iptables规则 79 | 2. 数据卷 80 | * `docker inspect 9d` 查看容器信息 81 | * `VOLUME ["/volume1","/volume2"]` Dockerfile指定数据卷 82 | * `docker run --volumes-from 55 -it alpine` 数据卷容器 83 | * `docker rm 55 -v` 删除容器及数据卷,只要被别的容器引用就删不了,即便容器停止 84 | * `docker run --volumes-from 55 -it -v /backup:/backup alpine tar cvf /backup/data.tar /volume1` 备份数据 85 | * `docker stata 9d` 监控容器状态 86 | 3. docker命令 87 | * `docker rm 55 -f` 删除正在运行的容器 88 | * `docker rm -f $(docker ps -a -q)` 删除正在运行的所有容器 89 | * `-v /etc/timezone:/etc/timezone` 直接挂在时区即可 90 | 91 | # linux 命令 92 | * `cat /proc/cpuinfo | grep "physical id" | uniq | wc -l` 查看CPU个数 93 | * `cat /proc/cpuinfo | grep "cpu cores" | uniq` 查看CPU核数 94 | * `cat /proc/cpuinfo | grep 'model name' |uniq` 查看CPU型号 95 | * `cat /proc/meminfo | grep MemTotal` 查看内存大小 96 | * `fdisk -l | grep Disk` 查看硬盘大小 97 | 98 | 99 | -------------------------------------------------------------------------------- /springboot-rabbitmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.ocly 7 | springboot-rabbitmq 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | springboot-rabbitmq 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 1.5.8.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-logging 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-amqp 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-log4j2 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-mail 59 | 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-thymeleaf 65 | 66 | 67 | 68 | 69 | org.projectlombok 70 | lombok 71 | 1.16.14 72 | 73 | 74 | 75 | 76 | net.sourceforge.nekohtml 77 | nekohtml 78 | 1.9.22 79 | 80 | 81 | 82 | org.jsoup 83 | jsoup 84 | 1.11.2 85 | 86 | 87 | 88 | com.alibaba 89 | fastjson 90 | 1.2.41 91 | 92 | 93 | 94 | commons-lang 95 | commons-lang 96 | 2.4 97 | 98 | 99 | 100 | 101 | 102 | 103 | org.springframework.boot 104 | spring-boot-maven-plugin 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/Application.java: -------------------------------------------------------------------------------- 1 | package com.ocly; 2 | 3 | import com.ocly.modle.User; 4 | import com.ocly.rabbit.ObjSender; 5 | import com.ocly.rabbit.Sender; 6 | import org.apache.coyote.http11.AbstractHttp11Protocol; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; 11 | import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.ui.Model; 14 | import org.springframework.ui.ModelMap; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.PostMapping; 17 | import org.springframework.web.bind.annotation.RequestParam; 18 | import org.springframework.web.bind.annotation.RestController; 19 | import org.springframework.web.multipart.MultipartFile; 20 | import org.springframework.web.servlet.ModelAndView; 21 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 22 | 23 | import java.io.IOException; 24 | import java.nio.file.Files; 25 | import java.nio.file.Path; 26 | import java.nio.file.Paths; 27 | 28 | @RestController 29 | @SpringBootApplication 30 | public class Application { 31 | @Autowired 32 | private ObjSender sender; 33 | @Autowired 34 | private Sender send; 35 | 36 | public static void main(String[] args) { 37 | 38 | SpringApplication.run(Application.class, args); 39 | } 40 | 41 | @Bean 42 | public TomcatEmbeddedServletContainerFactory tomcatEmbedded() { 43 | TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); 44 | tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { 45 | if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { 46 | //-1 means unlimited 47 | ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); 48 | } 49 | }); 50 | return tomcat; 51 | } 52 | 53 | 54 | @GetMapping(value = "/rabbit") 55 | public void hello() { 56 | User user = new User(); 57 | user.setAge(18); 58 | user.setName("ocly"); 59 | sender.send(user); 60 | } 61 | 62 | @GetMapping(value = "/topic/one") 63 | public void hellotopic() { 64 | send.topicSendOne(); 65 | } 66 | 67 | @GetMapping(value = "/topic/two") 68 | public void topictwo() { 69 | send.topicSendTwo(); 70 | } 71 | 72 | @GetMapping("/email") 73 | public ModelAndView mailTemplate(ModelMap model) { 74 | model.addAttribute("name", "ocly"); 75 | 76 | return new ModelAndView("emailTemplate", model); 77 | } 78 | 79 | @PostMapping(value = "/test") 80 | public String helloall(String name, String age) { 81 | return "Hello " + age + " de " + name; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/RabbitConfig.java: -------------------------------------------------------------------------------- 1 | package com.ocly; 2 | 3 | import org.springframework.amqp.core.*; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 10:55 10 | */ 11 | //@Configuration 12 | public class RabbitConfig { 13 | 14 | @Bean 15 | public Queue helloQueue() { 16 | return new Queue("hello",false); 17 | } 18 | 19 | @Bean 20 | public Queue ObjectQueue() { 21 | return new Queue("user",false); 22 | } 23 | /** 24 | * 主题模式 更灵活 25 | */ 26 | @Bean 27 | public Queue topicone() { 28 | return new Queue("topic.one",false); 29 | } 30 | @Bean 31 | public Queue topictwo() { 32 | return new Queue("topic.two",false); 33 | } 34 | @Bean 35 | TopicExchange exchange() { 36 | return new TopicExchange("topicexchange"); 37 | } 38 | @Bean 39 | Binding bindingtopicone(Queue topicone, TopicExchange exchange){ 40 | return BindingBuilder.bind(topicone).to(exchange).with("topic.one"); 41 | } 42 | 43 | /** 44 | * topic exchange 的 routing key 必须是由 . 分割* 45 | * * 可以表示任何单独的单词 46 | * # 可以表示0个或任意多个单词. 47 | */ 48 | @Bean 49 | Binding bindingtopictwo(Queue topictwo, TopicExchange exchange){ 50 | return BindingBuilder.bind(topictwo).to(exchange).with("topic.#"); 51 | } 52 | 53 | 54 | /** 55 | * 发布订阅模式 56 | */ 57 | @Bean 58 | public Queue AMessage() { 59 | return new Queue("fanout.A"); 60 | } 61 | 62 | @Bean 63 | public Queue BMessage() { 64 | return new Queue("fanout.B"); 65 | } 66 | 67 | @Bean 68 | public Queue CMessage() { 69 | return new Queue("fanout.C"); 70 | } 71 | 72 | @Bean 73 | FanoutExchange fanoutExchange() { 74 | return new FanoutExchange("fanoutExchange"); 75 | } 76 | 77 | @Bean 78 | Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) { 79 | return BindingBuilder.bind(AMessage).to(fanoutExchange); 80 | } 81 | 82 | @Bean 83 | Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) { 84 | return BindingBuilder.bind(BMessage).to(fanoutExchange); 85 | } 86 | 87 | @Bean 88 | Binding bindingExchangeC(Queue CMessage, FanoutExchange fanoutExchange) { 89 | return BindingBuilder.bind(CMessage).to(fanoutExchange); 90 | } 91 | } -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/controller/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.ocly.controller; 2 | 3 | import org.springframework.web.bind.annotation.ControllerAdvice; 4 | import org.springframework.web.bind.annotation.ExceptionHandler; 5 | import org.springframework.web.multipart.MultipartException; 6 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 7 | 8 | /** 9 | * @author ocly 10 | * @date 2018/1/22 8:40 11 | */ 12 | @ControllerAdvice 13 | public class GlobalExceptionHandler { 14 | @ExceptionHandler(MultipartException.class) 15 | public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) { 16 | redirectAttributes.addFlashAttribute("message", e.getCause().getMessage()); 17 | return "redirect:/uploadStatus"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/controller/UploadController.java: -------------------------------------------------------------------------------- 1 | package com.ocly.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestParam; 7 | import org.springframework.web.multipart.MultipartFile; 8 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 9 | 10 | import java.io.IOException; 11 | import java.nio.file.Files; 12 | import java.nio.file.Path; 13 | import java.nio.file.Paths; 14 | 15 | /** 16 | * @author ocly 17 | * @date 2018/1/22 8:37 18 | */ 19 | @Controller 20 | public class UploadController { 21 | //Save the uploaded file to this folder 22 | private static String UPLOADED_FOLDER = "L://temp//"; 23 | 24 | @GetMapping("/") 25 | public String index() { 26 | return "upload"; 27 | } 28 | 29 | @PostMapping("/upload") // //new annotation since 4.3 30 | public String singleFileUpload(@RequestParam("file") MultipartFile file, 31 | RedirectAttributes redirectAttributes) { 32 | if (file.isEmpty()) { 33 | redirectAttributes.addFlashAttribute("message", "Please select a file to upload"); 34 | return "redirect:uploadStatus"; 35 | } 36 | 37 | try { 38 | // Get the file and save it somewhere 39 | byte[] bytes = file.getBytes(); 40 | Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename()); 41 | Files.write(path, bytes); 42 | 43 | redirectAttributes.addFlashAttribute("message", 44 | "You successfully uploaded '" + file.getOriginalFilename() + "'"); 45 | 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | 50 | return "redirect:/uploadStatus"; 51 | } 52 | 53 | @GetMapping("/uploadStatus") 54 | public String uploadStatus() { 55 | return "uploadStatus"; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/generic/GenericTest.java: -------------------------------------------------------------------------------- 1 | package com.ocly.generic; 2 | 3 | /** 4 | * 泛型 5 | * 6 | * Created by cy 7 | * 2017/12/26 14:49 8 | */ 9 | 10 | class Hello{ 11 | private T name; 12 | 13 | public T getName() { 14 | return name; 15 | } 16 | 17 | public void setName(T name) { 18 | this.name = name; 19 | } 20 | 21 | 22 | } 23 | public class GenericTest { 24 | public static void main(String[] args) { 25 | Hello name = new Hello(); 26 | name.setName(new Hello()); 27 | hello(name); 28 | 29 | } 30 | public static void hello(Hello h){ 31 | System.out.println(h.getName()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/io/IOUtils.java: -------------------------------------------------------------------------------- 1 | package com.ocly.io; 2 | 3 | import java.awt.*; 4 | import java.io.*; 5 | 6 | /** 7 | * Created by cy 8 | * 2017/12/25 14:00 9 | */ 10 | public class IOUtils { 11 | 12 | /** 13 | * 读取文件内容,以16进制显示 14 | * 15 | * @param filename 16 | */ 17 | public static void printHex(String filename) throws IOException { 18 | FileInputStream in = new FileInputStream(filename); 19 | int b; 20 | int i = 1; 21 | while ((b = in.read()) != -1) { 22 | System.out.print(String.format("%02x ", b)); 23 | if (i++ % 10 == 0) { 24 | System.out.println(); 25 | } 26 | } 27 | in.close(); 28 | } 29 | 30 | /** 31 | * 读取文件内容到数组,以16进制显示 32 | * 33 | * @param filename 34 | */ 35 | public static void printHexArray(String filename) throws IOException { 36 | FileInputStream in = new FileInputStream(filename); 37 | byte[] buf = new byte[20 * 1024]; 38 | /* 从in中批量读取字节,放到buf数组中, 39 | 从0开始 最多 buf.length个 40 | 返回读到的字节个数*/ 41 | int b = in.read(buf, 0, buf.length); 42 | int i = 1; 43 | for (int j = 0; j < b; j++) { 44 | 45 | System.out.print(String.format("%02x ", buf[j])); 46 | if (i++ % 10 == 0) { 47 | System.out.println(); 48 | } 49 | } 50 | in.close(); 51 | } 52 | 53 | /** 54 | * 写到文件 55 | * 56 | * @param filename 57 | */ 58 | public static void writeHex(String filename) throws IOException { 59 | // 没有就创建,有的话 删了再创建,true则是追加 60 | FileOutputStream out = new FileOutputStream(filename, true); 61 | out.write('A'); 62 | out.write(10); 63 | //每次写一个字节 64 | out.close(); 65 | IOUtils.printHex(filename); 66 | } 67 | 68 | /** 69 | * 拷贝文件 批量+缓存 70 | * 71 | * @param fromfile 72 | * @param tofile 73 | * @throws IOException 74 | */ 75 | public static void copyFile(File fromfile, File tofile) throws IOException { 76 | if (!fromfile.exists()) { 77 | throw new IllegalArgumentException("不存在"); 78 | } 79 | if (!fromfile.isFile()) { 80 | throw new IllegalArgumentException("不是文件"); 81 | } 82 | FileInputStream in = new FileInputStream(fromfile); 83 | FileOutputStream out = new FileOutputStream(tofile); 84 | byte[] buf = new byte[8 * 1024]; 85 | int b; 86 | /* public int read(byte b[]) throws IOException { 87 | return readBytes(b, 0, b.length); 88 | }*/ 89 | while ((b = in.read(buf)) != -1) { 90 | out.write(buf, 0, b); 91 | } 92 | out.flush();//字节流最好加上 93 | in.close(); 94 | out.close(); 95 | } 96 | 97 | /** 98 | * 拷贝文件 buff缓存 99 | * 100 | * @param fromfile 101 | * @param tofile 102 | * @throws IOException 103 | */ 104 | public static void copyFileByBuff(File fromfile, File tofile) throws IOException { 105 | if (!fromfile.exists()) { 106 | throw new IllegalArgumentException("不存在"); 107 | } 108 | if (!fromfile.isFile()) { 109 | throw new IllegalArgumentException("不是文件"); 110 | } 111 | BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fromfile)); 112 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tofile)); 113 | int b; 114 | while ((b = bis.read()) != -1) { 115 | bos.write(b); 116 | } 117 | //bos.flush();//字节流最好加上 118 | bis.close(); 119 | bos.close(); 120 | } 121 | 122 | /** 123 | * 拷贝文本文件 buff缓存 124 | * 125 | * @param fromfile 126 | * @param tofile 127 | * @throws IOException 128 | */ 129 | public static void copytxtFileByBuff(File fromfile, File tofile) { 130 | if (!fromfile.exists()) { 131 | throw new IllegalArgumentException("不存在"); 132 | } 133 | if (!fromfile.isFile()) { 134 | throw new IllegalArgumentException("不是文件"); 135 | } 136 | try { 137 | InputStreamReader is = new InputStreamReader(new FileInputStream(fromfile)); 138 | OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(tofile)); 139 | 140 | BufferedReader bs = new BufferedReader(is); 141 | // BufferedWriter bw = new BufferedWriter(os); 142 | PrintWriter pw = new PrintWriter(os,true); 143 | String input; 144 | while ((input = bs.readLine()) != null) { 145 | pw.println(input); 146 | } 147 | // bw.flush(); 148 | // bw.close(); 149 | pw.close(); 150 | bs.close(); 151 | os.close(); 152 | is.close(); 153 | } catch (IOException e) { 154 | e.printStackTrace(); 155 | } finally { 156 | } 157 | } 158 | 159 | /** 160 | * 写到文件,dataoutputstream 161 | * 162 | * @param filename 163 | */ 164 | public static void writeInfile(String filename) throws IOException { 165 | // 没有就创建,有的话 删了再创建,true则是追加 166 | DataOutputStream out = new DataOutputStream(new FileOutputStream(filename)); 167 | out.writeInt(10); 168 | out.writeUTF("你好"); // utf-8 169 | out.writeChars("你好"); // utf-16 170 | out.close(); 171 | IOUtils.printHex("C:\\Users\\Administrator\\Desktop\\hhh.txt"); 172 | } 173 | 174 | public static void readfile(String filename) throws IOException { 175 | FileInputStream in = new FileInputStream(filename); 176 | InputStreamReader is = new InputStreamReader(in, "utf-8"); 177 | int b; 178 | while ((b = is.read()) != -1) { 179 | System.out.print((char) b); 180 | } 181 | in.close(); 182 | is.close(); 183 | } 184 | 185 | public static void main(String[] args) { 186 | try { 187 | // IOUtils.writeHex("H:\\mavenpro\\springboot-demo\\springboot-rabbitmq\\src\\main\\resources\\out.dat"); 188 | // IOUtils.copyFile(new File("H:\\mavenpro\\springboot-demo\\springboot-rabbitmq\\src\\main\\resources\\banner.txt"),new File 189 | // ("H:\\mavenpro\\springboot-demo\\springboot-rabbitmq\\src\\main\\resources\\out.txt")); 190 | // IOUtils.printHex("C:\\Users\\Administrator\\Desktop\\hhh.txt"); 191 | // System.out.println(""); 192 | // IOUtils.printHexArray("C:\\Users\\Administrator\\Desktop\\hhh.txt"); 193 | // IOUtils.writeInfile("C:\\\\Users\\\\Administrator\\\\Desktop\\\\hhh.txt"); 194 | 195 | // Long start = System.currentTimeMillis(); 196 | // IOUtils.copyFile(new File("C:\\Users\\Administrator\\Desktop\\1.mp3"), new File("C:\\Users\\Administrator\\Desktop\\4.mp3")); 197 | // Long end = System.currentTimeMillis(); 198 | // System.out.println(end - start); 199 | IOUtils.copytxtFileByBuff(new File("C:\\Users\\Administrator\\Desktop\\hhh.txt"), new File("C:\\Users\\Administrator\\Desktop\\hhhs.txt")); 200 | } catch (Exception e) { 201 | e.printStackTrace(); 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/io/ThreadCopy.java: -------------------------------------------------------------------------------- 1 | package com.ocly.io; 2 | 3 | 4 | import org.apache.commons.lang.StringUtils; 5 | import org.apache.logging.log4j.core.util.FileUtils; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.IOException; 10 | import java.io.RandomAccessFile; 11 | 12 | /** 13 | * Created by cy 14 | * 2017/12/26 9:40 15 | */ 16 | public class ThreadCopy extends Thread { 17 | int block; 18 | File fromfile; 19 | File tofile; 20 | int l = 100; 21 | 22 | public ThreadCopy(File tofile, int block) { 23 | this.tofile = tofile; 24 | this.block = block; 25 | 26 | } 27 | 28 | @Override 29 | public void run() { 30 | try { 31 | RandomAccessFile raf = new RandomAccessFile(tofile, "rw"); 32 | raf.seek((block - 1) * 100); 33 | raf.writeBytes("this is block "+block+"\n"); 34 | raf.close(); 35 | } catch (FileNotFoundException e) { 36 | e.printStackTrace(); 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | 41 | } 42 | public static void main(String[] args) { 43 | // File file = new File("test.txt"); 44 | // new ThreadCopy(file, 1).start(); 45 | // new ThreadCopy(file, 3).start(); 46 | // new ThreadCopy(file, 2).start(); 47 | // new ThreadCopy(file, 4).start(); 48 | 49 | String ss = "eeeeeeeedddd"; 50 | int sd = StringUtils.indexOf(ss, "sd"); 51 | System.out.println(sd); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/SingletonA.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | import sun.security.jca.GetInstance; 4 | 5 | /** 6 | * 饿汉模式,加载就创建 线程安全 7 | * Created by cy 8 | * 2017/12/25 9:11 9 | */ 10 | public class SingletonA { 11 | 12 | // 将构造方法私有化 13 | private SingletonA() { 14 | } 15 | // 创建唯一实例 16 | private static SingletonA instance = new SingletonA(); 17 | 18 | //提供获取实例的方法 19 | public static SingletonA getInstance(){ 20 | return instance; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/SingletonB.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | /** 4 | * 懒汉模式 线程不安全 5 | * Created by cy 6 | * 2017/12/25 9:19 7 | */ 8 | public class SingletonB { 9 | // 将构造方法私有化 10 | private SingletonB() { 11 | } 12 | 13 | // 申明唯一实例 14 | private static SingletonB instance; 15 | 16 | //提供获取实例的方法 17 | public static SingletonB getInstance() { 18 | if (instance == null) { 19 | instance = new SingletonB(); 20 | } 21 | return instance; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/SingletonC.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | import groovy.lang.Singleton; 4 | 5 | /** 6 | * 静态内部类 7 | * 这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程, 8 | * 它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了, 9 | * 那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了, 10 | * instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时, 11 | * 才会显示装载SingletonHolder类,从而实例化instance。 12 | * 想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化, 13 | * 因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载, 14 | * 那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理。 15 | * Created by cy 16 | * 2017/12/25 9:40 17 | */ 18 | public class SingletonC { 19 | private static class SingletonCHolder { 20 | private static final SingletonC INSTANCE = new SingletonC(); 21 | } 22 | 23 | private SingletonC() { 24 | } 25 | 26 | public static final SingletonC getInstance() { 27 | return SingletonCHolder.INSTANCE; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/SingletonD.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | /** 4 | * 枚举 这种方式是Effective Java作者Josh Bloch 提倡的方式 5 | * Created by cy 6 | * 2017/12/25 9:44 7 | */ 8 | public enum SingletonD { 9 | INSTANCE; 10 | public void whateverMethod() { 11 | } 12 | } -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/SingletonE.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | /** 4 | * 双重锁 5 | *

    6 | * Created by cy 7 | * 2017/12/25 9:47 8 | */ 9 | public class SingletonE { 10 | private SingletonE() { 11 | } 12 | 13 | private volatile static SingletonE singletonE; 14 | 15 | public static SingletonE getSingletonE() { 16 | if (singletonE == null) { 17 | synchronized (SingletonE.class) { 18 | if (singletonE == null) { 19 | singletonE = new SingletonE(); 20 | } 21 | } 22 | } 23 | return singletonE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/modle/User.java: -------------------------------------------------------------------------------- 1 | package com.ocly.modle; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by cy 7 | * 2017/12/12 14:22 8 | */ 9 | public class User implements Serializable { 10 | 11 | private String name; 12 | private Integer age; 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public void setName(String name) { 19 | this.name = name; 20 | } 21 | 22 | public Integer getAge() { 23 | return age; 24 | } 25 | 26 | public void setAge(Integer age) { 27 | this.age = age; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "User{" + 33 | "name='" + name + '\'' + 34 | ", age=" + age + 35 | '}'; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/FanoutReceiverA.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 19:32 10 | */ 11 | @Component 12 | @RabbitListener(queues = "fanout.A") 13 | public class FanoutReceiverA { 14 | 15 | @RabbitHandler 16 | public void process(String message) { 17 | System.out.println("fanout Receiver A : " + message); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/FanoutReceiverB.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 19:32 10 | */ 11 | @Component 12 | @RabbitListener(queues = "fanout.B") 13 | public class FanoutReceiverB { 14 | 15 | @RabbitHandler 16 | public void process(String message) { 17 | System.out.println("fanout Receiver B : " + message); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/FanoutReceiverC.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 19:32 10 | */ 11 | @Component 12 | @RabbitListener(queues = "fanout.C") 13 | public class FanoutReceiverC { 14 | 15 | @RabbitHandler 16 | public void process(String message) { 17 | System.out.println("fanout Receiver C : " + message); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/ObjReceive.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import com.ocly.modle.User; 4 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/12/12 14:28 11 | */ 12 | @Component 13 | @RabbitListener(queues = "user") 14 | public class ObjReceive { 15 | 16 | @RabbitHandler 17 | public void process(User user){ 18 | System.out.println("objreceive:"+user.toString()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/ObjSender.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import com.ocly.modle.User; 4 | import org.springframework.amqp.core.AmqpTemplate; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/12/12 10:06 11 | */ 12 | @Component 13 | public class ObjSender { 14 | @Autowired 15 | private AmqpTemplate rabbitTemplate; 16 | 17 | public void send(User user) { 18 | System.out.println("senderobj>>>" + user.toString()); 19 | this.rabbitTemplate.convertAndSend("user", user); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/Receiver.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 10:06 10 | */ 11 | @Component 12 | @RabbitListener(queues = "hello") 13 | public class Receiver { 14 | 15 | @RabbitHandler 16 | public void process(String context) { 17 | System.out.println("receive>>>>>" + context); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/Receivertow.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import com.ocly.modle.User; 4 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 5 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 6 | import org.springframework.stereotype.Component; 7 | 8 | /** 9 | * Created by cy 10 | * 2017/12/12 13:58 11 | */ 12 | @Component 13 | @RabbitListener(queues = "hello") 14 | public class Receivertow { 15 | 16 | @RabbitHandler 17 | public void process(String user) { 18 | System.out.println("receive2>>>>>" + user); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/Sender.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import com.ocly.modle.User; 4 | import org.springframework.amqp.core.AmqpTemplate; 5 | import org.springframework.amqp.rabbit.core.RabbitTemplate; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * Created by cy 11 | * 2017/12/12 10:06 12 | */ 13 | @Component 14 | public class Sender { 15 | @Autowired 16 | private AmqpTemplate rabbitTemplate; 17 | 18 | public void send() { 19 | String context = "hello world"; 20 | System.out.println("sender>>>" + context); 21 | this.rabbitTemplate.convertAndSend("hello", context); 22 | } 23 | 24 | 25 | public void topicSendOne() { 26 | String context = "hello topicSendone"; 27 | System.out.println("sender>>>" + context); 28 | this.rabbitTemplate.convertAndSend("topicexchange","topic.one",context); 29 | } 30 | 31 | public void topicSendTwo() { 32 | String context = "hello topicSendTwo"; 33 | System.out.println("sender>>>" + context); 34 | this.rabbitTemplate.convertAndSend("topicexchange","topic.two",context); 35 | } 36 | 37 | /** 38 | * 发布订阅模式 39 | */ 40 | public void fanoutSend() { 41 | String context = "hello fanout"; 42 | System.out.println("sender>>>" + context); 43 | this.rabbitTemplate.convertAndSend("fanoutExchange","",context); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/TopicOneReceive.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 17:17 10 | */ 11 | @Component 12 | @RabbitListener(queues = "topic.one") 13 | public class TopicOneReceive { 14 | 15 | @RabbitHandler 16 | public void process(String str) { 17 | System.out.println("topicone>>receive>>" + str); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/rabbit/TopicTwoReceive.java: -------------------------------------------------------------------------------- 1 | package com.ocly.rabbit; 2 | 3 | import org.springframework.amqp.rabbit.annotation.RabbitHandler; 4 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Created by cy 9 | * 2017/12/12 17:19 10 | */ 11 | @Component 12 | @RabbitListener(queues = "topic.two") 13 | public class TopicTwoReceive { 14 | @RabbitHandler 15 | public void process(String str) { 16 | System.out.println("topictwo>>receive>>" + str); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/task/Crawl.java: -------------------------------------------------------------------------------- 1 | package com.ocly.task; 2 | 3 | /** 4 | * Created by cy 5 | * 2017/12/19 10:37 6 | */ 7 | public class Crawl { 8 | 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.ocly.test; 2 | 3 | import com.ocly.modle.SingletonA; 4 | import com.ocly.modle.SingletonB; 5 | 6 | /** 7 | * Created by cy 8 | * 2017/12/25 9:15 9 | */ 10 | public class Test { 11 | public static void main(String[] args) { 12 | SingletonA a = SingletonA.getInstance(); 13 | SingletonA b = SingletonA.getInstance(); 14 | if (a == b) { 15 | System.out.println("同一个"); 16 | } else { 17 | System.out.println("不是同一个"); 18 | } 19 | 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/thread/Ocly.java: -------------------------------------------------------------------------------- 1 | package com.ocly.thread; 2 | 3 | /** 4 | * Created by cy 5 | * 2017/12/25 10:05 6 | */ 7 | public class Ocly extends Thread { 8 | 9 | // thread stop use flag 10 | volatile boolean isok = true; 11 | @Override 12 | public void run() { 13 | System.out.println(getName() + " is actor"); 14 | int count = 0; 15 | while (isok) { 16 | System.out.println(getName() + " appear " + (++count)); 17 | if (count == 40) { 18 | isok = false; 19 | } 20 | if (count % 5 == 0) { 21 | try { 22 | Thread.sleep(2000); 23 | } catch (InterruptedException e) { 24 | e.printStackTrace(); 25 | } 26 | } 27 | } 28 | 29 | System.out.println(getName() + " play over"); 30 | } 31 | 32 | public static void main(String[] args) throws InterruptedException { 33 | Thread a = new Ocly(); 34 | a.setName("Ocly"); 35 | a.start(); 36 | Wack wack = new Wack(); 37 | Thread b = new Thread(wack,"Wack"); 38 | b.start(); 39 | Thread.sleep(3000); 40 | wack.isok=false; 41 | } 42 | } 43 | 44 | class Wack implements Runnable{ 45 | volatile boolean isok = true; 46 | @Override 47 | public void run() { 48 | System.out.println(Thread.currentThread().getName() + " is actor"); 49 | int count = 0; 50 | while (isok) { 51 | System.out.println(Thread.currentThread().getName() + " appear " + (++count)); 52 | if (count == 100) { 53 | isok = false; 54 | } 55 | if (count % 10 == 0) { 56 | try { 57 | Thread.sleep(1000); 58 | } catch (InterruptedException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | 64 | System.out.println(Thread.currentThread().getName() + " play over"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/java/com/ocly/util/SendMail.java: -------------------------------------------------------------------------------- 1 | package com.ocly.util; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.core.io.FileSystemResource; 7 | import org.springframework.mail.SimpleMailMessage; 8 | import org.springframework.mail.javamail.JavaMailSender; 9 | import org.springframework.mail.javamail.MimeMessageHelper; 10 | import org.springframework.stereotype.Component; 11 | import org.thymeleaf.TemplateEngine; 12 | import org.thymeleaf.context.Context; 13 | 14 | import javax.mail.MessagingException; 15 | import javax.mail.internet.MimeMessage; 16 | import java.io.File; 17 | 18 | /** 19 | * Created by cy 20 | * 2017/12/13 19:57 21 | */ 22 | @Component 23 | @Log4j2 24 | public class SendMail { 25 | @Autowired 26 | private JavaMailSender javaMailSender; 27 | @Autowired 28 | private TemplateEngine templateEngine; 29 | 30 | @Value("${spring.mail.username}") 31 | private String from; 32 | 33 | /** 34 | * 发送文本邮件 35 | * 36 | * @param subject 37 | * @param to 38 | * @param context 39 | */ 40 | 41 | public void sendSimpleMail(String subject, String to, String context) { 42 | SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); 43 | 44 | simpleMailMessage.setFrom(from); 45 | simpleMailMessage.setTo(to); 46 | simpleMailMessage.setSubject(subject); 47 | simpleMailMessage.setText(context); 48 | 49 | try { 50 | javaMailSender.send(simpleMailMessage); 51 | log.info("sucessss:{}", from); 52 | } catch (Exception e) { 53 | log.info("error:{}", from); 54 | } 55 | 56 | 57 | } 58 | 59 | /** 60 | * 发送带文件的mail 61 | * 62 | * @param subject 63 | * @param to 64 | * @param context 65 | * @param filepath 66 | */ 67 | public void sendFileMail(String subject, String to, String context, String filepath) { 68 | 69 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 70 | 71 | try { 72 | MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 73 | helper.setSubject(subject); 74 | helper.setTo(to); 75 | helper.setFrom(from); 76 | helper.setText(context); 77 | 78 | FileSystemResource resource = new FileSystemResource(new File(filepath)); 79 | String filename = filepath.substring(filepath.lastIndexOf(File.separator)); 80 | helper.addAttachment(filename, resource); 81 | 82 | javaMailSender.send(mimeMessage); 83 | 84 | } catch (MessagingException e) { 85 | e.printStackTrace(); 86 | } 87 | } 88 | 89 | /** 90 | * 发送 html mail 91 | * 92 | * @param subject 93 | * @param to 94 | * @param context 95 | */ 96 | public void sendHtmlMail(String subject, String to, String context) { 97 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 98 | 99 | try { 100 | // 创建多部件的mail 101 | MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 102 | helper.setSubject(subject); 103 | helper.setTo(to); 104 | helper.setFrom(from); 105 | helper.setText(context, true); 106 | 107 | javaMailSender.send(mimeMessage); 108 | 109 | } catch (MessagingException e) { 110 | e.printStackTrace(); 111 | } 112 | 113 | 114 | } 115 | 116 | /** 117 | * 发送 模板html mail 带附件 带静态资源 118 | * 119 | * @param subject 120 | * @param to 121 | * @param name 122 | */ 123 | public void sendtemplateHtmlMail(String subject, String to, String name) { 124 | 125 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 126 | 127 | try { 128 | // 创建多部件的mail 129 | MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 130 | helper.setSubject(subject); 131 | helper.setTo(to); 132 | helper.setFrom(from); 133 | String filepath = "C:\\Users\\Administrator\\Desktop\\ocly.png"; 134 | FileSystemResource resource = new FileSystemResource(new File(filepath)); 135 | 136 | String filename = filepath.substring(filepath.lastIndexOf(File.separator)); 137 | helper.addAttachment(filename, resource); 138 | 139 | Context context = new Context(); 140 | context.setVariable("name", name); 141 | String templateHtml = templateEngine.process("emailTemplate", context); 142 | 143 | log.info("来看看模板长啥样 {}",templateHtml); 144 | 145 | helper.setText(templateHtml, true); 146 | // helper.setText("", true); 147 | 148 | helper.addInline("ocly", resource); 149 | javaMailSender.send(mimeMessage); 150 | log.info("模板邮件发送成功"); 151 | } catch (MessagingException e) { 152 | log.error("模板邮件发送失败"); 153 | } 154 | 155 | 156 | } 157 | 158 | /** 159 | * 发送静态邮件 160 | * 161 | * @param subject 162 | * @param to 163 | * @param context 164 | * @param filepath 165 | * @param fileid 166 | */ 167 | 168 | public void sendstaticMail(String subject, String to, String context, String filepath, String fileid) { 169 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); 170 | 171 | try { 172 | // 创建多部件的mail 173 | MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); 174 | helper.setSubject(subject); 175 | helper.setTo(to); 176 | helper.setFrom(from); 177 | helper.setText(context); 178 | 179 | FileSystemResource resource = new FileSystemResource(new File(filepath)); 180 | helper.addInline(fileid, resource); 181 | 182 | javaMailSender.send(mimeMessage); 183 | 184 | } catch (MessagingException e) { 185 | e.printStackTrace(); 186 | } 187 | 188 | 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | rabbitmq: 3 | username: ocly 4 | password: 123456 5 | thymeleaf: 6 | cache: false 7 | mode: LEGACYHTML5 8 | mail: 9 | host: smtp.sina.com 10 | # 去页面开启SMTP 11 | username: 12 | password: 13 | default-encoding: UTF-8 14 | port: 15 | http: 16 | multipart: 17 | max-file-size: 2Mb -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.RED}${AnsiStyle.ITALIC}I'm Red and italic ${AnsiStyle.NORMAL}${AnsiColor.DEFAULT} 2 | ${AnsiColor.BLUE}${AnsiBackground.YELLOW}I'm Blue with yellow background${AnsiBackground.DEFAULT}${AnsiColor.DEFAULT} 3 | ${AnsiColor.GREEN}Powered by ${spring-boot.formatted-version}${AnsiColor.DEFAULT} 4 | ${AnsiColor.BLUE} 5 | ██████╗ ██████╗██╗ ██╗ ██╗ 6 | ██╔═══██╗██╔════╝██║ ╚██╗ ██╔╝ 7 | ██║ ██║██║ ██║ ╚████╔╝ 8 | ██║ ██║██║ ██║ ╚██╔╝ 9 | ╚██████╔╝╚██████╗███████╗██║ 10 | ╚═════╝ ╚═════╝╚══════╝╚═╝ 11 | 12 | ${AnsiColor.BRIGHT_GREEN}Spring Boot>>>>> ${spring-boot.formatted-version} 13 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/out.dat: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/out.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.RED}${AnsiStyle.ITALIC}I'm Red and italic ${AnsiStyle.NORMAL}${AnsiColor.DEFAULT} 2 | ${AnsiColor.BLUE}${AnsiBackground.YELLOW}I'm Blue with yellow background${AnsiBackground.DEFAULT}${AnsiColor.DEFAULT} 3 | ${AnsiColor.GREEN}Powered by ${spring-boot.formatted-version}${AnsiColor.DEFAULT} 4 | ${AnsiColor.BLUE} 5 | ██████╗ ██████╗██╗ ██╗ ██╗ 6 | ██╔═══██╗██╔════╝██║ ╚██╗ ██╔╝ 7 | ██║ ██║██║ ██║ ╚████╔╝ 8 | ██║ ██║██║ ██║ ╚██╔╝ 9 | ╚██████╔╝╚██████╗███████╗██║ 10 | ╚═════╝ ╚═════╝╚══════╝╚═╝ 11 | 12 | ${AnsiColor.BRIGHT_GREEN}Spring Boot>>>>> ${spring-boot.formatted-version} 13 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/static/img/QQ图片20171214160014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/springboot-rabbitmq/src/main/resources/static/img/QQ图片20171214160014.png -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/templates/emailTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 29 | 30 | 31 |

    32 | 33 | 34 | 35 | 96 | 97 | 98 |
    36 | 37 | 38 | 39 | 92 | 93 | 94 |
    40 | 41 | 42 | 43 | 70 | 71 | 72 | 88 | 89 | 90 |
    44 | 45 | 46 | 47 | 66 | 67 | 68 |
    48 | 49 | 50 | 51 | 54 | 62 | 63 | 64 |
    52 | 53 | 55 |
    56 |

    欢迎来到宠物王国

    57 |

    感谢您的注册

    58 | 60 |
    61 |
    65 |
    69 |
    73 | 74 | 75 | 76 | 84 | 85 | 86 |
    77 |
    79 |
    80 |
    81 | 您已加入我们,点击上方激活按钮,开始你的旅程吧 82 |
    83 |
    87 |
    91 |
    95 |
    99 |
    100 | 101 | 102 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/templates/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

    Spring Boot file upload example

    6 | 7 |
    8 |

    9 | 10 |
    11 | 12 | 13 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/main/resources/templates/uploadStatus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

    Spring Boot - Upload Status

    6 | 7 |
    8 |

    9 |

    10 | 11 | 12 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/test/java/com/ocly/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.ocly; 2 | 3 | import com.ocly.modle.User; 4 | import com.ocly.rabbit.ObjSender; 5 | import com.ocly.rabbit.Sender; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | @RunWith(SpringRunner.class) 13 | @SpringBootTest 14 | public class ApplicationTests { 15 | 16 | @Autowired 17 | private Sender sender; 18 | @Autowired 19 | private ObjSender objSender; 20 | 21 | @Test 22 | public void hello() throws Exception { 23 | for (int i = 0; i < 10 ; i++) { 24 | sender.send(); 25 | } 26 | } 27 | 28 | @Test 29 | public void user() throws Exception { 30 | User user = new User(); 31 | user.setAge(18); 32 | user.setName("ocly"); 33 | objSender.send(user); 34 | } 35 | 36 | @Test 37 | public void topic() throws Exception { 38 | sender.topicSendOne(); 39 | } 40 | 41 | @Test 42 | public void fanout() throws Exception { 43 | sender.fanoutSend(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /springboot-rabbitmq/src/test/java/com/ocly/util/sendMailTest.java: -------------------------------------------------------------------------------- 1 | package com.ocly.util; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | /** 10 | * Created by cy 11 | * 2017/12/13 20:36 12 | */ 13 | @RunWith(SpringRunner.class) 14 | @SpringBootTest 15 | public class sendMailTest { 16 | 17 | 18 | @Autowired 19 | private SendMail sendMail; 20 | 21 | @Test 22 | public void hello() throws Exception { 23 | sendMail.sendSimpleMail("aaaa","1193889747@qq.com","sdas"); 24 | } 25 | 26 | @Test 27 | public void hellomaiTemplate() throws Exception { 28 | sendMail.sendtemplateHtmlMail("你好,模板邮件加附件加图片","1193889747@qq.com","Bocly"); 29 | } 30 | } -------------------------------------------------------------------------------- /test.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yy1193889747/springboot-demo/eee5700d46db3dd8c087f3924f43abcd045e35a1/test.txt --------------------------------------------------------------------------------