Repository: 527515025/springBoot Branch: master Commit: 8fadfc312409 Files: 492 Total size: 928.0 KB Directory structure: gitextract_rd5xf_h5/ ├── .gitignore ├── README.md ├── abel-parent/ │ └── pom.xml ├── abel-util/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── cn/ │ └── abel/ │ ├── code/ │ │ └── InfoCode.java │ ├── exception/ │ │ ├── AppRuntimeException.java │ │ ├── HttpExeption.java │ │ └── ServiceException.java │ ├── response/ │ │ └── ResponseEntity.java │ └── utils/ │ └── DateTimeUtils.java ├── springWebSocket/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ ├── Message.java │ │ │ └── Response.java │ │ ├── config/ │ │ │ ├── WebSecurityConfig.java │ │ │ └── WebSocketConfig.java │ │ ├── controller/ │ │ │ └── WebSocketController.java │ │ └── service/ │ │ └── WebSocketService.java │ └── resources/ │ ├── application.properties │ ├── static/ │ │ └── jquery.js │ └── templates/ │ ├── chat.html │ ├── login.html │ └── ws.html ├── springboot-Cache/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ └── Person.java │ │ ├── config/ │ │ │ ├── DBConfig.java │ │ │ ├── JpaConfig.java │ │ │ └── RedisConfig.java │ │ ├── controller/ │ │ │ └── CacheController.java │ │ ├── dao/ │ │ │ └── PersonRepository.java │ │ └── service/ │ │ ├── DemoService.java │ │ └── Impl/ │ │ └── DemoServiceImpl.java │ └── resources/ │ ├── application.properties │ └── ehcache.xml ├── springboot-Cache2/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ └── Person.java │ │ ├── config/ │ │ │ ├── CacheConfig.java │ │ │ ├── DBConfig.java │ │ │ └── JpaConfig.java │ │ ├── controller/ │ │ │ └── CacheController.java │ │ ├── dao/ │ │ │ └── PersonRepository.java │ │ └── service/ │ │ ├── DemoService.java │ │ └── PersonService.java │ └── resources/ │ └── application.properties ├── springboot-Quartz/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── abel/ │ │ └── quartz/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── InvokingJobDetailFactory.java │ │ │ └── QuartzConfig.java │ │ └── job/ │ │ └── ExecuteJob.java │ └── resources/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-SpringSecurity0/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── DBconfig.java │ │ │ ├── MyBatisConfig.java │ │ │ ├── MyBatisScannerConfig.java │ │ │ ├── TransactionConfig.java │ │ │ ├── WebMvcConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── controller/ │ │ │ └── HomeController.java │ │ ├── dao/ │ │ │ └── UserDao.java │ │ ├── domain/ │ │ │ ├── Msg.java │ │ │ ├── SysRole.java │ │ │ └── SysUser.java │ │ ├── security/ │ │ │ └── CustomUserService.java │ │ └── util/ │ │ └── MD5Util.java │ └── resources/ │ ├── application.properties │ ├── mapper/ │ │ └── UserDaoMapper.xml │ └── templates/ │ ├── home.html │ └── login.html ├── springboot-SpringSecurity1/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── DBconfig.java │ │ │ ├── MyBatisConfig.java │ │ │ ├── MyBatisScannerConfig.java │ │ │ ├── TransactionConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── controller/ │ │ │ └── HomeController.java │ │ ├── dao/ │ │ │ ├── PermissionDao.java │ │ │ └── UserDao.java │ │ ├── domain/ │ │ │ ├── Msg.java │ │ │ ├── Permission.java │ │ │ ├── SysRole.java │ │ │ └── SysUser.java │ │ └── service/ │ │ ├── CustomUserService.java │ │ ├── MyAccessDecisionManager.java │ │ ├── MyFilterSecurityInterceptor.java │ │ └── MyInvocationSecurityMetadataSourceService.java │ └── resources/ │ ├── application.properties │ ├── mapper/ │ │ ├── PermissionDaoMapper.xml │ │ └── UserDaoMapper.xml │ └── templates/ │ ├── home.html │ └── login.html ├── springboot-dubbo/ │ ├── README.md │ ├── abel-user-api/ │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── user/ │ │ ├── models/ │ │ │ ├── Permission.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ └── service/ │ │ ├── PermissionService.java │ │ ├── RoleService.java │ │ └── UserService.java │ └── abel-user-provider/ │ ├── doc/ │ │ └── user.sql │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── user/ │ │ ├── UserProviderApplication.java │ │ ├── constants/ │ │ │ └── Constants.java │ │ ├── dao/ │ │ │ ├── PermissionDao.java │ │ │ ├── RoleDao.java │ │ │ └── UserDao.java │ │ ├── exception/ │ │ │ ├── JsonExceptionMapper.java │ │ │ ├── ReaderExceptionMapper.java │ │ │ ├── RestExceptionMapper.java │ │ │ ├── ServiceExceptionMapper.java │ │ │ └── ValidationExceptionMapper.java │ │ ├── filter/ │ │ │ ├── RestFilter.java │ │ │ └── RestInterceptor.java │ │ ├── service/ │ │ │ └── impl/ │ │ │ ├── PermissionServiceImpl.java │ │ │ ├── RoleServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── utils/ │ │ └── CommentUtils.java │ ├── resources/ │ │ ├── META-INF/ │ │ │ └── spring/ │ │ │ └── provider.xml │ │ ├── dev/ │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ └── logback-spring.xml │ │ ├── local/ │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ └── logback-spring.xml │ │ └── mapper/ │ │ ├── PermissionDaoMapper.xml │ │ ├── RoleDaoMapper.xml │ │ └── UserDaoMapper.xml │ └── test/ │ └── cn/ │ └── abel/ │ └── user/ │ ├── BaseTest.java │ └── service/ │ └── impl/ │ └── PermissionServiceImplTest.java ├── springboot-dynamicDataSource/ │ ├── pom.xml │ ├── sql/ │ │ ├── news.sql │ │ └── user.sql │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── cn/ │ │ │ └── abel/ │ │ │ ├── Application.java │ │ │ ├── bean/ │ │ │ │ ├── News.java │ │ │ │ └── User.java │ │ │ ├── config/ │ │ │ │ ├── DynamicDataSource.java │ │ │ │ ├── DynamicDataSourceConfig.java │ │ │ │ ├── DynamicDataSourceContextHolder.java │ │ │ │ └── HikariConfig.java │ │ │ ├── dao/ │ │ │ │ ├── NewsDao.java │ │ │ │ └── UserDao.java │ │ │ ├── enums/ │ │ │ │ └── DatabaseTypeEnum.java │ │ │ └── service/ │ │ │ ├── NewsService.java │ │ │ └── UserService.java │ │ └── resources/ │ │ ├── local/ │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ └── logback-spring.xml │ │ └── mapper/ │ │ ├── NewsDaoMapper.xml │ │ └── UserDaoMapper.xml │ └── test/ │ └── java/ │ └── cn/ │ └── abel/ │ ├── BaseTest.java │ └── service/ │ └── ServiceTest.java ├── springboot-elasticsearch/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── cn/ │ │ │ └── abel/ │ │ │ ├── Application.java │ │ │ ├── bean/ │ │ │ │ └── User.java │ │ │ ├── config/ │ │ │ │ ├── ESRestClient2Config.java │ │ │ │ └── ESRestClientConfig.java │ │ │ ├── constants/ │ │ │ │ └── Constants.java │ │ │ ├── dao/ │ │ │ │ └── UserDao.java │ │ │ └── service/ │ │ │ └── UserService.java │ │ └── resources/ │ │ ├── local/ │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ └── logback-spring.xml │ │ └── mapper/ │ │ └── UserDaoMapper.xml │ └── test/ │ └── java/ │ └── cn/ │ └── abel/ │ ├── BaseTest.java │ └── service/ │ └── ServiceTest.java ├── springboot-jpa/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ └── User.java │ │ ├── config/ │ │ │ ├── DBConfig.java │ │ │ └── JpaConfig.java │ │ ├── controller/ │ │ │ └── UserController.java │ │ ├── dao/ │ │ │ └── UserJpaDao.java │ │ ├── service/ │ │ │ └── UserService.java │ │ ├── serviceImpl/ │ │ │ └── UserServiceImpl.java │ │ └── util/ │ │ └── CommonUtil.java │ └── resources/ │ └── application.properties ├── springboot-kafka/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ ├── Application.java │ │ ├── config/ │ │ │ └── KafkaConfig.java │ │ └── service/ │ │ └── prehandle/ │ │ ├── KafkaConsumerService.java │ │ └── SplitService.java │ └── resources/ │ └── local/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-mybatis/ │ ├── docker-it.sh │ ├── env/ │ │ ├── dev/ │ │ │ ├── application.properties │ │ │ ├── env.properties │ │ │ └── log4j.properties │ │ └── local/ │ │ ├── application.properties │ │ ├── env.properties │ │ └── log4j.properties │ ├── package.sh │ ├── pom.xml │ ├── scripts/ │ │ ├── docker/ │ │ │ ├── common/ │ │ │ │ ├── common-env.sh │ │ │ │ ├── install-cluster.sh │ │ │ │ ├── install-single.sh │ │ │ │ ├── install.sh │ │ │ │ └── package.xml │ │ │ └── manager/ │ │ │ ├── check-os.sh │ │ │ ├── setenv.sh │ │ │ ├── start.sh │ │ │ └── stop.sh │ │ └── springboot/ │ │ ├── common/ │ │ │ ├── common-env.sh │ │ │ ├── install-cluster.sh │ │ │ ├── install-single.sh │ │ │ ├── install.sh │ │ │ └── package.xml │ │ └── manager/ │ │ ├── setenv.sh │ │ ├── start.sh │ │ └── stop.sh │ ├── src/ │ │ ├── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── us/ │ │ │ │ └── example/ │ │ │ │ ├── Application.java │ │ │ │ ├── bean/ │ │ │ │ │ └── User.java │ │ │ │ ├── config/ │ │ │ │ │ ├── DBConfig.java │ │ │ │ │ ├── MyBatisConfig.java │ │ │ │ │ ├── MyBatisScannerConfig.java │ │ │ │ │ └── TransactionConfig.java │ │ │ │ ├── controller/ │ │ │ │ │ └── UserController.java │ │ │ │ ├── dao/ │ │ │ │ │ └── UserDao.java │ │ │ │ ├── service/ │ │ │ │ │ ├── Impl/ │ │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ │ └── UserService.java │ │ │ │ └── util/ │ │ │ │ └── CommonUtil.java │ │ │ └── resources/ │ │ │ └── mapper/ │ │ │ └── UserDaoMapper.xml │ │ └── test/ │ │ └── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── BaseTest.java │ │ └── service/ │ │ └── UserServiceTest.java │ ├── tar-it.sh │ └── war-it.sh ├── springboot-mybatis2/ │ ├── pom.xml │ ├── sql/ │ │ └── user.sql │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── cn/ │ │ │ └── abel/ │ │ │ ├── Application.java │ │ │ ├── bean/ │ │ │ │ └── User.java │ │ │ ├── dao/ │ │ │ │ └── UserDao.java │ │ │ └── service/ │ │ │ └── UserService.java │ │ └── resources/ │ │ ├── local/ │ │ │ ├── application.properties │ │ │ ├── banner.txt │ │ │ └── logback-spring.xml │ │ └── mapper/ │ │ ├── NewsDaoMapper.xml │ │ └── UserDaoMapper.xml │ └── test/ │ └── java/ │ └── cn/ │ └── abel/ │ ├── BaseTest.java │ └── service/ │ └── ServiceTest.java ├── springboot-neo4j/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── cn/ │ │ │ └── abel/ │ │ │ └── neo4j/ │ │ │ ├── Application.java │ │ │ ├── bean/ │ │ │ │ ├── King.java │ │ │ │ ├── Person.java │ │ │ │ ├── Queen.java │ │ │ │ └── relation/ │ │ │ │ └── FatherAndSonRelation.java │ │ │ ├── controller/ │ │ │ │ └── KingController.java │ │ │ ├── dao/ │ │ │ │ ├── KingDao.java │ │ │ │ ├── Neo4jDao.java │ │ │ │ └── Neo4jSession.java │ │ │ ├── dto/ │ │ │ │ └── GraphDTO.java │ │ │ └── service/ │ │ │ └── KingService.java │ │ └── resources/ │ │ ├── application.properties │ │ ├── banner.txt │ │ └── logback-spring.xml │ └── test/ │ └── java/ │ └── cn/ │ └── abel/ │ └── neo4j/ │ ├── BaseTest.java │ └── service/ │ ├── InitData.java │ └── KingServiceTest.java ├── springboot-redis-queue/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── queue/ │ │ ├── Application.java │ │ ├── config/ │ │ │ └── RedisConfig.java │ │ ├── controller/ │ │ │ └── PublisherController.java │ │ └── service/ │ │ ├── ProducerService.java │ │ └── ReceiverService.java │ └── resources/ │ └── local/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-rocketmq/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── queue/ │ │ ├── Application.java │ │ ├── config/ │ │ │ └── JmsConfig.java │ │ ├── controller/ │ │ │ └── PublisherController.java │ │ └── service/ │ │ ├── ProducerService.java │ │ └── ReceiverService.java │ └── resources/ │ └── local/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-rocketmq-ali/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── queue/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── ALiConsumerClient.java │ │ │ ├── ALiMqConfig.java │ │ │ └── ALiProducerClient.java │ │ └── service/ │ │ ├── MessageHandler.java │ │ └── ProducerService.java │ └── resources/ │ └── local/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-shiro/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ ├── Event.java │ │ │ ├── Permission.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ ├── config/ │ │ │ ├── DataSourceConfig.java │ │ │ ├── MapperScannerConfig.java │ │ │ ├── MyBatisConfig.java │ │ │ └── TransactionConfig.java │ │ ├── controller/ │ │ │ ├── EventController.java │ │ │ ├── LoginController.java │ │ │ └── UserController.java │ │ ├── dao/ │ │ │ ├── EventDao.java │ │ │ ├── PermissionDao.java │ │ │ ├── RoleDao.java │ │ │ └── UserDao.java │ │ ├── service/ │ │ │ ├── EventService.java │ │ │ ├── PermissionService.java │ │ │ ├── RoleService.java │ │ │ └── UserService.java │ │ └── shiro/ │ │ ├── ShiroConfiguration.java │ │ └── ShiroRealm.java │ └── resources/ │ ├── application.properties │ ├── log4j.properties │ └── mapper/ │ ├── EventDaoMapper.xml │ ├── PermissionDaoMapper.xml │ ├── RoleDaoMapper.xml │ └── UserDaoMapper.xml ├── springboot-shiro2/ │ ├── README.md │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── cn/ │ │ └── abel/ │ │ └── rest/ │ │ ├── ShiroRestApplication.java │ │ ├── config/ │ │ │ └── RedisConfig.java │ │ ├── constants/ │ │ │ └── Constants.java │ │ ├── controller/ │ │ │ └── LoginController.java │ │ ├── exception/ │ │ │ ├── DefaultErrorController.java │ │ │ └── DefaultExceptionHandler.java │ │ ├── freemarker/ │ │ │ ├── CustomFreeMarkerView.java │ │ │ └── FreeMarkerConfig.java │ │ ├── shiro/ │ │ │ ├── HttpHeaderSessionManager.java │ │ │ ├── RedisSessionDao.java │ │ │ ├── ShiroConfig.java │ │ │ ├── ShiroProperty.java │ │ │ ├── ShiroRealm.java │ │ │ ├── ShiroRedisCacheManager.java │ │ │ ├── ShiroUser.java │ │ │ ├── UuidSessionIdGenerator.java │ │ │ ├── credentials/ │ │ │ │ ├── PasswordHelper.java │ │ │ │ ├── RetryLimitHashedCredentialsMatcher.java │ │ │ │ └── ThirdPartySupportedToken.java │ │ │ ├── ext/ │ │ │ │ ├── QuartzSessionValidationJob.java │ │ │ │ └── QuartzSessionValidationScheduler.java │ │ │ └── filter/ │ │ │ ├── ShiroFormAuthenticationFilter.java │ │ │ └── ShiroLogoutFilter.java │ │ └── utils/ │ │ ├── ServletKit.java │ │ └── SpringContextKit.java │ └── resources/ │ ├── META-INF/ │ │ └── spring/ │ │ └── consumer.xml │ ├── dev/ │ │ ├── application.properties │ │ ├── banner.txt │ │ └── logback-spring.xml │ └── local/ │ ├── application.properties │ ├── banner.txt │ └── logback-spring.xml ├── springboot-springCloud/ │ ├── config/ │ │ ├── pom.xml │ │ ├── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── abel/ │ │ │ │ └── ConfigApplication.java │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ ├── bootstrap.yml │ │ │ └── config/ │ │ │ ├── person.yml │ │ │ └── some.yml │ │ └── target/ │ │ └── classes/ │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── config/ │ │ ├── person.yml │ │ └── some.yml │ ├── discovery/ │ │ ├── pom.xml │ │ ├── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── abel/ │ │ │ │ └── DiscoveryApplication.java │ │ │ └── resources/ │ │ │ └── application.yml │ │ └── target/ │ │ └── classes/ │ │ └── application.yml │ ├── monitor/ │ │ ├── pom.xml │ │ ├── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── abel/ │ │ │ │ └── MonitorApplication.java │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── target/ │ │ └── classes/ │ │ ├── application.yml │ │ └── bootstrap.yml │ ├── person/ │ │ ├── pom.xml │ │ ├── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── abel/ │ │ │ │ ├── PersonApplication.java │ │ │ │ ├── bean/ │ │ │ │ │ └── Person.java │ │ │ │ ├── controller/ │ │ │ │ │ └── PersonController.java │ │ │ │ └── dao/ │ │ │ │ └── PersonRepository.java │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── target/ │ │ └── classes/ │ │ ├── application.yml │ │ └── bootstrap.yml │ ├── pom.xml │ ├── some/ │ │ ├── pom.xml │ │ ├── src/ │ │ │ └── main/ │ │ │ ├── java/ │ │ │ │ └── com/ │ │ │ │ └── abel/ │ │ │ │ └── SomeApplication.java │ │ │ └── resources/ │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── target/ │ │ └── classes/ │ │ ├── application.yml │ │ └── bootstrap.yml │ └── ui/ │ ├── pom.xml │ ├── src/ │ │ └── main/ │ │ ├── java/ │ │ │ └── com/ │ │ │ └── abel/ │ │ │ ├── UiApplication.java │ │ │ ├── bean/ │ │ │ │ └── Person.java │ │ │ ├── controller/ │ │ │ │ └── UiController.java │ │ │ └── service/ │ │ │ ├── PersonHystrixService.java │ │ │ ├── PersonService.java │ │ │ └── SomeHystrixService.java │ │ └── resources/ │ │ ├── application.yml │ │ ├── bootstrap.yml │ │ └── static/ │ │ ├── css/ │ │ │ └── application.css │ │ ├── index.html │ │ ├── js/ │ │ │ └── app.js │ │ └── tpl/ │ │ ├── person.html │ │ └── some.html │ └── target/ │ └── classes/ │ ├── application.yml │ ├── bootstrap.yml │ └── static/ │ ├── css/ │ │ └── application.css │ ├── index.html │ ├── js/ │ │ └── app.js │ └── tpl/ │ ├── person.html │ └── some.html ├── springboot-springSecurity2/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── DBconfig.java │ │ │ ├── MyBatisConfig.java │ │ │ ├── MyBatisScannerConfig.java │ │ │ ├── TransactionConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── controller/ │ │ │ ├── HomeController.java │ │ │ └── LoginController.java │ │ ├── dao/ │ │ │ └── UserDao.java │ │ ├── domain/ │ │ │ ├── SysRole.java │ │ │ └── SysUser.java │ │ ├── security/ │ │ │ └── CustomUserService.java │ │ ├── service/ │ │ │ └── UserService.java │ │ └── util/ │ │ ├── BCryptPasswordEncoderTest.java │ │ └── MD5Util.java │ └── resources/ │ ├── application.properties │ └── mapper/ │ └── UserDaoMapper.xml ├── springboot-springSecurity3/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── us/ │ │ └── example/ │ │ ├── Application.java │ │ ├── config/ │ │ │ ├── DBconfig.java │ │ │ ├── MyBatisConfig.java │ │ │ ├── MyBatisScannerConfig.java │ │ │ ├── TransactionConfig.java │ │ │ ├── WebMvcConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── controller/ │ │ │ └── HomeController.java │ │ ├── dao/ │ │ │ ├── PermissionDao.java │ │ │ └── UserDao.java │ │ ├── domain/ │ │ │ ├── Msg.java │ │ │ ├── Permission.java │ │ │ ├── SysRole.java │ │ │ └── SysUser.java │ │ └── service/ │ │ ├── CustomUserService.java │ │ ├── MyAccessDecisionManager.java │ │ ├── MyFilterSecurityInterceptor.java │ │ ├── MyGrantedAuthority.java │ │ └── MyInvocationSecurityMetadataSourceService.java │ └── resources/ │ ├── application.properties │ ├── mapper/ │ │ ├── PermissionDaoMapper.xml │ │ └── UserDaoMapper.xml │ └── templates/ │ ├── home.html │ └── login.html ├── springboot-springSecurity4/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── yy/ │ │ └── example/ │ │ ├── Application.java │ │ ├── bean/ │ │ │ ├── Permission.java │ │ │ ├── Role.java │ │ │ └── User.java │ │ ├── config/ │ │ │ ├── DataSourceConfig.java │ │ │ ├── MapperScannerConfig.java │ │ │ ├── MyBatisConfig.java │ │ │ ├── MyBatisScannerConfig.java │ │ │ ├── TransactionConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── controller/ │ │ │ ├── LoginController.java │ │ │ └── UserController.java │ │ ├── dao/ │ │ │ ├── PermissionDao.java │ │ │ └── UserDao.java │ │ ├── security/ │ │ │ ├── UrlAccessDecisionManager.java │ │ │ ├── UrlConfigAttribute.java │ │ │ ├── UrlFilterSecurityInterceptor.java │ │ │ ├── UrlGrantedAuthority.java │ │ │ ├── UrlMetadataSourceService.java │ │ │ └── UrlUserService.java │ │ ├── service/ │ │ │ └── UserService.java │ │ └── utils/ │ │ └── MD5Util.java │ └── resources/ │ ├── application.properties │ └── com/ │ └── yy/ │ └── example/ │ └── mapper/ │ ├── PermissionDaoMapper.xml │ └── UserDaoMapper.xml └── springboot-swagger-ui/ ├── pom.xml └── src/ └── main/ ├── java/ │ └── com/ │ └── abel/ │ └── example/ │ ├── Application.java │ ├── Swagger2.java │ ├── bean/ │ │ └── User.java │ ├── config/ │ │ ├── DBConfig.java │ │ └── JpaConfig.java │ ├── controller/ │ │ └── UserController.java │ ├── dao/ │ │ └── UserJpaDao.java │ ├── service/ │ │ └── UserService.java │ ├── serviceImpl/ │ │ └── UserServiceImpl.java │ └── util/ │ └── CommonUtil.java └── resources/ └── application.properties ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ /.settings /bin */target/* /logs */out/ # filter config files, except .gitignore *.MF !.gitignore *.iml *.exe # eclipse ignore .project .classpath # IDEA ignore .idea .class *.class *.log !application.properties ================================================ FILE: README.md ================================================ ## 致歉 由于自己懒以及身体对issuse 解决的不及时。请大家以后提issuse 的时候写清楚 模块名 比如“springboot-SpringSecurity4” 和问题,我会抽时间抓紧解决。 ## springboot-SpringSecurity0 包含两部分代码: * 第一是 博客 springboot+mybatis+SpringSecurity 实现用户角色数据库管理 地址:http://blog.csdn.net/u012373815/article/details/54632176 * 第二是 博客 springBoot+springSecurity验证密码MD5加密 地址:http://blog.csdn.net/u012373815/article/details/54927070 ## springboot-SpringSecurity1 * 博客 springBoot+springSecurity 数据库动态管理用户、角色、权限(二) 地址:http://blog.csdn.net/u012373815/article/details/54633046 ## springboot-SpringSecurity2 * 博客 springboot+security restful权限控制官方推荐(五) 地址:http://blog.csdn.net/u012373815/article/details/59749385 ## springboot-SpringSecurity3 * 博客 springBoot+springSecurity 动态管理Restful风格权限(三) 地址:http://blog.csdn.net/u012373815/article/details/55225079 ## springboot-SpringSecurity4 * 实战,项目中正在用 ## springboot-WebSocket 包含三部分代码,三部分代码有交合: * 第一是 博客 spring boot +WebSocket 广播式(一)地址:http://blog.csdn.net/u012373815/article/details/54375195 中所示代码 * 第二是 博客 spring boot +WebSocket 广播式(二)地址:http://blog.csdn.net/u012373815/article/details/54377937 中所示代码 * 第三是 博客 spring boot +WebSocket(三) 点对点式 地址: http://blog.csdn.net/u012373815/article/details/54380476 中所示代码 ## springboot-Cache 包含两部分代码: * 第一部分是 博客 springboot的缓存技术 地址: http://blog.csdn.net/u012373815/article/details/54564076 * 第二部分是 博客 springboot缓存篇(二)-redis 做缓存 地址:http://blog.csdn.net/u012373815/article/details/54572687 ## springboot-Cache2 * 是 博客 springboot缓存 之 GuavaCacheManager 地址:http://blog.csdn.net/u012373815/article/details/60468033 ## springboot-shiro * 是博客 springboot集成shiro 实现权限控制 地址:http://blog.csdn.net/u012373815/article/details/57532292 ##springboot-shior2 是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换 springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 ## springboot-swagger-ui * 博客 spring boot +Swagger-ui 自动生成API文档 地址: https://blog.csdn.net/u012373815/article/details/82685962 ## springBoot-Quartz * 博客 springBoot-Quartz 定时任务 地址: https://abelyang.blog.csdn.net/article/details/86740625 ## springboot 整合mybatis2 * springboot 整合mybatis2 更简便的整合方式地址: https://abelyang.blog.csdn.net/article/details/89296273 ## springboot+Kafka * kafka 与 sprigboot 的结合,springboot 从Kafka中读取数据的小例子地址: https://abelyang.blog.csdn.net/article/details/89296305 ## springboot+es * Elasticsearch 与 sprigboot 的结合,springboot 操作es的小例子地址: https://abelyang.blog.csdn.net/article/details/89296320 ## Springboot多数据源切换 * springboot 多个数据源的配置, 一个springboot 项目操作多个数据库的数据:https://abelyang.blog.csdn.net/article/details/89296341 ##springboot-dubbo 该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务 Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 ##未完待续。。。 ================================================ FILE: abel-parent/pom.xml ================================================ 4.0.0 cn.abel abel-parent pom 1.0.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE UTF-8 UTF-8 1.4.0 5.1.47 org.apache.commons commons-lang3 3.7 org.apache.commons commons-collections4 4.2 org.apache.commons commons-pool2 2.6.0 dom4j dom4j 1.6.1 mysql mysql-connector-java ${mysql.version} runtime com.alibaba druid 1.1.10 org.apache.shiro shiro-spring ${shiro.version} org.apache.shiro shiro-ehcache ${shiro.version} org.apache.shiro shiro-quartz ${shiro.version} org.opensymphony.quartz quartz net.mingsoft shiro-freemarker-tags 1.0.0 org.hibernate hibernate-core 5.3.4.Final com.fasterxml.jackson.core jackson-core 2.9.7 com.fasterxml.jackson.core jackson-databind 2.9.9.1 com.alibaba fastjson 1.2.58 org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2 com.github.pagehelper pagehelper-spring-boot-starter 1.2.5 org.quartz-scheduler quartz 2.2.1 com.alibaba dubbo 2.8.4 log4j log4j org.slf4j log4j-over-slf4j 1.7.25 org.apache.zookeeper zookeeper 3.4.13 org.slf4j slf4j-log4j12 log4j log4j org.jboss.resteasy resteasy-jaxrs 3.0.26.Final org.jboss.resteasy resteasy-client 3.0.26.Final org.jboss.resteasy resteasy-jackson-provider 3.0.26.Final javax.validation validation-api 2.0.1.Final org.hibernate.validator hibernate-validator 6.0.13.Final com.101tec zkclient 0.10 com.google.code.gson gson 2.8.5 org.apache.httpcomponents httpcore 4.4.10 org.apache.httpcomponents httpcore-nio 4.4.10 org.apache.httpcomponents httpclient 4.5.6 org.apache.httpcomponents httpasyncclient 4.1.4 com.aliyun.oss aliyun-sdk-oss 3.3.0 com.aliyun aliyun-java-sdk-sts 3.0.0 com.aliyun aliyun-java-sdk-core 4.2.0 com.aliyun aliyun-java-sdk-dysmsapi 1.1.0 com.aliyun.mns aliyun-sdk-mns 1.1.8.6 org.mapstruct mapstruct-jdk8 1.1.0.Final Releases http://maven.aliyun.com/nexus/content/groups/public/releases Snapshots http://maven.aliyun.com/nexus/content/groups/public/snapshots local local true dev dev online online test test test-ali test-ali ${project.artifactId}-${project.version} src/main/resources/${package.environment} *.* src/main/resources local/** dev/** test/** test-ali/** online/** org.springframework.boot spring-boot-maven-plugin true true true org.apache.maven.plugins maven-compiler-plugin 3.6.0 UTF-8 1.8 1.8 org.mapstruct mapstruct-processor 1.1.0.Final ================================================ FILE: abel-util/pom.xml ================================================ 4.0.0 cn.abel abel-util 1.0.0-SNAPSHOT jar cn.abel abel-parent 1.0.0-SNAPSHOT UTF-8 org.apache.commons commons-lang3 org.apache.commons commons-collections4 org.springframework spring-web 5.1.3.RELEASE org.springframework.boot spring-boot-starter-web 2.0.4.RELEASE com.fasterxml.jackson.core jackson-databind 2.9.8 com.alibaba fastjson javax.servlet javax.servlet-api 4.0.1 provided junit junit 4.12 test ================================================ FILE: abel-util/src/main/java/cn/abel/code/InfoCode.java ================================================ package cn.abel.code; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; /** * 返回响应 Created by liyunfeng */ public enum InfoCode { //系统错误从200~10000 SUCCESS(200, "OK"), TIME_OUT(300, "超时"), //业务相关从10000自增 // 10000开始 INVALID_REQUEST(10000, "不支持的请求方式"), //用户相关(20000自增) REQUEST_PARAM_ERROR(20000, "传入参数错误"), REGISTER_TYPE_ERROR(20001, "不支持的注册类型"), INVALID_SIGN(20002, "签名无效"), USER_LOGIN_EXIST(20003, "用户已存在"), USER_LOGIN_NOT_EXIST(20008, "用户不存在"), PASSWORD_ERROR(20009, "用户名或密码错误"), INVALID_TOKEN(20010, "无效token"), INVALID_LOGIN(20011, "登录失效,重新登录"), PASSWORD_SAME(20017, "密码重复"), OLD_PASSWORD_ERROR(20018, "密码错误,不能修改"), LOGIN_FAIL(20024, "登录失败"), VISITOR_REGISTER_FAIL(20025, "游客注册失败"), TOKEN_EXIST(20033, "token重复"), LOGIN_TYPE_EXIST(20034, "登录方式已存在"), USER_PROFILE_SEARCH_ERROR(20035, "用户查询失败"), USER_PROFILE_LOCK(20036, "用户已锁定"), ACCOUNT_SEARCH_FAIL(20037, "账号查询失败"), LOGIN_NAME_TYPE_ERROR(20038, "登录名不为空时,登录方式不能为空"), PASSWORD_SIMPLE_ERROR(20042, "密码错误,长度应为6-18,包含字母、数字和特殊字符"), PASSWORD_ERROR_MORE_THAN(20043,"用户名密码连续错误已达5次,请15分钟后再试"), LOGIN_TYPE_ERROR(20044, "不支持的登录类型"), SERVICE_UNAVAILABLE(50000, "操作失败,请重试"); private int status; private String msg; private InfoCode(int status, String msg) { this.status = status; this.msg = msg; } public int getStatus() { return status; } public String getMsg() { return msg; } @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } } ================================================ FILE: abel-util/src/main/java/cn/abel/exception/AppRuntimeException.java ================================================ package cn.abel.exception; import cn.abel.code.InfoCode; /** * 接口服务抛出的异常 * */ public class AppRuntimeException extends RuntimeException { private static final long serialVersionUID = 2963760410777899525L; private InfoCode infoCode; public AppRuntimeException() { infoCode = InfoCode.SERVICE_UNAVAILABLE; } public AppRuntimeException(InfoCode infoCode) { this.infoCode = infoCode; } public AppRuntimeException(InfoCode infoCode, String message) { super(message); this.infoCode = infoCode; } public InfoCode getInfoCode() { return infoCode; } } ================================================ FILE: abel-util/src/main/java/cn/abel/exception/HttpExeption.java ================================================ package cn.abel.exception; public class HttpExeption extends Exception { private static final long serialVersionUID = -4707210535385221192L; public HttpExeption() { } public HttpExeption(String msg) { super(msg); } public HttpExeption(String msg, Throwable e) { super(msg, e); } public HttpExeption(Throwable e) { super(e); } } ================================================ FILE: abel-util/src/main/java/cn/abel/exception/ServiceException.java ================================================ package cn.abel.exception; import cn.abel.code.*; /** * 服务异常类 * */ @SuppressWarnings("serial") public class ServiceException extends Exception { //默认的错误码 private int errorCode = 500; private String errorCodes; public ServiceException() { } public ServiceException(Throwable e) { super(e); } public ServiceException(int errorCode) { this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } public String getErrorCodes() { return errorCodes; } public ServiceException(InfoCode infoCode){ super(infoCode.getMsg()); this.errorCode = infoCode.getStatus(); } public ServiceException(int errorCode, String msg) { super(msg); this.errorCode = errorCode; } public ServiceException(String errorCode, String msg) { super(msg); this.errorCodes = errorCode; } public ServiceException(int errorCode, String msg, Throwable e) { super(msg, e); this.errorCode = errorCode; } public ServiceException(int errorCode, Throwable e) { super(e); this.errorCode = errorCode; } } ================================================ FILE: abel-util/src/main/java/cn/abel/response/ResponseEntity.java ================================================ package cn.abel.response; import cn.abel.code.*; import java.util.HashMap; /** * Created by guoshan on 2018/3/21. *

* 服务端返回给前端或客户端使用 */ public class ResponseEntity { int status = 200; String message = "ok"; Object data = new HashMap(); private ResponseEntity() { } public static ResponseEntity ok(Object data) { ResponseEntity ResponseEntity = new ResponseEntity(); ResponseEntity.setData(data); return ResponseEntity; } public static ResponseEntity error(InfoCode infoCode) { ResponseEntity ResponseEntity = new ResponseEntity(); ResponseEntity.setStatus(infoCode.getStatus()); ResponseEntity.setMessage(infoCode.getMsg()); return ResponseEntity; } public static ResponseEntity ok() { ResponseEntity ResponseEntity = new ResponseEntity(); return ResponseEntity; } public static ResponseEntity error(int code, String msg) { ResponseEntity ResponseEntity = new ResponseEntity(); ResponseEntity.setStatus(code); ResponseEntity.setMessage(msg); return ResponseEntity; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public Object getData() { return data == null ? new HashMap() : data; } public void setData(Object data) { this.data = data; } } ================================================ FILE: abel-util/src/main/java/cn/abel/utils/DateTimeUtils.java ================================================ package cn.abel.utils; import cn.abel.exception.ServiceException; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DateUtils; import java.text.ParseException; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; import java.util.Calendar; import java.util.Date; /** * 日期util。 */ public class DateTimeUtils { /** * 一分钟。 */ public static final int ONE_MINUTE = 60 * 1000; /** * 一小时。 */ public static final int ONE_HOUR = 60 * ONE_MINUTE; /** * 一天。 */ public static final int ONE_DAY = 24 * ONE_HOUR; public static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; private static final int ARG_ERROR_CODE = 400; private static final String ARG_ERROR = "输入的参数有误"; /** * 根据给定的格式将时间转为字符串。 * * @param dateTime * @param pattern * @return */ public static String format(Date dateTime, String pattern) { if (dateTime == null || pattern == null) { return StringUtils.EMPTY; } return DateFormatUtils.format(dateTime, pattern); } /** * 将时间转为默认格式的字符串。 * * @param dateTime * @return */ public static String format(Date dateTime) { return format(dateTime, DEFAULT_DATETIME_PATTERN); } /** * 根据给定的格式获取当前日期的字符串。 * * @param pattern * @return */ public static String formatCurrent(String pattern) { return format(new Date(), pattern); } /** * 获取当前日期的字符串。 * * @return */ public static String formatCurrent() { return format(new Date(), DEFAULT_DATE_PATTERN); } /** * 去除时间中的时分秒毫秒,只保留日期部分。 * * @param dateTime * @return */ public static Date removeTime(Date dateTime) { if (dateTime == null) { return null; } Calendar calendar = Calendar.getInstance(); calendar.setTime(dateTime); calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } /** * 获取明天的日期。 * * @return */ public static Date getTomorrowDate() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.add(Calendar.DATE, 1); return calendar.getTime(); } /** * 获取昨天的日期。 * * @return */ public static Date getYesterdayDate() { Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.add(Calendar.DATE, -1); return calendar.getTime(); } /** * 根据给定的格式将时间字符串转化成{@link Date}对象。 * * @param dateTimeStr * @param pattern * @return * @throws ServiceException */ public static Date parse(String dateTimeStr, String pattern) throws ServiceException { if (dateTimeStr == null || pattern == null) { return null; } try { return DateUtils.parseDate(dateTimeStr, pattern); } catch (ParseException e) { throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); } } /** * 将时间字符串根据默认格式转换成{@link Date}对象。 * * @param dateTimeStr * @return * @throws ServiceException */ public static Date parse(String dateTimeStr) throws ServiceException { return parse(dateTimeStr, DEFAULT_DATETIME_PATTERN); } /** * 获取日期中的月份。 * * @param date * @return */ public static int getMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.MONTH) + 1; } /** * 获取日期中的年份。 * * @param date * @return */ public static int getYear(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); return calendar.get(Calendar.YEAR); } /** * 增加日期。 * * @param date * @param days * @return * @throws ServiceException */ public static Date dateAdd(Date date, int days) throws ServiceException { if (date == null) { throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DATE, days); return calendar.getTime(); } /** * 增加月份。 * * @param date * @param months * @return * @throws ServiceException */ public static Date monthAdd(Date date, int months) throws ServiceException { if (date == null) { throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.MONTH, months); return calendar.getTime(); } /** * 获取两个日期之间的差值。 * * @param one * @param two * @return * @throws ServiceException */ public static int dateDiff(Date one, Date two) throws ServiceException { if (one == null || two == null) { throw new ServiceException(ARG_ERROR_CODE, ARG_ERROR); } long diff = Math.abs((one.getTime() - two.getTime()) / (1000 * 3600 * 24)); return new Long(diff).intValue(); } /** * 计算几天前的时间 * * @param date 当前时间 * @param day 几天前 * @return */ public static Date getDateBefore(Date date, int day) { Calendar now = Calendar.getInstance(); now.setTime(date); now.set(Calendar.DATE, now.get(Calendar.DATE) - day); return now.getTime(); } /** * 获取当前月第一天 * * @return Date * @throws ParseException */ public static Date getFirstAndLastOfMonth() { LocalDate today = LocalDate.now(); LocalDate firstDay = LocalDate.of(today.getYear(),today.getMonth(),1); ZoneId zone = ZoneId.systemDefault(); Instant instant = firstDay.atStartOfDay().atZone(zone).toInstant(); return Date.from(instant); } /** * 获取当前周第一天 * * @return Date * @throws ParseException */ public static Date getWeekFirstDate(){ Calendar cal = Calendar.getInstance(); cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); Date date = cal.getTime(); return date; } } ================================================ FILE: springWebSocket/pom.xml ================================================ 4.0.0 com.us.example springWebSocket 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.example.Application 1.8 1.8 org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket org.springframework.boot spring-boot-starter-security org.apache.maven.plugins maven-shade-plugin 2.3 package shade ================================================ FILE: springWebSocket/src/main/java/com/us/example/Application.java ================================================ package com.us.example; /** * Created by yangyibo on 16/12/29. */ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import static org.springframework.boot.SpringApplication.run; @ComponentScan(basePackages ="com.us.example") @SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/bean/Message.java ================================================ package com.us.example.bean; /** * Created by yangyibo on 16/12/29. * 浏览器向服务器发送的消息使用此类接受 */ public class Message { private String name; public String getName(){ return name; } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/bean/Response.java ================================================ package com.us.example.bean; /** * Created by yangyibo on 16/12/29. * 服务器向浏览器发送的此类消息。 */ public class Response { public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } private String responseMessage; public Response(String responseMessage){ this.responseMessage = responseMessage; } public String getResponseMessage(){ return responseMessage; } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/config/WebSecurityConfig.java ================================================ package com.us.example.config; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/","/login").permitAll()//根路径和/login路径不拦截 .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") //2登陆页面路径为/login .defaultSuccessUrl("/chat") //3登陆成功转向chat页面 .permitAll() .and() .logout() .permitAll(); } //4在内存中配置两个用户 wyf 和 wisely ,密码和用户名一致,角色是 USER @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin").password("admin").roles("USER") .and() .withUser("abel").password("abel").roles("USER"); } //5忽略静态资源的拦截 @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/resources/static/**"); } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/config/WebSocketConfig.java ================================================ package com.us.example.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; /** * Created by yangyibo on 16/12/29. */ @Configuration @EnableWebSocketMessageBroker //通过EnableWebSocketMessageBroker 开启使用STOMP协议来传输基于代理(message broker)的消息,此时浏览器支持使用@MessageMapping 就像支持@RequestMapping一样。 public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //endPoint 注册协议节点,并映射指定的URl //注册一个Stomp 协议的endpoint,并指定 SockJS协议 registry.addEndpoint("/endpointWisely").withSockJS(); //注册一个名字为"endpointChat" 的endpoint,并指定 SockJS协议。 点对点-用 registry.addEndpoint("/endpointChat").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(message broker) //广播式应配置一个/topic 消息代理 registry.enableSimpleBroker("/topic"); //点对点式增加一个/queue 消息代理 registry.enableSimpleBroker("/queue","/topic"); } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/controller/WebSocketController.java ================================================ package com.us.example.controller; import com.us.example.bean.Message; import com.us.example.bean.Response; import com.us.example.service.WebSocketService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.security.Principal; /** * Created by yangyibo on 16/12/29. * */ @CrossOrigin @Controller public class WebSocketController { @Autowired private WebSocketService ws; @Autowired private SimpMessagingTemplate messagingTemplate; @RequestMapping(value = "/login") public String login(){ return "login"; } @RequestMapping(value = "/ws") public String ws(){ return "ws"; } @RequestMapping(value = "/chat") public String chat(){ return "chat"; } //http://localhost:8080/ws @MessageMapping("/welcome")//浏览器发送请求通过@messageMapping 映射/welcome 这个地址。 @SendTo("/topic/getResponse")//服务器端有消息时,会订阅@SendTo 中的路径的浏览器发送消息。 public Response say(Message message) throws Exception { Thread.sleep(1000); return new Response("Welcome, " + message.getName() + "!"); } //http://localhost:8080/Welcome1 @RequestMapping("/Welcome1") @ResponseBody public String say2()throws Exception { ws.sendMessage(); return "is ok"; } @MessageMapping("/chat") //在springmvc 中可以直接获得principal,principal 中包含当前用户的信息 public void handleChat(Principal principal, Message message) { /** * 此处是一段硬编码。如果发送人是wyf 则发送给 wisely 如果发送人是wisely 就发送给 wyf。 * 通过当前用户,然后查找消息,如果查找到未读消息,则发送给当前用户。 */ if (principal.getName().equals("admin")) { //通过convertAndSendToUser 向用户发送信息, // 第一个参数是接收消息的用户,第二个参数是浏览器订阅的地址,第三个参数是消息本身 messagingTemplate.convertAndSendToUser("abel", "/queue/notifications", principal.getName() + "-send:" + message.getName()); /** * 72 行操作相等于 * messagingTemplate.convertAndSend("/user/abel/queue/notifications",principal.getName() + "-send:" + message.getName()); */ } else { messagingTemplate.convertAndSendToUser("admin", "/queue/notifications", principal.getName() + "-send:" + message.getName()); } } } ================================================ FILE: springWebSocket/src/main/java/com/us/example/service/WebSocketService.java ================================================ package com.us.example.service; /** * Created by yangyibo on 17/1/12. */ import com.us.example.bean.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Service; @Service public class WebSocketService { @Autowired //使用SimpMessagingTemplate 向浏览器发送消息 private SimpMessagingTemplate template; public void sendMessage() throws Exception{ for(int i=0;i<10;i++) { Thread.sleep(1000); template.convertAndSend("/topic/getResponse",new Response("Welcome,yangyibo !"+i)); System.out.println("----------------------yangyibo"+i); } } } ================================================ FILE: springWebSocket/src/main/resources/application.properties ================================================ server.port=8090 ================================================ FILE: springWebSocket/src/main/resources/static/jquery.js ================================================ /*! * jQuery JavaScript Library v1.6.1 * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Thu May 12 15:04:36 2011 -0400 */ (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document, navigator = window.navigator, location = window.location; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // (both of which we optimize for) quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace trimLeft = /^\s+/, trimRight = /\s+$/, // Check for digits rdigit = /\d/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, // Useragent RegExp rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // The deferred used on DOM ready readyList, // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf, // [[Class]] -> type pairs class2type = {}; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = (context ? context.ownerDocument || context : document); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if (selector.selector !== undefined) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.6.1", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + (this.selector ? " " : "") + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // Add the callback readyList.done( fn ); return this; }, eq: function( i ) { return i === -1 ? this.slice( i ) : this.slice( i, +i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).unbind( "ready" ); } } }, bindReady: function() { if ( readyList ) { return; } readyList = jQuery._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, // A crude way of determining if an object is a window isWindow: function( obj ) { return obj && typeof obj === "object" && "setInterval" in obj; }, isNaN: function( obj ) { return obj == null || !rdigit.test( obj ) || isNaN( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw msg; }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return (new Function( "return " + data ))(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing // (xml & tmp used internally) parseXML: function( data , xml , tmp ) { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } tmp = xml.documentElement; if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // The extra typeof function check is to prevent crashes // in Safari 2 (See: #3039) // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array ) { if ( indexOf ) { return indexOf.call( array, elem ); } for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Mutifunctional method to get and set values to a collection // The value/s can be optionally by executed if its a function access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute return length ? fn( elems[0], key ) : undefined; }, now: function() { return (new Date()).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {} }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } // IE doesn't match non-breaking spaces with \s if ( rnotwhite.test( "\xA0" ) ) { trimLeft = /^[\s\xA0]+/; trimRight = /[\s\xA0]+$/; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } // Expose jQuery to the global object return jQuery; })(); var // Promise methods promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), // Static reference to slice sliceDeferred = [].slice; jQuery.extend({ // Create a simple deferred (one callbacks list) _Deferred: function() { var // callbacks list callbacks = [], // stored [ context , args ] fired, // to avoid firing when already doing so firing, // flag to know if the deferred has been cancelled cancelled, // the deferred itself deferred = { // done( f1, f2, ...) done: function() { if ( !cancelled ) { var args = arguments, i, length, elem, type, _fired; if ( fired ) { _fired = fired; fired = 0; } for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { deferred.done.apply( deferred, elem ); } else if ( type === "function" ) { callbacks.push( elem ); } } if ( _fired ) { deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); } } return this; }, // resolve with given context and args resolveWith: function( context, args ) { if ( !cancelled && !fired && !firing ) { // make sure args are available (#8421) args = args || []; firing = 1; try { while( callbacks[ 0 ] ) { callbacks.shift().apply( context, args ); } } finally { fired = [ context, args ]; firing = 0; } } return this; }, // resolve with this as context and given arguments resolve: function() { deferred.resolveWith( this, arguments ); return this; }, // Has this deferred been resolved? isResolved: function() { return !!( firing || fired ); }, // Cancel cancel: function() { cancelled = 1; callbacks = []; return this; } }; return deferred; }, // Full fledged deferred (two callbacks list) Deferred: function( func ) { var deferred = jQuery._Deferred(), failDeferred = jQuery._Deferred(), promise; // Add errorDeferred methods, then and promise jQuery.extend( deferred, { then: function( doneCallbacks, failCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ); return this; }, always: function() { return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); }, fail: failDeferred.done, rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, pipe: function( fnDone, fnFail ) { return jQuery.Deferred(function( newDefer ) { jQuery.each( { done: [ fnDone, "resolve" ], fail: [ fnFail, "reject" ] }, function( handler, data ) { var fn = data[ 0 ], action = data[ 1 ], returned; if ( jQuery.isFunction( fn ) ) { deferred[ handler ](function() { returned = fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise().then( newDefer.resolve, newDefer.reject ); } else { newDefer[ action ]( returned ); } }); } else { deferred[ handler ]( newDefer[ action ] ); } }); }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { if ( obj == null ) { if ( promise ) { return promise; } promise = obj = {}; } var i = promiseMethods.length; while( i-- ) { obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; } return obj; } }); // Make sure only one callback list will be used deferred.done( failDeferred.cancel ).fail( deferred.cancel ); // Unexpose cancel delete deferred.cancel; // Call given func if any if ( func ) { func.call( deferred, deferred ); } return deferred; }, // Deferred helper when: function( firstParam ) { var args = arguments, i = 0, length = args.length, count = length, deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? firstParam : jQuery.Deferred(); function resolveFunc( i ) { return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { // Strange bug in FF4: // Values changed onto the arguments object sometimes end up as undefined values // outside the $.when method. Cloning the object into a fresh array solves the issue deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); } }; } if ( length > 1 ) { for( ; i < length; i++ ) { if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { args[ i ].promise().then( resolveFunc(i), deferred.reject ); } else { --count; } } if ( !count ) { deferred.resolveWith( deferred, args ); } } else if ( deferred !== firstParam ) { deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); } return deferred.promise(); } }); jQuery.support = (function() { var div = document.createElement( "div" ), documentElement = document.documentElement, all, a, select, opt, input, marginDiv, support, fragment, body, bodyStyle, tds, events, eventName, i, isSupported; // Preliminary tests div.setAttribute("className", "t"); div.innerHTML = "
a"; all = div.getElementsByTagName( "*" ); a = div.getElementsByTagName( "a" )[ 0 ]; // Can't get basic test support if ( !all || !all.length || !a ) { return {}; } // First batch of supports tests select = document.createElement( "select" ); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName( "input" )[ 0 ]; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName( "tbody" ).length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName( "link" ).length, // Get the style information from getAttribute // (IE uses .cssText instead) style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55$/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: ( input.value === "on" ), // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", // Will be defined later submitBubbles: true, changeBubbles: true, focusinBubbles: false, deleteExpando: true, noCloneEvent: true, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, reliableMarginRight: true }; // Make sure checked status is properly cloned input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Test to see if it's possible to delete an expando from an element // Fails in Internet Explorer try { delete div.test; } catch( e ) { support.deleteExpando = false; } if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { div.attachEvent( "onclick", function click() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) support.noCloneEvent = false; div.detachEvent( "onclick", click ); }); div.cloneNode( true ).fireEvent( "onclick" ); } // Check if a radio maintains it's value // after being appended to the DOM input = document.createElement("input"); input.value = "t"; input.setAttribute("type", "radio"); support.radioValue = input.value === "t"; input.setAttribute("checked", "checked"); div.appendChild( input ); fragment = document.createDocumentFragment(); fragment.appendChild( div.firstChild ); // WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; div.innerHTML = ""; // Figure out if the W3C box model works as expected div.style.width = div.style.paddingLeft = "1px"; // We use our own, invisible, body body = document.createElement( "body" ); bodyStyle = { visibility: "hidden", width: 0, height: 0, border: 0, margin: 0, // Set background to avoid IE crashes when removing (#9028) background: "none" }; for ( i in bodyStyle ) { body.style[ i ] = bodyStyle[ i ]; } body.appendChild( div ); documentElement.insertBefore( body, documentElement.firstChild ); // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; support.boxModel = div.offsetWidth === 2; if ( "zoom" in div.style ) { // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout // (IE < 8 does this) div.style.display = "inline"; div.style.zoom = 1; support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); // Check if elements with layout shrink-wrap their children // (IE 6 does this) div.style.display = ""; div.innerHTML = "

"; support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); } div.innerHTML = "
t
"; tds = div.getElementsByTagName( "td" ); // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). // (only IE 8 fails this test) isSupported = ( tds[ 0 ].offsetHeight === 0 ); tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; // Check if empty table cells still have offsetWidth/Height // (IE < 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); div.innerHTML = ""; // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. For more // info see bug #3333 // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right if ( document.defaultView && document.defaultView.getComputedStyle ) { marginDiv = document.createElement( "div" ); marginDiv.style.width = "0"; marginDiv.style.marginRight = "0"; div.appendChild( marginDiv ); support.reliableMarginRight = ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; } // Remove the body element we added body.innerHTML = ""; documentElement.removeChild( body ); // Technique from Juriy Zaytsev // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ // We only care about the case where non-standard event systems // are used, namely in IE. Short-circuiting here helps us to // avoid an eval call (in setAttribute) which can cause CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP if ( div.attachEvent ) { for( i in { submit: 1, change: 1, focusin: 1 } ) { eventName = "on" + i; isSupported = ( eventName in div ); if ( !isSupported ) { div.setAttribute( eventName, "return;" ); isSupported = ( typeof div[ eventName ] === "function" ); } support[ i + "Bubbles" ] = isSupported; } } return support; })(); // Keep track of boxModel jQuery.boxModel = jQuery.support.boxModel; var rbrace = /^(?:\{.*\}|\[.*\])$/, rmultiDash = /([a-z])([A-Z])/g; jQuery.extend({ cache: {}, // Please use with caution uuid: 0, // Unique for each copy of jQuery on the page // Non-digits removed to match rinlinejQuery expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, // Ban all objects except for Flash (which handle expandos) "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { elem[ jQuery.expando ] = id = ++jQuery.uuid; } else { id = jQuery.expando; } } if ( !cache[ id ] ) { cache[ id ] = {}; // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery // metadata on plain JS objects when the object is serialized using // JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); } else { cache[ id ] = jQuery.extend(cache[ id ], name); } } thisCache = cache[ id ]; // Internal jQuery data is stored in a separate object inside the object's data // cache in order to avoid key collisions between internal data and user-defined // data if ( pvt ) { if ( !thisCache[ internalKey ] ) { thisCache[ internalKey ] = {}; } thisCache = thisCache[ internalKey ]; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should // not attempt to inspect the internal events object using jQuery.data, as this // internal data object is undocumented and subject to change. if ( name === "events" && !thisCache[name] ) { return thisCache[ internalKey ] && thisCache[ internalKey ].events; } return getByName ? thisCache[ jQuery.camelCase( name ) ] : thisCache; }, removeData: function( elem, name, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var internalKey = jQuery.expando, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, // See jQuery.data for more information id = isNode ? elem[ jQuery.expando ] : jQuery.expando; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; if ( thisCache ) { delete thisCache[ name ]; // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( !isEmptyDataObject(thisCache) ) { return; } } } // See jQuery.data for more information if ( pvt ) { delete cache[ id ][ internalKey ]; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject(cache[ id ]) ) { return; } } var internalCache = cache[ id ][ internalKey ]; // Browsers that fail expando deletion also refuse to delete expandos on // the window, but it will allow it on all other JS objects; other browsers // don't care if ( jQuery.support.deleteExpando || cache != window ) { delete cache[ id ]; } else { cache[ id ] = null; } // We destroyed the entire user cache at once because it's faster than // iterating through each key, but we need to continue to persist internal // data if it existed if ( internalCache ) { cache[ id ] = {}; // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery // metadata on plain JS objects when the object is serialized using // JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } cache[ id ][ internalKey ] = internalCache; // Otherwise, we need to eliminate the expando on the node to avoid // false lookups in the cache for entries that no longer exist } else if ( isNode ) { // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( jQuery.support.deleteExpando ) { delete elem[ jQuery.expando ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( jQuery.expando ); } else { elem[ jQuery.expando ] = null; } } }, // For internal use only. _data: function( elem, name, data ) { return jQuery.data( elem, name, data, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { if ( elem.nodeName ) { var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; if ( match ) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); jQuery.fn.extend({ data: function( key, value ) { var data = null; if ( typeof key === "undefined" ) { if ( this.length ) { data = jQuery.data( this[0] ); if ( this[0].nodeType === 1 ) { var attr = this[0].attributes, name; for ( var i = 0, l = attr.length; i < l; i++ ) { name = attr[i].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( this[0], name, data[ name ] ); } } } } return data; } else if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } var parts = key.split("."); parts[1] = parts[1] ? "." + parts[1] : ""; if ( value === undefined ) { data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); // Try to fetch any internally stored data first if ( data === undefined && this.length ) { data = jQuery.data( this[0], key ); data = dataAttr( this[0], key, data ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } else { return this.each(function() { var $this = jQuery( this ), args = [ parts[0], value ]; $this.triggerHandler( "setData" + parts[1] + "!", args ); jQuery.data( this, key, value ); $this.triggerHandler( "changeData" + parts[1] + "!", args ); }); } }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : !jQuery.isNaN( data ) ? parseFloat( data ) : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON // property to be considered empty objects; this property always exists in // order to make sure JSON.stringify does not expose internal metadata function isEmptyDataObject( obj ) { for ( var name in obj ) { if ( name !== "toJSON" ) { return false; } } return true; } function handleQueueMarkDefer( elem, type, src ) { var deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", defer = jQuery.data( elem, deferDataKey, undefined, true ); if ( defer && ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { // Give room for hard-coded callbacks to fire first // and eventually mark/queue something else on the element setTimeout( function() { if ( !jQuery.data( elem, queueDataKey, undefined, true ) && !jQuery.data( elem, markDataKey, undefined, true ) ) { jQuery.removeData( elem, deferDataKey, true ); defer.resolve(); } }, 0 ); } } jQuery.extend({ _mark: function( elem, type ) { if ( elem ) { type = (type || "fx") + "mark"; jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); } }, _unmark: function( force, elem, type ) { if ( force !== true ) { type = elem; elem = force; force = false; } if ( elem ) { type = type || "fx"; var key = type + "mark", count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); if ( count ) { jQuery.data( elem, key, count, true ); } else { jQuery.removeData( elem, key, true ); handleQueueMarkDefer( elem, type, "mark" ); } } }, queue: function( elem, type, data ) { if ( elem ) { type = (type || "fx") + "queue"; var q = jQuery.data( elem, type, undefined, true ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !q || jQuery.isArray(data) ) { q = jQuery.data( elem, type, jQuery.makeArray(data), true ); } else { q.push( data ); } } return q || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(), defer; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift("inprogress"); } fn.call(elem, function() { jQuery.dequeue(elem, type); }); } if ( !queue.length ) { jQuery.removeData( elem, type + "queue", true ); handleQueueMarkDefer( elem, type, "queue" ); } } }); jQuery.fn.extend({ queue: function( type, data ) { if ( typeof type !== "string" ) { data = type; type = "fx"; } if ( data === undefined ) { return jQuery.queue( this[0], type ); } return this.each(function() { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; type = type || "fx"; return this.queue( type, function() { var elem = this; setTimeout(function() { jQuery.dequeue( elem, type ); }, time ); }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, object ) { if ( typeof type !== "string" ) { object = type; type = undefined; } type = type || "fx"; var defer = jQuery.Deferred(), elements = this, i = elements.length, count = 1, deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", tmp; function resolve() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } } while( i-- ) { if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { count++; tmp.done( resolve ); } } resolve(); return defer.promise(); } }); var rclass = /[\n\t\r]/g, rspace = /\s+/, rreturn = /\r/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, rinvalidChar = /\:/, formHook, boolHook; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.attr ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, name, value, true, jQuery.prop ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); }, addClass: function( value ) { if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); self.addClass( value.call(this, i, self.attr("class") || "") ); }); } if ( value && typeof value === "string" ) { var classNames = (value || "").split( rspace ); for ( var i = 0, l = this.length; i < l; i++ ) { var elem = this[i]; if ( elem.nodeType === 1 ) { if ( !elem.className ) { elem.className = value; } else { var className = " " + elem.className + " ", setClass = elem.className; for ( var c = 0, cl = classNames.length; c < cl; c++ ) { if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { setClass += " " + classNames[c]; } } elem.className = jQuery.trim( setClass ); } } } } return this; }, removeClass: function( value ) { if ( jQuery.isFunction(value) ) { return this.each(function(i) { var self = jQuery(this); self.removeClass( value.call(this, i, self.attr("class")) ); }); } if ( (value && typeof value === "string") || value === undefined ) { var classNames = (value || "").split( rspace ); for ( var i = 0, l = this.length; i < l; i++ ) { var elem = this[i]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { var className = (" " + elem.className + " ").replace(rclass, " "); for ( var c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[c] + " ", " "); } elem.className = jQuery.trim( className ); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function(i) { var self = jQuery(this); self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " "; for ( var i = 0, l = this.length; i < l; i++ ) { if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } return (elem.value || "").replace(rreturn, ""); } return undefined; } var isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var self = jQuery(this), val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { var option = options[ i ]; // Don't return options that are disabled or in a disabled optgroup if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } // Fixes Bug #2551 -- select.val() broken in IE after form.reset() if ( one && !values.length && options.length ) { return jQuery( options[ index ] ).val(); } return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); jQuery(elem).find("option").each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { elem.selectedIndex = -1; } return values; } } }, attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attrFix: { // Always normalize to ensure hook usage tabindex: "tabIndex" }, attr: function( elem, name, value, pass ) { var nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( !("getAttribute" in elem) ) { return jQuery.prop( elem, name, value ); } var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // Normalize the name if needed name = notxml && jQuery.attrFix[ name ] || name; hooks = jQuery.attrHooks[ name ]; if ( !hooks ) { // Use boolHook for boolean attributes if ( rboolean.test( name ) && (typeof value === "boolean" || value === undefined || value.toLowerCase() === name.toLowerCase()) ) { hooks = boolHook; // Use formHook for forms and if the name contains certain characters } else if ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { hooks = formHook; } } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return undefined; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, "" + value ); return value; } } else if ( hooks && "get" in hooks && notxml ) { return hooks.get( elem, name ); } else { ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, name ) { var propName; if ( elem.nodeType === 1 ) { name = jQuery.attrFix[ name ] || name; if ( jQuery.support.getSetAttribute ) { // Use removeAttribute in browsers that support it elem.removeAttribute( name ); } else { jQuery.attr( elem, name, "" ); elem.removeAttributeNode( elem.getAttributeNode( name ) ); } // Set corresponding property to false for boolean attributes if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { elem[ propName ] = false; } } }, attrHooks: { type: { set: function( elem, value ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } }, tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ var attributeNode = elem.getAttributeNode("tabIndex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function( elem, name, value ) { var nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return undefined; } var ret, hooks, notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // Try to normalize/fix the name name = notxml && jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { return (elem[ name ] = value); } } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { return ret; } else { return elem[ name ]; } } }, propHooks: {} }); // Hook for boolean attributes boolHook = { get: function( elem, name ) { // Align boolean attributes with corresponding properties return elem[ jQuery.propFix[ name ] || name ] ? name.toLowerCase() : undefined; }, set: function( elem, value, name ) { var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { // value is true since we know at this point it's type boolean and not false // Set boolean attributes to the same name and set the DOM property propName = jQuery.propFix[ name ] || name; if ( propName in elem ) { // Only set the IDL specifically if it already exists on the element elem[ propName ] = value; } elem.setAttribute( name, name.toLowerCase() ); } return name; } }; // Use the value property for back compat // Use the formHook for button elements in IE6/7 (#1954) jQuery.attrHooks.value = { get: function( elem, name ) { if ( formHook && jQuery.nodeName( elem, "button" ) ) { return formHook.get( elem, name ); } return elem.value; }, set: function( elem, value, name ) { if ( formHook && jQuery.nodeName( elem, "button" ) ) { return formHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; } }; // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !jQuery.support.getSetAttribute ) { // propFix is more comprehensive and contains all fixes jQuery.attrFix = jQuery.propFix; // Use this for any attribute on a form in IE6/7 formHook = jQuery.attrHooks.name = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); // Return undefined if nodeValue is empty string return ret && ret.nodeValue !== "" ? ret.nodeValue : undefined; }, set: function( elem, value, name ) { // Check form objects in IE (multiple bugs related) // Only use nodeValue if the attribute node exists on the form var ret = elem.getAttributeNode( name ); if ( ret ) { ret.nodeValue = value; return value; } } }; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }); }); } // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { var ret = elem.getAttribute( name, 2 ); return ret === null ? undefined : ret; } }); }); } if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Normalize to lowercase since IE uppercases css property names return elem.style.cssText.toLowerCase() || undefined; }, set: function( elem, value ) { return (elem.style.cssText = "" + value); } }; } // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } } }); } // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { get: function( elem ) { // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; } }; }); } jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); } } }); }); var hasOwn = Object.prototype.hasOwnProperty, rnamespaces = /\.(.*)$/, rformElems = /^(?:textarea|input|select)$/i, rperiod = /\./g, rspaces = / /g, rescape = /[^\w\s.|`]/g, fcleanup = function( nm ) { return nm.replace(rescape, "\\$&"); }; /* * A number of helper functions used for managing events. * Many of the ideas behind this code originated from * Dean Edwards' addEvent library. */ jQuery.event = { // Bind an event to an element // Original by Dean Edwards add: function( elem, types, handler, data ) { if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } if ( handler === false ) { handler = returnFalse; } else if ( !handler ) { // Fixes bug #7229. Fix recommended by jdalton return; } var handleObjIn, handleObj; if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; } // Make sure that the function being executed has a unique ID if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure var elemData = jQuery._data( elem ); // If no elemData is found then we must be trying to bind to one of the // banned noData elements if ( !elemData ) { return; } var events = elemData.events, eventHandle = elemData.handle; if ( !events ) { elemData.events = events = {}; } if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.handle.apply( eventHandle.elem, arguments ) : undefined; }; } // Add elem as a property of the handle function // This is to prevent a memory leak with non-native events in IE. eventHandle.elem = elem; // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = types.split(" "); var type, i = 0, namespaces; while ( (type = types[ i++ ]) ) { handleObj = handleObjIn ? jQuery.extend({}, handleObjIn) : { handler: handler, data: data }; // Namespaced event handlers if ( type.indexOf(".") > -1 ) { namespaces = type.split("."); type = namespaces.shift(); handleObj.namespace = namespaces.slice(0).sort().join("."); } else { namespaces = []; handleObj.namespace = ""; } handleObj.type = type; if ( !handleObj.guid ) { handleObj.guid = handler.guid; } // Get the current list of functions bound to this event var handlers = events[ type ], special = jQuery.event.special[ type ] || {}; // Init the event handler queue if ( !handlers ) { handlers = events[ type ] = []; // Check for a special event handler // Only use addEventListener/attachEvent if the special // events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add the function to the element's handler list handlers.push( handleObj ); // Keep track of which events have been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler, pos ) { // don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } if ( handler === false ) { handler = returnFalse; } var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, elemData = jQuery.hasData( elem ) && jQuery._data( elem ), events = elemData && elemData.events; if ( !elemData || !events ) { return; } // types is actually an event object here if ( types && types.type ) { handler = types.handler; types = types.type; } // Unbind all events for the element if ( !types || typeof types === "string" && types.charAt(0) === "." ) { types = types || ""; for ( type in events ) { jQuery.event.remove( elem, type + types ); } return; } // Handle multiple events separated by a space // jQuery(...).unbind("mouseover mouseout", fn); types = types.split(" "); while ( (type = types[ i++ ]) ) { origType = type; handleObj = null; all = type.indexOf(".") < 0; namespaces = []; if ( !all ) { // Namespaced event handlers namespaces = type.split("."); type = namespaces.shift(); namespace = new RegExp("(^|\\.)" + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); } eventType = events[ type ]; if ( !eventType ) { continue; } if ( !handler ) { for ( j = 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( all || namespace.test( handleObj.namespace ) ) { jQuery.event.remove( elem, origType, handleObj.handler, j ); eventType.splice( j--, 1 ); } } continue; } special = jQuery.event.special[ type ] || {}; for ( j = pos || 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( handler.guid === handleObj.guid ) { // remove the given handler for the given type if ( all || namespace.test( handleObj.namespace ) ) { if ( pos == null ) { eventType.splice( j--, 1 ); } if ( special.remove ) { special.remove.call( elem, handleObj ); } } if ( pos != null ) { break; } } } // remove generic event handler if no more handlers exist if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } ret = null; delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { var handle = elemData.handle; if ( handle ) { handle.elem = null; } delete elemData.events; delete elemData.handle; if ( jQuery.isEmptyObject( elemData ) ) { jQuery.removeData( elem, undefined, true ); } } }, // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { "getData": true, "setData": true, "changeData": true }, trigger: function( event, data, elem, onlyHandlers ) { // Event object or event type var type = event.type || event, namespaces = [], exclusive; if ( type.indexOf("!") >= 0 ) { // Exclusive events trigger only for the exact event (no namespaces) type = type.slice(0, -1); exclusive = true; } if ( type.indexOf(".") >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object event[ jQuery.expando ] ? event : // Object literal new jQuery.Event( type, event ) : // Just the event type (string) new jQuery.Event( type ); event.type = type; event.exclusive = exclusive; event.namespace = namespaces.join("."); event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); // triggerHandler() and global events don't bubble or run the default action if ( onlyHandlers || !elem ) { event.preventDefault(); event.stopPropagation(); } // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document jQuery.each( jQuery.cache, function() { // internalKey variable is just used to make it easier to find // and potentially change this stuff later; currently it just // points to jQuery.expando var internalKey = jQuery.expando, internalCache = this[ internalKey ]; if ( internalCache && internalCache.events && internalCache.events[ type ] ) { jQuery.event.trigger( event, data, internalCache.handle.elem ); } }); return; } // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) { return; } // Clean up the event in case it is being reused event.result = undefined; event.target = elem; // Clone any incoming data and prepend the event, creating the handler arg list data = data ? jQuery.makeArray( data ) : []; data.unshift( event ); var cur = elem, // IE doesn't like method names with a colon (#3533, #8272) ontype = type.indexOf(":") < 0 ? "on" + type : ""; // Fire event on the current element, then bubble up the DOM tree do { var handle = jQuery._data( cur, "handle" ); event.currentTarget = cur; if ( handle ) { handle.apply( cur, data ); } // Trigger an inline bound script if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { event.result = false; event.preventDefault(); } // Bubble up to document, then to window cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; } while ( cur && !event.isPropagationStopped() ); // If nobody prevented the default action, do it now if ( !event.isDefaultPrevented() ) { var old, special = jQuery.event.special[ type ] || {}; if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction)() check here because IE6/7 fails that test. // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. try { if ( ontype && elem[ type ] ) { // Don't re-trigger an onFOO event when we call its FOO() method old = elem[ ontype ]; if ( old ) { elem[ ontype ] = null; } jQuery.event.triggered = type; elem[ type ](); } } catch ( ieError ) {} if ( old ) { elem[ ontype ] = old; } jQuery.event.triggered = undefined; } } return event.result; }, handle: function( event ) { event = jQuery.event.fix( event || window.event ); // Snapshot the handlers list since a called handler may add/remove events. var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), run_all = !event.exclusive && !event.namespace, args = Array.prototype.slice.call( arguments, 0 ); // Use the fix-ed Event rather than the (read-only) native event args[0] = event; event.currentTarget = this; for ( var j = 0, l = handlers.length; j < l; j++ ) { var handleObj = handlers[ j ]; // Triggered event must 1) be non-exclusive and have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event. if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { // Pass in a reference to the handler function itself // So that we can later remove it event.handler = handleObj.handler; event.data = handleObj.data; event.handleObj = handleObj; var ret = handleObj.handler.apply( this, args ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } if ( event.isImmediatePropagationStopped() ) { break; } } } return event.result; }, props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // store a copy of the original event object // and "clone" to set read-only properties var originalEvent = event; event = jQuery.Event( originalEvent ); for ( var i = this.props.length, prop; i; ) { prop = this.props[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary if ( !event.target ) { // Fixes #1925 where srcElement might not be defined either event.target = event.srcElement || document; } // check if target is a textnode (safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // Add relatedTarget, if necessary if ( !event.relatedTarget && event.fromElement ) { event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; } // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && event.clientX != null ) { var eventDocument = event.target.ownerDocument || document, doc = eventDocument.documentElement, body = eventDocument.body; event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); } // Add which for key events if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { event.which = event.charCode != null ? event.charCode : event.keyCode; } // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) if ( !event.metaKey && event.ctrlKey ) { event.metaKey = event.ctrlKey; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && event.button !== undefined ) { event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); } return event; }, // Deprecated, use jQuery.guid instead guid: 1E8, // Deprecated, use jQuery.proxy instead proxy: jQuery.proxy, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady, teardown: jQuery.noop }, live: { add: function( handleObj ) { jQuery.event.add( this, liveConvert( handleObj.origType, handleObj.selector ), jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); }, remove: function( handleObj ) { jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); } }, beforeunload: { setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( jQuery.isWindow( this ) ) { this.onbeforeunload = eventHandle; } }, teardown: function( namespaces, eventHandle ) { if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } } } }; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { if ( elem.detachEvent ) { elem.detachEvent( "on" + type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !this.preventDefault ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // timeStamp is buggy for some events on Firefox(#3843) // So we won't rely on the native value this.timeStamp = jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); // otherwise set the returnValue property of the original event to false (IE) } else { e.returnValue = false; } }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Checks if an event happened on an element within another element // Used in jQuery.event.special.mouseenter and mouseleave handlers var withinElement = function( event ) { // Check if mouse(over|out) are still within the same parent element var parent = event.relatedTarget; // set the correct event type event.type = event.data; // Firefox sometimes assigns relatedTarget a XUL element // which we cannot access the parentNode property of try { // Chrome does something similar, the parentNode property // can be accessed but is null. if ( parent && parent !== document && !parent.parentNode ) { return; } // Traverse up the tree while ( parent && parent !== this ) { parent = parent.parentNode; } if ( parent !== this ) { // handle event if we actually just moused on to a non sub-element jQuery.event.handle.apply( this, arguments ); } // assuming we've left the element since we most likely mousedover a xul element } catch(e) { } }, // In case of event delegation, we only need to rename the event.type, // liveHandler will take care of the rest. delegate = function( event ) { event.type = event.data; jQuery.event.handle.apply( this, arguments ); }; // Create mouseenter and mouseleave events jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { setup: function( data ) { jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); }, teardown: function( data ) { jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); } }; }); // submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function( data, namespaces ) { if ( !jQuery.nodeName( this, "form" ) ) { jQuery.event.add(this, "click.specialSubmit", function( e ) { var elem = e.target, type = elem.type; if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { trigger( "submit", this, arguments ); } }); jQuery.event.add(this, "keypress.specialSubmit", function( e ) { var elem = e.target, type = elem.type; if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { trigger( "submit", this, arguments ); } }); } else { return false; } }, teardown: function( namespaces ) { jQuery.event.remove( this, ".specialSubmit" ); } }; } // change delegation, happens here so we have bind. if ( !jQuery.support.changeBubbles ) { var changeFilters, getVal = function( elem ) { var type = elem.type, val = elem.value; if ( type === "radio" || type === "checkbox" ) { val = elem.checked; } else if ( type === "select-multiple" ) { val = elem.selectedIndex > -1 ? jQuery.map( elem.options, function( elem ) { return elem.selected; }).join("-") : ""; } else if ( jQuery.nodeName( elem, "select" ) ) { val = elem.selectedIndex; } return val; }, testChange = function testChange( e ) { var elem = e.target, data, val; if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { return; } data = jQuery._data( elem, "_change_data" ); val = getVal(elem); // the current data will be also retrieved by beforeactivate if ( e.type !== "focusout" || elem.type !== "radio" ) { jQuery._data( elem, "_change_data", val ); } if ( data === undefined || val === data ) { return; } if ( data != null || val ) { e.type = "change"; e.liveFired = undefined; jQuery.event.trigger( e, arguments[1], elem ); } }; jQuery.event.special.change = { filters: { focusout: testChange, beforedeactivate: testChange, click: function( e ) { var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { testChange.call( this, e ); } }, // Change has to be called before submit // Keydown will be called before keypress, which is used in submit-event delegation keydown: function( e ) { var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || type === "select-multiple" ) { testChange.call( this, e ); } }, // Beforeactivate happens also before the previous element is blurred // with this event you can't trigger a change event, but you can store // information beforeactivate: function( e ) { var elem = e.target; jQuery._data( elem, "_change_data", getVal(elem) ); } }, setup: function( data, namespaces ) { if ( this.type === "file" ) { return false; } for ( var type in changeFilters ) { jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); } return rformElems.test( this.nodeName ); }, teardown: function( namespaces ) { jQuery.event.remove( this, ".specialChange" ); return rformElems.test( this.nodeName ); } }; changeFilters = jQuery.event.special.change.filters; // Handle when the input is .focus()'d changeFilters.focus = changeFilters.beforeactivate; } function trigger( type, elem, args ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. // Don't pass args or remember liveFired; they apply to the donor event. var event = jQuery.extend( {}, args[ 0 ] ); event.type = type; event.originalEvent = {}; event.liveFired = undefined; jQuery.event.handle.call( elem, event ); if ( event.isDefaultPrevented() ) { args[ 0 ].preventDefault(); } } // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; function handler( donor ) { // Donor event is always a native one; fix it and switch its type. // Let focusin/out handler cancel the donor focus/blur event. var e = jQuery.event.fix( donor ); e.type = fix; e.originalEvent = {}; jQuery.event.trigger( e, null, e.target ); if ( e.isDefaultPrevented() ) { donor.preventDefault(); } } }); } jQuery.each(["bind", "one"], function( i, name ) { jQuery.fn[ name ] = function( type, data, fn ) { var handler; // Handle object literals if ( typeof type === "object" ) { for ( var key in type ) { this[ name ](key, data, type[key], fn); } return this; } if ( arguments.length === 2 || data === false ) { fn = data; data = undefined; } if ( name === "one" ) { handler = function( event ) { jQuery( this ).unbind( event, handler ); return fn.apply( this, arguments ); }; handler.guid = fn.guid || jQuery.guid++; } else { handler = fn; } if ( type === "unload" && name !== "one" ) { this.one( type, data, fn ); } else { for ( var i = 0, l = this.length; i < l; i++ ) { jQuery.event.add( this[i], type, handler, data ); } } return this; }; }); jQuery.fn.extend({ unbind: function( type, fn ) { // Handle object literals if ( typeof type === "object" && !type.preventDefault ) { for ( var key in type ) { this.unbind(key, type[key]); } } else { for ( var i = 0, l = this.length; i < l; i++ ) { jQuery.event.remove( this[i], type, fn ); } } return this; }, delegate: function( selector, types, data, fn ) { return this.live( types, data, fn, selector ); }, undelegate: function( selector, types, fn ) { if ( arguments.length === 0 ) { return this.unbind( "live" ); } else { return this.die( types, null, fn, selector ); } }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { return jQuery.event.trigger( type, data, this[0], true ); } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); var liveMap = { focus: "focusin", blur: "focusout", mouseenter: "mouseover", mouseleave: "mouseout" }; jQuery.each(["live", "die"], function( i, name ) { jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { var type, i = 0, match, namespaces, preType, selector = origSelector || this.selector, context = origSelector ? this : jQuery( this.context ); if ( typeof types === "object" && !types.preventDefault ) { for ( var key in types ) { context[ name ]( key, data, types[key], selector ); } return this; } if ( name === "die" && !types && origSelector && origSelector.charAt(0) === "." ) { context.unbind( origSelector ); return this; } if ( data === false || jQuery.isFunction( data ) ) { fn = data || returnFalse; data = undefined; } types = (types || "").split(" "); while ( (type = types[ i++ ]) != null ) { match = rnamespaces.exec( type ); namespaces = ""; if ( match ) { namespaces = match[0]; type = type.replace( rnamespaces, "" ); } if ( type === "hover" ) { types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); continue; } preType = type; if ( liveMap[ type ] ) { types.push( liveMap[ type ] + namespaces ); type = type + namespaces; } else { type = (liveMap[ type ] || type) + namespaces; } if ( name === "live" ) { // bind live handler for ( var j = 0, l = context.length; j < l; j++ ) { jQuery.event.add( context[j], "live." + liveConvert( type, selector ), { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); } } else { // unbind live handler context.unbind( "live." + liveConvert( type, selector ), fn ); } } return this; }; }); function liveHandler( event ) { var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, elems = [], selectors = [], events = jQuery._data( this, "events" ); // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { return; } if ( event.namespace ) { namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); } event.liveFired = this; var live = events.live.slice(0); for ( j = 0; j < live.length; j++ ) { handleObj = live[j]; if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { selectors.push( handleObj.selector ); } else { live.splice( j--, 1 ); } } match = jQuery( event.target ).closest( selectors, event.currentTarget ); for ( i = 0, l = match.length; i < l; i++ ) { close = match[i]; for ( j = 0; j < live.length; j++ ) { handleObj = live[j]; if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { elem = close.elem; related = null; // Those two events require additional checking if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { event.type = handleObj.preType; related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; // Make sure not to accidentally match a child element with the same selector if ( related && jQuery.contains( elem, related ) ) { related = elem; } } if ( !related || related !== elem ) { elems.push({ elem: elem, handleObj: handleObj, level: close.level }); } } } } for ( i = 0, l = elems.length; i < l; i++ ) { match = elems[i]; if ( maxLevel && match.level > maxLevel ) { break; } event.currentTarget = match.elem; event.data = match.handleObj.data; event.handleObj = match.handleObj; ret = match.handleObj.origHandler.apply( match.elem, arguments ); if ( ret === false || event.isPropagationStopped() ) { maxLevel = match.level; if ( ret === false ) { stop = false; } if ( event.isImmediatePropagationStopped() ) { break; } } } return stop; } function liveConvert( type, selector ) { return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); } jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { if ( fn == null ) { fn = data; data = null; } return arguments.length > 0 ? this.bind( name, data, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } }); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true, rBackslash = /\\/g, rNonWord = /\W/; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function() { baseHasDuplicate = false; return 0; }); var Sizzle = function( selector, context, results, seed ) { results = results || []; context = context || document; var origContext = context; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var m, set, checkSet, extra, ret, cur, pop, i, prune = true, contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); m = chunker.exec( soFar ); if ( m ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } } while ( m ); if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray( set ); } else { prune = false; } while ( parts.length ) { cur = parts.pop(); pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function( results ) { if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[ i - 1 ] ) { results.splice( i--, 1 ); } } } } return results; }; Sizzle.matches = function( expr, set ) { return Sizzle( expr, null, null, set ); }; Sizzle.matchesSelector = function( node, expr ) { return Sizzle( expr, null, null, [node] ).length > 0; }; Sizzle.find = function( expr, context, isXML ) { var set; if ( !expr ) { return []; } for ( var i = 0, l = Expr.order.length; i < l; i++ ) { var match, type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { var left = match[1]; match.splice( 1, 1 ); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace( rBackslash, "" ); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) : []; } return { set: set, expr: expr }; }; Sizzle.filter = function( expr, set, inplace, not ) { var match, anyFound, old = expr, result = [], curLoop = set, isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); while ( expr && set.length ) { for ( var type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { var found, item, filter = Expr.filter[ type ], left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( var i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); var pass = not ^ !!found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw "Syntax error, unrecognized expression: " + msg; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function( elem ) { return elem.getAttribute( "href" ); }, type: function( elem ) { return elem.getAttribute( "type" ); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !rNonWord.test( part ), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function( checkSet, part ) { var elem, isPartStr = typeof part === "string", i = 0, l = checkSet.length; if ( isPartStr && !rNonWord.test( part ) ) { part = part.toLowerCase(); for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); }, "~": function( checkSet, part, isXML ) { var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); } }, find: { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } }, preFilter: { CLASS: function( match, curLoop, inplace, result, not, isXML ) { match = " " + match[1].replace( rBackslash, "" ) + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function( match ) { return match[1].replace( rBackslash, "" ); }, TAG: function( match, curLoop ) { return match[1].replace( rBackslash, "" ).toLowerCase(); }, CHILD: function( match ) { if ( match[1] === "nth" ) { if ( !match[2] ) { Sizzle.error( match[0] ); } match[2] = match[2].replace(/^\+|\s*/g, ''); // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } else if ( match[2] ) { Sizzle.error( match[0] ); } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } // Handle if an un-quoted value was used match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function( match, curLoop, inplace, result, not ) { if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function( match ) { match.unshift( true ); return match; } }, filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; }, disabled: function( elem ) { return elem.disabled === true; }, checked: function( elem ) { return elem.checked === true; }, selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, parent: function( elem ) { return !!elem.firstChild; }, empty: function( elem ) { return !elem.firstChild; }, has: function( elem, i, match ) { return !!Sizzle( match[3], elem ).length; }, header: function( elem ) { return (/h\d/i).test( elem.nodeName ); }, text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, radio: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; }, checkbox: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; }, file: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; }, password: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; }, submit: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "submit" === elem.type; }, image: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; }, reset: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "reset" === elem.type; }, button: function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && "button" === elem.type || name === "button"; }, input: function( elem ) { return (/input|select|textarea|button/i).test( elem.nodeName ); }, focus: function( elem ) { return elem === elem.ownerDocument.activeElement; } }, setFilters: { first: function( elem, i ) { return i === 0; }, last: function( elem, i, match, array ) { return i === array.length - 1; }, even: function( elem, i ) { return i % 2 === 0; }, odd: function( elem, i ) { return i % 2 === 1; }, lt: function( elem, i, match ) { return i < match[3] - 0; }, gt: function( elem, i, match ) { return i > match[3] - 0; }, nth: function( elem, i, match ) { return match[3] - 0 === i; }, eq: function( elem, i, match ) { return match[3] - 0 === i; } }, filter: { PSEUDO: function( elem, match, i, array ) { var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var j = 0, l = not.length; j < l; j++ ) { if ( not[j] === elem ) { return false; } } return true; } else { Sizzle.error( name ); } }, CHILD: function( elem, match ) { var type = match[1], node = elem; switch ( type ) { case "only": case "first": while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; case "last": while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case "nth": var first = match[2], last = match[3]; if ( first === 1 && last === 0 ) { return true; } var doneName = match[0], parent = elem.parentNode; if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { var count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent.sizcache = doneName; } var diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function( elem, match ) { return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; }, CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function( elem, match ) { var name = match[1], result = Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function( elem, match, i, array ) { var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS, fescape = function(all, num){ return "\\" + (num - 0 + 1); }; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); } var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch( e ) { makeArray = function( array, results ) { var i = 0, ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( ; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder, siblingCheck; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; return 0; } if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { return a.compareDocumentPosition ? -1 : 1; } return a.compareDocumentPosition(b) & 4 ? -1 : 1; }; } else { sortOrder = function( a, b ) { // The nodes are identical, we can exit early if ( a === b ) { hasDuplicate = true; return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes } else if ( a.sourceIndex && b.sourceIndex ) { return a.sourceIndex - b.sourceIndex; } var al, bl, ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, cur = aup; // If the nodes are siblings (or identical) we can do a quick check if ( aup === bup ) { return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected } else if ( !aup ) { return -1; } else if ( !bup ) { return 1; } // Otherwise they're somewhere else in the tree so we need // to build up a full list of the parentNodes for comparison while ( cur ) { ap.unshift( cur ); cur = cur.parentNode; } cur = bup; while ( cur ) { bp.unshift( cur ); cur = cur.parentNode; } al = ap.length; bl = bp.length; // Start walking down the tree looking for a discrepancy for ( var i = 0; i < al && i < bl; i++ ) { if ( ap[i] !== bp[i] ) { return siblingCheck( ap[i], bp[i] ); } } // We ended someplace up the tree so do a sibling check return i === al ? siblingCheck( a, bp[i], -1 ) : siblingCheck( ap[i], b, 1 ); }; siblingCheck = function( a, b, ret ) { if ( a === b ) { return ret; } var cur = a.nextSibling; while ( cur ) { if ( cur === b ) { return -1; } cur = cur.nextSibling; } return 1; }; } // Utility function for retreiving the text value of an array of DOM nodes Sizzle.getText = function( elems ) { var ret = "", elem; for ( var i = 0; elems[i]; i++ ) { elem = elems[i]; // Get the text from text nodes and CDATA nodes if ( elem.nodeType === 3 || elem.nodeType === 4 ) { ret += elem.nodeValue; // Traverse everything else, except comment nodes } else if ( elem.nodeType !== 8 ) { ret += Sizzle.getText( elem.childNodes ); } } return ret; }; // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // release memory in IE root = form = null; })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function( match, context ) { var results = context.getElementsByTagName( match[1] ); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function( elem ) { return elem.getAttribute( "href", 2 ); }; } // release memory in IE div = null; })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"), id = "__sizzle__"; div.innerHTML = "

"; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function( query, context, extra, seed ) { context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } } else { return makeArray( [], extra ); } } try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var oldContext = context, old = context.getAttribute( "id" ), nid = old || id, hasParent = context.parentNode, relativeHierarchySelector = /^\s*[+~]/.test( query ); if ( !old ) { context.setAttribute( "id", nid ); } else { nid = nid.replace( /'/g, "\\$&" ); } if ( relativeHierarchySelector && hasParent ) { context = context.parentNode; } try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch(pseudoError) { } finally { if ( !old ) { oldContext.removeAttribute( "id" ); } } } } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } // release memory in IE div = null; })(); } (function(){ var html = document.documentElement, matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; if ( matches ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9 fails this) var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), pseudoWorks = false; try { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); } catch( pseudoError ) { pseudoWorks = true; } Sizzle.matchesSelector = function( node, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || !disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9, so check for that node.document && node.document.nodeType !== 11 ) { return ret; } } } catch(e) {} } return Sizzle(expr, null, null, [node]).length > 0; }; } })(); (function(){ var div = document.createElement("div"); div.innerHTML = "
"; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; // release memory in IE div = null; })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem.sizcache = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem.sizcache === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem.sizcache = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } if ( document.documentElement.contains ) { Sizzle.contains = function( a, b ) { return a !== b && (a.contains ? a.contains(b) : true); }; } else if ( document.documentElement.compareDocumentPosition ) { Sizzle.contains = function( a, b ) { return !!(a.compareDocumentPosition(b) & 16); }; } else { Sizzle.contains = function() { return false; }; } Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function( selector, context ) { var match, tmpSet = [], later = "", root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, isSimple = /^.[^:#\[\.,]*$/, slice = Array.prototype.slice, POS = jQuery.expr.match.POS, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self = this, i, l; if ( typeof selector !== "string" ) { return jQuery( selector ).filter(function() { for ( i = 0, l = self.length; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }); } var ret = this.pushStack( "", "find", selector ), length, n, r; for ( i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( n = length; n < ret.length; n++ ) { for ( r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; // Array if ( jQuery.isArray( selectors ) ) { var match, selector, matches = {}, level = 1; if ( cur && selectors.length ) { for ( i = 0, l = selectors.length; i < l; i++ ) { selector = selectors[i]; if ( !matches[ selector ] ) { matches[ selector ] = POS.test( selector ) ? jQuery( selector, context || this.context ) : selector; } } while ( cur && cur.ownerDocument && cur !== context ) { for ( selector in matches ) { match = matches[ selector ]; if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { ret.push({ selector: selector, elem: cur, level: level }); } } cur = cur.parentNode; level++; } } return ret; } // String var pos = POS.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( i = 0, l = this.length; i < l; i++ ) { cur = this[i]; while ( cur ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } else { cur = cur.parentNode; if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { break; } } } } ret = ret.length > 1 ? jQuery.unique( ret ) : ret; return this.pushStack( ret, "closest", selectors ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { if ( !elem || typeof elem === "string" ) { return jQuery.inArray( this[0], // If it receives a string, the selector is used // If it receives nothing, the siblings are used elem ? jQuery( elem ) : this.parent().children() ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( elem.parentNode.firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ), // The variable 'args' was introduced in // https://github.com/jquery/jquery/commit/52a0238 // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. // http://code.google.com/p/v8/issues/detail?id=1050 args = slice.call(arguments); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, args.join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return (elem === qualifier) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return (jQuery.inArray( elem, qualifier ) >= 0) === keep; }); } var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /", "" ], legend: [ 1, "
", "
" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], col: [ 2, "", "
" ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }; wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and

聊天室

================================================ FILE: springWebSocket/src/main/resources/templates/login.html ================================================ 登陆页面
无效的账号和密码
你已注销
================================================ FILE: springWebSocket/src/main/resources/templates/ws.html ================================================ Spring Boot+WebSocket+广播式

================================================ FILE: springboot-Cache/pom.xml ================================================ 4.0.0 com.us springboot-Cache 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 org.springframework.boot spring-boot-starter-cache org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-redis mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging ================================================ FILE: springboot-Cache/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.*; /** * Created by yangyibo on 17/1/13. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/bean/Person.java ================================================ package com.us.example.bean; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import java.io.Serializable; /** * Created by yangyibo on 17/1/13. */ @Entity @Table(name = "Person") public class Person implements Serializable { private static final long serialVersionUID = 133938246231808718L; @Id @GeneratedValue private Long id; private String name; private Integer age; private String address; public Person() { super(); } public Person(Long id, String name, Integer age, String address) { super(); this.id = id; this.name = name; this.age = age; this.address = address; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/config/DBConfig.java ================================================ package com.us.example.config; /** * Created by yangyibo on 17/1/13. */ import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/config/JpaConfig.java ================================================ package com.us.example.config; import java.util.HashMap; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Created by yangyibo on 17/1/13. */ @Configuration @EnableJpaRepositories("com.us.example.dao") @EnableTransactionManagement @ComponentScan public class JpaConfig { @Autowired private DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); //vendorAdapter.setShowSql(true); //vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.us.example.bean"); factory.setDataSource(dataSource); Map jpaProperties = new HashMap<>(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.jdbc.batch_size",50); //jpaProperties.put("hibernate.show_sql",true); factory.setJpaPropertyMap(jpaProperties); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/config/RedisConfig.java ================================================ package com.us.example.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheErrorHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; /** * Created by yangyibo on 17/1/16. */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport{ private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); @Autowired private Environment env; @Bean public JedisConnectionFactory redisConnectionFactory() { JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(); redisConnectionFactory.setHostName(env.getProperty("redis.hostname")); redisConnectionFactory.setPort(Integer.parseInt(env.getProperty("redis.port"))); return redisConnectionFactory; } @Bean public RedisTemplate redisTemplate(RedisConnectionFactory cf) { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(cf); return redisTemplate; } @Bean public CacheManager cacheManager(RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); cacheManager.setDefaultExpiration(600); return cacheManager; } public CacheErrorHandler errorHandler() { return new CacheErrorHandler(){ @Override public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) { logger.warn("handleCacheGetError in redis: {}", exception.getMessage()); } @Override public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) { logger.warn("handleCachePutError in redis: {}", exception.getMessage()); } @Override public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) { logger.warn("handleCacheEvictError in redis: {}", exception.getMessage()); } @Override public void handleCacheClearError(RuntimeException exception, Cache cache) { logger.warn("handleCacheClearError in redis: {}", exception.getMessage()); }}; } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/controller/CacheController.java ================================================ package com.us.example.controller; import com.us.example.bean.Person; import com.us.example.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * Created by yangyibo on 17/1/13. */ @RestController public class CacheController { @Autowired private DemoService demoService; //http://localhost:8080/put?name=abel&age=23&address=shanghai @RequestMapping("/put") public Person put(Person person){ return demoService.save(person); } //http://localhost:8080/able?id=1 @RequestMapping("/able") @ResponseBody public Person cacheable(Person person){ return demoService.findOne(person); } //http://localhost:8080/evit?id=1 @RequestMapping("/evit") public String evit(Long id){ demoService.remove(id); return "ok"; } } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/dao/PersonRepository.java ================================================ package com.us.example.dao; import com.us.example.bean.Person; import org.springframework.data.jpa.repository.JpaRepository; /** * Created by yangyibo on 17/1/13. */ public interface PersonRepository extends JpaRepository { } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/service/DemoService.java ================================================ package com.us.example.service; import com.us.example.bean.Person; /** * Created by yangyibo on 17/1/13. */ public interface DemoService { public Person save(Person person); public void remove(Long id); public Person findOne(Person person); } ================================================ FILE: springboot-Cache/src/main/java/com/us/example/service/Impl/DemoServiceImpl.java ================================================ package com.us.example.service.Impl; import com.us.example.bean.Person; import com.us.example.dao.PersonRepository; import com.us.example.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; /** * Created by yangyibo on 17/1/13. */ @Service public class DemoServiceImpl implements DemoService { @Autowired private PersonRepository personRepository; @Override //@CachePut缓存新增的或更新的数据到缓存,其中缓存名字是 people 。数据的key是person的id @CachePut(value = "people", key = "#person.id") public Person save(Person person) { Person p = personRepository.save(person); System.out.println("为id、key为:"+p.getId()+"数据做了缓存"); return p; } @Override //@CacheEvict 从缓存people中删除key为id 的数据 @CacheEvict(value = "people") public void remove(Long id) { System.out.println("删除了id、key为"+id+"的数据缓存"); //这里不做实际删除操作 } @Override //@Cacheable缓存key为person 的id 数据到缓存people 中,如果没有指定key则方法参数作为key保存到缓存中。 @Cacheable(value = "people", key = "#person.id") public Person findOne(Person person) { Person p = personRepository.findOne(person.getId()); System.out.println("为id、key为:"+p.getId()+"数据做了缓存"); return p; } } ================================================ FILE: springboot-Cache/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true ms.db.username=root ms.db.password=admin ms.db.maxActive=500 #最多缓存 500 条 ,缓存在 30 分钟后失效 #spring.cache.guava.spec= maximumSize=500,expireAfterWrite=30m #redis.hostname=xxxxxx redis.hostname=xxxxxx redis.port=6379 ================================================ FILE: springboot-Cache/src/main/resources/ehcache.xml ================================================ ================================================ FILE: springboot-Cache2/pom.xml ================================================ 4.0.0 com.us springboot-Cache2 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 org.springframework.boot spring-boot-starter-cache org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web com.google.guava guava 18.0 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.*; /** * Created by yangyibo on 17/1/13. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/bean/Person.java ================================================ package com.us.example.bean; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import java.io.Serializable; /** * Created by yangyibo on 17/1/13. */ @Entity @Table(name = "Person") public class Person implements Serializable { private static final long serialVersionUID = 133938246231808718L; @Id @GeneratedValue private Long id; private String name; private Integer age; private String address; public Person() { super(); } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Person(Long id, String name, Integer age, String address) { super(); this.id = id; this.name = name; this.age = age; this.address = address; } @Override public String toString() { return "Person{" + "id=" + id + ", name=" + name + ", age=" + age + ", address=" + address + '}'; } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/config/CacheConfig.java ================================================ package com.us.example.config; import com.us.example.bean.Person; import com.us.example.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/3/2. */ @Configuration public class CacheConfig { @Autowired private DemoService demoService; @Bean public CacheManager getCacheManager() { List personList = demoService.findAll(); //所有缓存的名字 List cacheNames = new ArrayList(); GuavaCacheManager cacheManager = new GuavaCacheManager(); //GuavaCacheManager 的数据结构类似 Map> map =new HashMap<>(); //将数据放入缓存 personList.stream().forEach(person -> { //用person 的id cacheName String cacheName=person.getId().toString(); if(cacheManager.getCache(cacheName)==null){ //为每一个person 如果不存在,创建一个新的缓存对象 cacheNames.add(cacheName); cacheManager.setCacheNames(cacheNames); } Cache cache = cacheManager.getCache(cacheName); //缓存对象用person的id当作缓存的key 用person 当作缓存的value cache.put(person.getId(),person); System.out.println("为 ID 为"+cacheName+ "的person 数据做了缓存"); }); return cacheManager; } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/config/DBConfig.java ================================================ package com.us.example.config; /** * Created by yangyibo on 17/1/13. */ import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/config/JpaConfig.java ================================================ package com.us.example.config; import java.util.HashMap; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * Created by yangyibo on 17/1/13. */ @Configuration @EnableJpaRepositories("com.us.example.dao") @EnableTransactionManagement @ComponentScan public class JpaConfig { @Autowired private DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); //vendorAdapter.setShowSql(true); //vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.us.example.bean"); factory.setDataSource(dataSource); Map jpaProperties = new HashMap<>(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.jdbc.batch_size",50); //jpaProperties.put("hibernate.show_sql",true); factory.setJpaPropertyMap(jpaProperties); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/controller/CacheController.java ================================================ package com.us.example.controller; import com.us.example.bean.Person; import com.us.example.service.PersonService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * Created by yangyibo on 17/1/13. */ @RestController @RequestMapping(value = "/person") public class CacheController { @Autowired private PersonService personService; @RequestMapping(method = RequestMethod.POST) @ResponseBody public Person put(Person person){ return personService.save(person); } //http://localhost:8080/person/1 @RequestMapping(value ="/{id}" ,method = RequestMethod.GET) @ResponseBody public Person cacheable( @PathVariable Long id){ return personService.findOne(id); } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/dao/PersonRepository.java ================================================ package com.us.example.dao; import com.us.example.bean.Person; import org.springframework.data.jpa.repository.JpaRepository; /** * Created by yangyibo on 17/1/13. */ public interface PersonRepository extends JpaRepository { } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/service/DemoService.java ================================================ package com.us.example.service; import com.us.example.bean.Person; import com.us.example.dao.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * Created by yangyibo on 17/1/13. */ @Service public class DemoService { @Autowired private PersonRepository personRepository; public List findAll() { return personRepository.findAll(); } } ================================================ FILE: springboot-Cache2/src/main/java/com/us/example/service/PersonService.java ================================================ package com.us.example.service; import com.us.example.bean.Person; import com.us.example.dao.PersonRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.stereotype.Service; /** * Created by yangyibo on 17/3/2. */ @Service public class PersonService { @Autowired CacheManager cacheManager; @Autowired private PersonRepository personRepository; public Person findOne(Long id) { Person person = getCache(id, cacheManager); if (person != null) { System.out.println("从缓存中取出:" + person.toString()); } else { person = personRepository.findOne(id); System.out.println("从数据库中取出:" + person.toString()); } return person; } public Person save(Person person) { Person p = personRepository.save(person); return p; } public Person getCache(Long id, CacheManager cacheManager) { // Person person=(Person) cacheManager.getCache(id.toString()).get(id).get(); Cache cache = cacheManager.getCache(id.toString()); Cache.ValueWrapper valueWrapper = cache.get(id); Person person = (Person) valueWrapper.get(); return person; } } ================================================ FILE: springboot-Cache2/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true ms.db.username=root ms.db.password=admin ms.db.maxActive=500 ================================================ FILE: springboot-Quartz/pom.xml ================================================ 4.0.0 com.abel.quartz springboot-Quartz 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.quartz-scheduler quartz 2.2.1 org.springframework.boot spring-boot-starter-mail mysql mysql-connector-java com.zaxxer HikariCP 3.2.0 org.springframework spring-jdbc org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-surefire-plugin 2.18.1 true ================================================ FILE: springboot-Quartz/src/main/java/com/abel/quartz/Application.java ================================================ package com.abel.quartz; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; /** * Created by yangyibo on 2019/2/1. */ @SpringBootApplication @ImportResource("classpath*:META-INF/spring/*.xml") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-Quartz/src/main/java/com/abel/quartz/config/InvokingJobDetailFactory.java ================================================ package com.abel.quartz.config; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; import java.lang.reflect.Method; /** * Created by yangyibo on 2019/2/1. */ public class InvokingJobDetailFactory extends QuartzJobBean { /** * 计划任务所在类 */ private String targetObject; /** * 具体需要执行的计划任务 */ private String targetMethod; private ApplicationContext ctx; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { Object obj = ctx.getBean(targetObject); Method m = null; try { m = obj.getClass().getMethod(targetMethod); //调用被代理对象的方法 m.invoke(obj); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } catch (Exception e) { throw new JobExecutionException(e); } } public void setApplicationContext(ApplicationContext applicationContext) { this.ctx = applicationContext; } public void setTargetObject(String targetObject) { this.targetObject = targetObject; } public void setTargetMethod(String targetMethod) { this.targetMethod = targetMethod; } } ================================================ FILE: springboot-Quartz/src/main/java/com/abel/quartz/config/QuartzConfig.java ================================================ package com.abel.quartz.config; import java.beans.PropertyVetoException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import com.zaxxer.hikari.HikariDataSource; import org.quartz.Job; import org.quartz.JobDetail; import org.quartz.Trigger; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.CronTriggerFactoryBean; import org.springframework.scheduling.quartz.JobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; /** * Created by yangyibo on 2019/1/16. */ @Configuration public class QuartzConfig { /** * 1.通过name+group获取唯一的jobKey;2.通过groupname来获取其下的所有jobkey */ final static String GROUP_NAME = "QuartzJobGroups"; @Value("${quartz.scheduler.instanceName}") private String quartzInstanceName; @Value("${spring.datasource.driverClassName}") private String myDSDriver; @Value("${spring.datasource.url}") private String myDSUrl; @Value("${spring.datasource.username}") private String myDSUser; @Value("${spring.datasource.password}") private String myDSPassword; @Value("${org.quartz.dataSource.myDS.maxConnections}") private int myDSMaxConnections; /** * 设置属性 * * @return * @throws IOException */ private Properties quartzProperties() throws IOException { Properties prop = new Properties(); // 调度标识名 集群中每一个实例都必须使用相同的名称 prop.put("quartz.scheduler.instanceName", quartzInstanceName); // ID设置为自动获取 每一个必须不同 prop.put("org.quartz.scheduler.instanceId", "AUTO"); // 禁用quartz软件更新 prop.put("org.quartz.scheduler.skipUpdateCheck", "true"); prop.put("org.quartz.scheduler.jmx.export", "true"); // 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库 prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); // 数据保存方式为数据库持久化 prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); // 数据库别名 随便取 prop.put("org.quartz.jobStore.dataSource", "quartzDataSource"); //prop.put("org.quartz.jobStore.dataSource", "myDS"); // 表的前缀,默认QRTZ_ prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); // 是否加入集群 prop.put("org.quartz.jobStore.isClustered", "true"); // 调度实例失效的检查时间间隔 prop.put("org.quartz.jobStore.clusterCheckinInterval", "20000"); prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); // 信息保存时间 ms 默认值60秒 prop.put("org.quartz.jobStore.misfireThreshold", "120000"); prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE"); // 程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求) prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); // 定线程数,至少为1(无默认值)(一般设置为1-100之间的整数合适) prop.put("org.quartz.threadPool.threadCount", "10"); // 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5) prop.put("org.quartz.threadPool.threadPriority", "5"); prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true"); prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin"); prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin"); prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true"); //#自定义连接池 //org.quartz.dataSource.myDS.connectionProvider.class=com.poly.pay.schedule.DruidConnectionProvider return prop; } /** * 数据源 * * @return * @throws PropertyVetoException */ @Bean public HikariDataSource createDataSource() throws PropertyVetoException { HikariDataSource dataSource = new HikariDataSource(); dataSource.setJdbcUrl(myDSUrl); dataSource.setDriverClassName(myDSDriver); dataSource.setUsername(myDSUser); dataSource.setPassword(myDSPassword); dataSource.setMaximumPoolSize(myDSMaxConnections); return dataSource; } /** * 创建触发器工厂 * * @param jobDetail * @param cronExpression * @return */ private static CronTriggerFactoryBean cronTriggerFactoryBean(JobDetail jobDetail, String cronExpression) { CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean(); factoryBean.setJobDetail(jobDetail); factoryBean.setCronExpression(cronExpression); return factoryBean; } /****************************************************以下配置需要注意******************************************************/ /** * 调度工厂 * 此处配置需要调度的触发器 例如 executeJobTrigger * * @param executeJobTrigger * @return * @throws IOException * @throws PropertyVetoException */ @Bean public SchedulerFactoryBean schedulerFactoryBean(@Qualifier("executeJobTrigger") Trigger executeJobTrigger) throws IOException, PropertyVetoException { SchedulerFactoryBean factory = new SchedulerFactoryBean(); // this allows to update triggers in DB when updating settings in config file: //用于quartz集群,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 factory.setOverwriteExistingJobs(true); //用于quartz集群,加载quartz数据源 //factory.setDataSource(dataSource); //QuartzScheduler 延时启动,应用启动完10秒后 QuartzScheduler 再启动 //factory.setStartupDelay(10); //用于quartz集群,加载quartz数据源配置 factory.setAutoStartup(true); factory.setQuartzProperties(quartzProperties()); factory.setApplicationContextSchedulerContextKey("applicationContext"); factory.setDataSource(createDataSource()); //注册触发器 Trigger[] triggers = {executeJobTrigger}; factory.setTriggers(triggers); return factory; } /** * 加载触发器 * * 新建触发器进行job 的调度 例如 executeJobDetail * @param jobDetail * @return */ @Bean(name = "executeJobTrigger") public CronTriggerFactoryBean executeJobTrigger(@Qualifier("executeJobDetail") JobDetail jobDetail) { //每天凌晨3点执行 return cronTriggerFactoryBean(jobDetail, "0 1 0 * * ? "); } /** * 加载job * * 新建job 类用来代理 * * * @return */ @Bean public JobDetailFactoryBean executeJobDetail() { return createJobDetail(InvokingJobDetailFactory.class, GROUP_NAME, "executeJob"); } /** * 执行规则job工厂 * * 配置job 类中需要定时执行的 方法 execute * @param jobClass * @param groupName * @param targetObject * @return */ private static JobDetailFactoryBean createJobDetail(Class jobClass, String groupName, String targetObject) { JobDetailFactoryBean factoryBean = new JobDetailFactoryBean(); factoryBean.setJobClass(jobClass); factoryBean.setDurability(true); factoryBean.setRequestsRecovery(true); factoryBean.setGroup(groupName); Map map = new HashMap<>(); map.put("targetMethod", "execute"); map.put("targetObject", targetObject); factoryBean.setJobDataAsMap(map); return factoryBean; } } ================================================ FILE: springboot-Quartz/src/main/java/com/abel/quartz/job/ExecuteJob.java ================================================ package com.abel.quartz.job; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; /** * Created by yangyibo on 2019/2/1. */ @Service public class ExecuteJob { private static final Logger logger = LoggerFactory.getLogger(ExecuteJob.class); /** * 方法名在quartz定义 */ public void execute() { System.out.println("定时任务执行了。。。。。"); } } ================================================ FILE: springboot-Quartz/src/main/resources/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=8090 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.abel.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=springboot-Quartz application.main=com.abel.quartz.Application ## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 spring.datasource.url=jdbc:mysql://localhost:3306/quartz?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver ## \u8FDE\u63A5\u6C60\u914D\u7F6E spring.datasource.type=com.zaxxer.hikari.HikariDataSource #\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.datasource.hikari.minimum-idle=10 #\u8FDE\u63A5\u6C60\u4E2D\u5141\u8BB8\u7684\u6700\u5927\u8FDE\u63A5\u6570\u3002\u7F3A\u7701\u503C\uFF1A10\uFF1B\u63A8\u8350\u7684\u516C\u5F0F\uFF1A((core_count * 2) + effective_spindle_count) spring.datasource.hikari.maximum-pool-size=30 #spring.datasource.hikari.auto-commit=true #\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09\uFF0C\u8D85\u65F6\u5219\u88AB\u91CA\u653E\uFF08retired\uFF09\uFF0C\u7F3A\u7701:10\u5206\u949F\u3002minimumIdle springboot-quartz %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-SpringSecurity0/pom.xml ================================================ 4.0.0 com.us springboot-security0 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 3.2.7 1.2.2 org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/DBconfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * Created by yangyibo on 17/1/18. */ @Configuration public class DBconfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/MyBatisConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration @ComponentScan public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()}); sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/MyBatisScannerConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/TransactionConfig.java ================================================ package com.us.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/WebMvcConfig.java ================================================ package com.us.example.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Created by yangyibo on 17/1/18. */ @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter{ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/config/WebSecurityConfig.java ================================================ package com.us.example.config; import com.us.example.security.CustomUserService; import com.us.example.util.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * Created by yangyibo on 17/1/18. */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean UserDetailsService customUserService(){ //注册UserDetailsService 的bean return new CustomUserService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder(){ @Override public String encode(CharSequence rawPassword) { return MD5Util.encode((String)rawPassword); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { return encodedPassword.equals(MD5Util.encode((String)rawPassword)); }}); //user Details Service验证 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() //任何请求,登录后可以访问 .and() .formLogin() .loginPage("/login") .failureUrl("/login?error") .permitAll() //登录页面用户任意访问 .and() .logout().permitAll(); //注销行为任意访问 } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/controller/HomeController.java ================================================ package com.us.example.controller; import com.us.example.domain.Msg; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; /** * Created by yangyibo on 17/1/18. */ @Controller public class HomeController { @RequestMapping("/") public String index(Model model){ Msg msg = new Msg("测试标题","测试内容","额外信息,只对管理员显示"); model.addAttribute("msg", msg); return "home"; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/dao/UserDao.java ================================================ package com.us.example.dao; import com.us.example.domain.SysUser; public interface UserDao { public SysUser findByUserName(String username); } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/domain/Msg.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class Msg { private String title; private String content; private String etraInfo; public Msg(String title, String content, String etraInfo) { super(); this.title = title; this.content = content; this.etraInfo = etraInfo; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getEtraInfo() { return etraInfo; } public void setEtraInfo(String etraInfo) { this.etraInfo = etraInfo; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/domain/SysRole.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class SysRole { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/domain/SysUser.java ================================================ package com.us.example.domain; import java.util.List; /** * Created by yangyibo on 17/1/17. */ public class SysUser { private Integer id; private String username; private String password; private List roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/security/CustomUserService.java ================================================ package com.us.example.security; import com.us.example.dao.UserDao; import com.us.example.domain.SysRole; import com.us.example.domain.SysUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/1/18. */ @Service public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口 @Autowired UserDao userDao; @Override public UserDetails loadUserByUsername(String username) { //重写loadUserByUsername 方法获得 userdetails 类型用户 SysUser user = userDao.findByUserName(username); if(user == null){ throw new UsernameNotFoundException("用户名不存在"); } List authorities = new ArrayList<>(); //用于添加用户的权限。只要把用户权限添加到authorities 就万事大吉。 for(SysRole role:user.getRoles()) { authorities.add(new SimpleGrantedAuthority(role.getName())); System.out.println(role.getName()); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities); } } ================================================ FILE: springboot-SpringSecurity0/src/main/java/com/us/example/util/MD5Util.java ================================================ package com.us.example.util; /** * Created by yangyibo on 17/2/7. */ import java.security.MessageDigest; /** * MD5加密工具 * */ public class MD5Util { private static final String SALT = "tamboo"; public static String encode(String password) { password = password + SALT; MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { throw new RuntimeException(e); } char[] charArray = password.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } public static void main(String[] args) { System.out.println(MD5Util.encode("abel")); } } ================================================ FILE: springboot-SpringSecurity0/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?characterEncoding=utf-8&useSSL=false ms.db.username=root ms.db.password=admin ms.db.maxActive=500 logging.level.org.springframework.security= INFO spring.thymeleaf.cache=false ================================================ FILE: springboot-SpringSecurity0/src/main/resources/mapper/UserDaoMapper.xml ================================================ ================================================ FILE: springboot-SpringSecurity0/src/main/resources/templates/home.html ================================================

无更多信息显示

================================================ FILE: springboot-SpringSecurity0/src/main/resources/templates/login.html ================================================ 登录页面

已成功注销

有错误,请重试

使用账号密码登录

================================================ FILE: springboot-SpringSecurity1/pom.xml ================================================ 4.0.0 com.us springboot-security1 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.example.Application 1.8 1.8 3.2.7 1.2.2 org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} org.apache.maven.plugins maven-shade-plugin 2.3 package shade ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/config/DBconfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * Created by yangyibo on 17/1/18. */ @Configuration public class DBconfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/config/MyBatisConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration @ComponentScan public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()}); sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/config/MyBatisScannerConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/config/TransactionConfig.java ================================================ package com.us.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/config/WebSecurityConfig.java ================================================ package com.us.example.config; import com.us.example.service.CustomUserService; import com.us.example.service.MyFilterSecurityInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; /** * Created by yangyibo on 17/1/18. */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyFilterSecurityInterceptor myFilterSecurityInterceptor; @Autowired UserDetailsService customUserService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService); //user Details Service验证 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/css/**").permitAll() .anyRequest().authenticated() //任何请求,登录后可以访问 .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/") .failureUrl("/login?error") .permitAll() //登录页面用户任意访问 .and() .logout().permitAll(); //注销行为任意访问 http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class); } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/controller/HomeController.java ================================================ package com.us.example.controller; import com.us.example.domain.Msg; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * Created by yangyibo on 17/1/18. */ @Controller public class HomeController { @RequestMapping("/") public String index(Model model){ Msg msg = new Msg("测试标题","测试内容","欢迎来到HOME页面,您拥有 ROLE_HOME 权限"); model.addAttribute("msg", msg); return "home"; } @RequestMapping("/login") public String login(){ return "login"; } @RequestMapping("/admin") @ResponseBody public String hello(){ return "hello admin"; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/dao/PermissionDao.java ================================================ package com.us.example.dao; import com.us.example.domain.Permission; import java.util.List; /** * Created by yangyibo on 17/1/20. */ public interface PermissionDao { public List findAll(); public List findByAdminUserId(int userId); } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/dao/UserDao.java ================================================ package com.us.example.dao; import com.us.example.domain.SysUser; public interface UserDao { public SysUser findByUserName(String username); } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/domain/Msg.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class Msg { private String title; private String content; private String etraInfo; public Msg(String title, String content, String etraInfo) { super(); this.title = title; this.content = content; this.etraInfo = etraInfo; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getEtraInfo() { return etraInfo; } public void setEtraInfo(String etraInfo) { this.etraInfo = etraInfo; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/domain/Permission.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/20. */ public class Permission { private int id; //权限名称 private String name; //权限描述 private String descritpion; //授权链接 private String url; //父节点id private int pid; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescritpion() { return descritpion; } public void setDescritpion(String descritpion) { this.descritpion = descritpion; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/domain/SysRole.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class SysRole { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/domain/SysUser.java ================================================ package com.us.example.domain; import java.util.List; /** * Created by yangyibo on 17/1/17. */ public class SysUser { private Integer id; private String username; private String password; private List roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/service/CustomUserService.java ================================================ package com.us.example.service; import com.us.example.dao.PermissionDao; import com.us.example.dao.UserDao; import com.us.example.domain.Permission; import com.us.example.domain.SysRole; import com.us.example.domain.SysUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/1/18. */ @Service public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口 @Autowired UserDao userDao; @Autowired PermissionDao permissionDao; public UserDetails loadUserByUsername(String username) { SysUser user = userDao.findByUserName(username); if (user != null) { List permissions = permissionDao.findByAdminUserId(user.getId()); List grantedAuthorities = new ArrayList <>(); for (Permission permission : permissions) { if (permission != null && permission.getName()!=null) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName()); grantedAuthorities.add(grantedAuthority); } } return new User(user.getUsername(), user.getPassword(), grantedAuthorities); } else { throw new UsernameNotFoundException("admin: " + username + " do not exist!"); } } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/service/MyAccessDecisionManager.java ================================================ package com.us.example.service; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.Iterator; /** * Created by yangyibo on 17/1/19. */ @Service public class MyAccessDecisionManager implements AccessDecisionManager { @Override public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(null== configAttributes || configAttributes.size() <=0) { return; } ConfigAttribute c; String needRole; for(Iterator iter = configAttributes.iterator(); iter.hasNext(); ) { c = iter.next(); needRole = c.getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()) { if(needRole.trim().equals(ga.getAuthority())) { return; } } } throw new AccessDeniedException("no right"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class clazz) { return true; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/service/MyFilterSecurityInterceptor.java ================================================ package com.us.example.service; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import java.io.IOException; /** * Created by yangyibo on 17/1/19. */ @Service public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { @Autowired private FilterInvocationSecurityMetadataSource securityMetadataSource; @Autowired public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { super.setAccessDecisionManager(myAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi里面有一个被拦截的url //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); try { //执行下一个拦截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } } ================================================ FILE: springboot-SpringSecurity1/src/main/java/com/us/example/service/MyInvocationSecurityMetadataSourceService.java ================================================ package com.us.example.service; import com.us.example.dao.PermissionDao; import com.us.example.domain.Permission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * Created by yangyibo on 17/1/19. */ @Service public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { @Autowired private PermissionDao permissionDao; private HashMap> map =null; /** * 加载资源,初始化资源变量 */ public void loadResourceDefine(){ map = new HashMap<>(); Collection array; ConfigAttribute cfg; List permissions = permissionDao.findAll(); for(Permission permission : permissions) { array = new ArrayList<>(); cfg = new SecurityConfig(permission.getName()); array.add(cfg); map.put(permission.getUrl(), array); } } @Override public Collection getAttributes(Object object) throws IllegalArgumentException { if(map ==null) loadResourceDefine(); HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); AntPathRequestMatcher matcher; String resUrl; for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) { resUrl = iter.next(); matcher = new AntPathRequestMatcher(resUrl); if(matcher.matches(request)) { return map.get(resUrl); } } return null; } @Override public Collection getAllConfigAttributes() { return null; } @Override public boolean supports(Class clazz) { return true; } } ================================================ FILE: springboot-SpringSecurity1/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?characterEncoding=utf-8&useSSL=false ms.db.username=root ms.db.password=admin ms.db.maxActive=500 server.port=8081 logging.level.org.springframework.security= INFO ================================================ FILE: springboot-SpringSecurity1/src/main/resources/mapper/PermissionDaoMapper.xml ================================================ ================================================ FILE: springboot-SpringSecurity1/src/main/resources/mapper/UserDaoMapper.xml ================================================ ================================================ FILE: springboot-SpringSecurity1/src/main/resources/templates/home.html ================================================

恭喜您,您有 ROLE_ADMIN 权限

================================================ FILE: springboot-SpringSecurity1/src/main/resources/templates/login.html ================================================ 登录页面

已成功注销

有错误,请重试

使用账号密码登录

================================================ FILE: springboot-dubbo/README.md ================================================ ##springboot-dubbo 该项目是Springboot 和 dubbo 结合的例子,是provider 的示例,提供服务。简单的写了一些用户和权限的接口没有写的很完整,主要是为了提现dubbo 服务 Springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 ### abel-user-api 该模块是让消费者 引用的 api 模块,主要用来定义接口和数据传输实体 ### abel-user-provider 该模块是真正的微服务提供者 ================================================ FILE: springboot-dubbo/abel-user-api/pom.xml ================================================ 4.0.0 cn.abel abel-parent 1.0.0-SNAPSHOT cn.abel abel-user-api 1.0.0-SNAPSHOT jar com.github.pagehelper pagehelper-spring-boot-starter com.fasterxml.jackson.core jackson-core com.fasterxml.jackson.core jackson-databind org.apache.maven.plugins maven-source-plugin attach-sources jar ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Permission.java ================================================ package cn.abel.user.models; import java.io.Serializable; public class Permission implements Serializable { private static final long serialVersionUID = 2079120477173696231L; private Integer id; private String name; private String permissionUrl; private String method; private String description; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPermissionUrl() { return permissionUrl; } public void setPermissionUrl(String permissionUrl) { this.permissionUrl = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Permission{" + "id=" + id + ", name=" + name + ", permissionUrl=" + permissionUrl + ", method=" + method + ", description=" + description + '}'; } } ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/Role.java ================================================ package cn.abel.user.models; import java.io.Serializable; public class Role implements Serializable { private static final long serialVersionUID = -4873217276773065821L; private Integer id; private String name; private Integer roleLevel; private String description; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getRoleLevel() { return roleLevel; } public void setRoleLevel(Integer roleLevel) { this.roleLevel = roleLevel; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Role{" + "id=" + id + ", name=" + name + ", roleLevel=" + roleLevel + ", description=" + description + '}'; } } ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/models/User.java ================================================ package cn.abel.user.models; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.List; public class User implements Serializable { private static final long serialVersionUID = -4523695542426439365L; private Integer id; private String cnname; private String username; @JsonIgnore private String password; private String email; private String mobilePhone; private List roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCnname() { return cnname; } public void setCnname(String cnname) { this.cnname = cnname; } public String getUsername() { return username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobilePhone() { return mobilePhone; } public void setMobilePhone(String mobilePhone) { this.mobilePhone = mobilePhone; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } @Override public String toString() { return "User{" + "id=" + id + ", cnname=" + cnname + ", username=" + username + ", password=" + password + ", email=" + email + ", mobilePhone=" + mobilePhone + '}'; } } ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/PermissionService.java ================================================ package cn.abel.user.service; import cn.abel.user.models.Permission; import java.util.List; import java.util.Map; public interface PermissionService { List getByMap(Map map); Permission getById(Integer id); Permission create(Permission permission); Permission update(Permission permission); int delete(Integer id); } ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/RoleService.java ================================================ package cn.abel.user.service; import cn.abel.user.models.Role; import java.util.List; import java.util.Map; public interface RoleService { List getByMap(Map map); Role getById(Integer id); Role create(Role role); Role update(Role role); int delete(Integer id); } ================================================ FILE: springboot-dubbo/abel-user-api/src/main/java/cn/abel/user/service/UserService.java ================================================ package cn.abel.user.service; import cn.abel.user.models.User; import java.util.List; import java.util.Map; public interface UserService { List getByMap(Map map); User getById(Integer id); User create(User user); User update(User user); int delete(Integer id); User getByUserName(String userName); } ================================================ FILE: springboot-dubbo/abel-user-provider/doc/user.sql ================================================ /* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50719 Source Host : 127.0.0.1:3306 Source Schema : shiro Target Server Type : MySQL Target Server Version : 50719 File Encoding : 65001 Date: 20/03/2020 10:51:00 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for permission -- ---------------------------- DROP TABLE IF EXISTS `permission`; CREATE TABLE `permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) COLLATE utf8_bin NOT NULL, `permission_url` varchar(100) COLLATE utf8_bin DEFAULT NULL, `method` varchar(100) COLLATE utf8_bin DEFAULT NULL, `description` varchar(1000) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Table structure for role -- ---------------------------- DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) COLLATE utf8_bin NOT NULL, `role_level` int(1) DEFAULT NULL, `description` varchar(1000) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Table structure for role_permission -- ---------------------------- DROP TABLE IF EXISTS `role_permission`; CREATE TABLE `role_permission` ( `role_id` int(11) NOT NULL, `permission_id` int(11) NOT NULL, PRIMARY KEY (`role_id`,`permission_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `cnname` varchar(50) COLLATE utf8_bin DEFAULT NULL, `username` varchar(50) COLLATE utf8_bin NOT NULL, `password` varchar(100) COLLATE utf8_bin NOT NULL, `email` varchar(100) COLLATE utf8_bin DEFAULT NULL, `mobile_phone` varchar(50) COLLATE utf8_bin DEFAULT NULL, `status` int(11) DEFAULT '4' COMMENT '用户登录状态,1 : 在线 2 离开 3 忙碌 4 离线', PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; -- ---------------------------- -- Table structure for user_role -- ---------------------------- DROP TABLE IF EXISTS `user_role`; CREATE TABLE `user_role` ( `user_id` int(11) NOT NULL, `role_id` int(11) NOT NULL, PRIMARY KEY (`user_id`,`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; SET FOREIGN_KEY_CHECKS = 1; ================================================ FILE: springboot-dubbo/abel-user-provider/pom.xml ================================================ 4.0.0 cn.abel abel-parent 1.0.0-SNAPSHOT cn.abel abel-user-provider 1.0.0 jar cn.abel abel-user-api 1.0.0-SNAPSHOT cn.abel abel-util 1.0.0-SNAPSHOT org.apache.commons commons-pool2 com.alibaba fastjson 1.2.58 org.apache.commons commons-collections4 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-test test com.fasterxml.jackson.core jackson-core com.fasterxml.jackson.core jackson-databind org.mybatis.spring.boot mybatis-spring-boot-starter com.github.pagehelper pagehelper-spring-boot-starter mysql mysql-connector-java com.alibaba dubbo org.slf4j log4j-over-slf4j org.apache.zookeeper zookeeper org.jboss.resteasy resteasy-jaxrs org.jboss.resteasy resteasy-client org.jboss.resteasy resteasy-jackson-provider javax.validation validation-api org.hibernate.validator hibernate-validator com.101tec zkclient org.apache.httpcomponents httpcore org.apache.httpcomponents httpcore-nio org.apache.httpcomponents httpclient org.apache.httpcomponents httpasyncclient it.uniroma1.dis.wsngroup.gexf4j gexf4j 1.0.0 io.sentry sentry-logback 1.7.3 com.fasterxml.jackson.core jackson-databind org.apache.curator curator-framework 2.5.0 org.javassist javassist 3.15.0-GA org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/UserProviderApplication.java ================================================ package cn.abel.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication @ImportResource("classpath*:META-INF/spring/*.xml") public class UserProviderApplication { public static void main(String[] args) { SpringApplication.run(UserProviderApplication.class, args); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/constants/Constants.java ================================================ package cn.abel.user.constants; /** * 公用的常量类。 */ public interface Constants { } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/PermissionDao.java ================================================ package cn.abel.user.dao; import cn.abel.user.models.Permission; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; @Repository @Mapper public interface PermissionDao { List getByMap(Map map); Permission getById(Integer id); Integer create(Permission permission); int update(Permission permission); int delete(Integer id); List getList(); List getByUserId(Integer userId); } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/RoleDao.java ================================================ package cn.abel.user.dao; import cn.abel.user.models.Role; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; @Repository @Mapper public interface RoleDao { List getByMap(Map map); Role getById(Integer id); Integer create(Role role); int update(Role role); int delete(Integer id); } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/dao/UserDao.java ================================================ package cn.abel.user.dao; import cn.abel.user.models.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; @Repository @Mapper public interface UserDao { List getByMap(Map map); User getById(Integer id); Integer create(User user); int update(User user); int delete(Integer id); User getByUserName(String userName); } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/JsonExceptionMapper.java ================================================ package cn.abel.user.exception; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import cn.abel.code.InfoCode; import cn.abel.response.ResponseEntity; import org.codehaus.jackson.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * json转换错误 * * @author ye * @date 2018/11/02 14:20 */ public class JsonExceptionMapper implements ExceptionMapper { /** logger */ private static final Logger logger = LoggerFactory.getLogger(JsonExceptionMapper.class); @Override public Response toResponse(JsonProcessingException exception) { ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR); logger.info("{}", InfoCode.REQUEST_PARAM_ERROR.getMsg()); return Response.ok(entity, MediaType.APPLICATION_JSON).build(); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ReaderExceptionMapper.java ================================================ package cn.abel.user.exception; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import cn.abel.code.InfoCode; import cn.abel.response.ResponseEntity; import org.jboss.resteasy.spi.ReaderException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * json转换错误 * * @author ye * @date 2018/11/02 14:20 */ public class ReaderExceptionMapper implements ExceptionMapper { /** logger */ private static final Logger logger = LoggerFactory.getLogger(ReaderExceptionMapper.class); @Override public Response toResponse(ReaderException exception) { ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR); logger.info("{}", InfoCode.REQUEST_PARAM_ERROR.getMsg()); return Response.ok(entity, MediaType.APPLICATION_JSON).build(); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/RestExceptionMapper.java ================================================ package cn.abel.user.exception; import javax.ws.rs.NotAllowedException; import javax.ws.rs.NotFoundException; import javax.ws.rs.NotSupportedException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * http调用错误 * * @author ye * @date 2018/11/02 14:20 */ public class RestExceptionMapper implements ExceptionMapper { /** logger */ private static final Logger logger = LoggerFactory.getLogger(WebApplicationException.class); @Override public Response toResponse(WebApplicationException e) { if (e instanceof NotAllowedException) { logger.info("method错误。{}", e.getMessage()); return null; } //415 if (e instanceof NotSupportedException) { logger.info("content-type错误。{}", e.getMessage()); return null; } if (e instanceof NotFoundException) { logger.info("url错误。{}", e.getMessage()); return null; } return null; } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ServiceExceptionMapper.java ================================================ package cn.abel.user.exception; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import cn.abel.exception.ServiceException; import cn.abel.response.ResponseEntity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ServiceExceptionMapper * * @author ye * @date 2018/11/02 14:20 */ public class ServiceExceptionMapper implements ExceptionMapper { /** logger */ private static final Logger logger = LoggerFactory.getLogger(ServiceException.class); @Override public Response toResponse(ServiceException exception) { ResponseEntity entity = ResponseEntity.error(exception.getErrorCode(), exception.getMessage()); logger.error("{},{}", exception.getErrorCode(), exception.getMessage()); return Response.ok(entity, MediaType.APPLICATION_JSON).build(); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/exception/ValidationExceptionMapper.java ================================================ package cn.abel.user.exception; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import javax.ws.rs.core.Response; import cn.abel.code.InfoCode; import cn.abel.response.ResponseEntity; import com.alibaba.dubbo.rpc.protocol.rest.RpcExceptionMapper; import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType; /** * 参数校验异常 * * @author ye * @date 2018/11/04 16:53 */ public class ValidationExceptionMapper extends RpcExceptionMapper { @Override protected Response handleConstraintViolationException(ConstraintViolationException cve) { //ViolationReport report = new ViolationReport(); String msg = ""; for (ConstraintViolation cv : cve.getConstraintViolations()) { //report.addConstraintViolation(new RestConstraintViolation(cv.getPropertyPath().toString(), // cv.getMessage(), cv.getInvalidValue() == null ? "null" : cv.getInvalidValue().toString())); msg = cv.getPropertyPath().toString() + " " + cv.getMessage(); } ResponseEntity entity = ResponseEntity.error(InfoCode.REQUEST_PARAM_ERROR.getStatus(), InfoCode.REQUEST_PARAM_ERROR.getMsg() + "(" + msg + ")"); // 采用json输出代替xml输出 return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(entity).type(ContentType.APPLICATION_JSON_UTF_8).build(); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestFilter.java ================================================ package cn.abel.user.filter; import java.io.IOException; import java.util.List; import java.util.Map; import javax.annotation.Priority; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientResponseContext; import javax.ws.rs.client.ClientResponseFilter; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.MultivaluedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 日志-复制并替代com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter * * @author ye * @date 2018/11/02 15:20 */ @Priority(900) @PreMatching public class RestFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, ClientResponseFilter { /** logger */ private static final Logger logger = LoggerFactory.getLogger(RestFilter.class); @Override public void filter(ClientRequestContext context) throws IOException { logHttpHeaders(context.getStringHeaders()); } @Override public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { logHttpHeaders(responseContext.getHeaders()); } @Override public void filter(ContainerRequestContext context) throws IOException { logHttpHeaders(context.getHeaders()); } @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { logHttpHeaders(responseContext.getStringHeaders()); } protected void logHttpHeaders(MultivaluedMap headers) { StringBuilder msg = new StringBuilder("The HTTP headers are: \n"); for (Map.Entry> entry : headers.entrySet()) { msg.append(entry.getKey()).append(": "); for (int i = 0; i < entry.getValue().size(); i++) { msg.append(entry.getValue().get(i)); if (i < entry.getValue().size() - 1) { msg.append(", "); } } msg.append("\n"); } logger.info(msg.toString()); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/filter/RestInterceptor.java ================================================ package cn.abel.user.filter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.ws.rs.WebApplicationException; import javax.ws.rs.ext.ReaderInterceptor; import javax.ws.rs.ext.ReaderInterceptorContext; import javax.ws.rs.ext.WriterInterceptor; import javax.ws.rs.ext.WriterInterceptorContext; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 日志-复制并替代com.alibaba.dubbo.rpc.protocol.rest.support.LoggingFilter * * @author ye * @date 2018/11/04 16:34 */ public class RestInterceptor implements WriterInterceptor, ReaderInterceptor { /** logger */ private static final Logger logger = LoggerFactory.getLogger(RestInterceptor.class); @Override public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException { byte[] buffer = IOUtils.toByteArray(context.getInputStream()); logger.info("The contents of request body is: \n" + new String(buffer, "UTF-8") + "\n"); context.setInputStream(new ByteArrayInputStream(buffer)); return context.proceed(); } @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { RestInterceptor.OutputStreamWrapper wrapper = new RestInterceptor.OutputStreamWrapper(context.getOutputStream()); context.setOutputStream(wrapper); context.proceed(); logger.info("The contents of response body is: \n" + new String(wrapper.getBytes(), "UTF-8") + "\n"); } protected static class OutputStreamWrapper extends OutputStream { private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); private final OutputStream output; private OutputStreamWrapper(OutputStream output) { this.output = output; } @Override public void write(int i) throws IOException { buffer.write(i); output.write(i); } @Override public void write(byte[] b) throws IOException { buffer.write(b); output.write(b); } @Override public void write(byte[] b, int off, int len) throws IOException { buffer.write(b, off, len); output.write(b, off, len); } @Override public void flush() throws IOException { output.flush(); } @Override public void close() throws IOException { output.close(); } public byte[] getBytes() { return buffer.toByteArray(); } } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/PermissionServiceImpl.java ================================================ package cn.abel.user.service.impl; import cn.abel.user.dao.PermissionDao; import cn.abel.user.models.Permission; import cn.abel.user.service.PermissionService; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.Map; @Service(protocol = {"dubbo"}, validation = "false") public class PermissionServiceImpl implements PermissionService { @Autowired private PermissionDao permissionDao; @Override public List getByMap(Map map) { return permissionDao.getByMap(map); } @Override public Permission getById(Integer id) { return permissionDao.getById(id); } @Override public Permission create(Permission permission) { permissionDao.create(permission); return permission; } @Override public Permission update(Permission permission) { permissionDao.update(permission); return permission; } @Override public int delete(Integer id) { return permissionDao.delete(id); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/RoleServiceImpl.java ================================================ package cn.abel.user.service.impl; import cn.abel.user.dao.RoleDao; import cn.abel.user.models.Role; import cn.abel.user.service.RoleService; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.Map; @Service(protocol = {"dubbo"}, validation = "false") public class RoleServiceImpl implements RoleService{ @Autowired private RoleDao roleDao; @Override public List getByMap(Map map) { return roleDao.getByMap(map); } @Override public Role getById(Integer id) { return roleDao.getById(id); } @Override public Role create(Role role) { roleDao.create(role); return role; } @Override public Role update(Role role) { roleDao.update(role); return role; } @Override public int delete(Integer id) { return roleDao.delete(id); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/service/impl/UserServiceImpl.java ================================================ package cn.abel.user.service.impl; import cn.abel.user.dao.UserDao; import cn.abel.user.models.User; import cn.abel.user.service.UserService; import com.alibaba.dubbo.config.annotation.Service; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.Map; @Service(protocol = {"dubbo"}, validation = "false") public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public List getByMap(Map map) { return userDao.getByMap(map); } @Override public User getById(Integer id) { return userDao.getById(id); } @Override public User create(User user) { userDao.create(user); return user; } @Override public User update(User user) { userDao.update(user); return user; } @Override public int delete(Integer id) { return userDao.delete(id); } @Override public User getByUserName(String userName) { return userDao.getByUserName(userName); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/java/cn/abel/user/utils/CommentUtils.java ================================================ package cn.abel.user.utils; import com.alibaba.fastjson.JSON; import org.apache.commons.collections4.CollectionUtils; import java.util.ArrayList; import java.util.List; /** * @author yyb * @time 2020/3/10 */ public class CommentUtils { /** * * @param list * @param * @return */ public static List copyList(List list) { if (CollectionUtils.isEmpty(list)) { return new ArrayList(); } return JSON.parseArray(JSON.toJSONString(list), list.get(0).getClass()); } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/META-INF/spring/provider.xml ================================================ ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/dev/application.properties ================================================ #application spring.application.name=abel-user-provider application.main=cn.abel.user.UserProviderApplication server.port=9658 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 server.tomcat.max-threads=200 server.session-timeout=60 log4j.logger.java.sql.Connection=DEBUG #dubbo dubbo.application.name=abel-user-provider dubbo.registry.group=abel dubbo.registry.address=127.0.0.1:2181 dubbo.registry.version=1.0.0 dubbo.protocol.port=12885 dubbo.protocol.rest.port=12886 dubbo.annotation.package=cn.abel.user dubbo.log.file=/logs/abel-user-provider/abel-user-provider-dubbo.log #db spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver #DataSource spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.hikari.minimum-idle=10 spring.datasource.hikari.maximum-pool-size=30 spring.datasource.hikari.idle-timeout=120000 spring.datasource.hikari.max-lifetime=1800000 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.validation-timeout=3000 spring.datasource.hikari.connection-test-query=SELECT 1 #mybatis logging.level.cn.abel.user.dao=info mybatis.type-aliases-package=cn.abel.user.model mybatis.mapper-locations=classpath*:mapper/*Mapper.xml #PageHelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql logging.file=/logs/abel-user-provider/abel-user-provider.log ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/dev/banner.txt ================================================ ######################################################## # # # dev # # # ######################################################## ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/dev/logback-spring.xml ================================================ abel_user %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/local/application.properties ================================================ #application spring.application.name=abel-user-provider application.main=cn.abel.user.UserProviderApplication server.port=9658 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 server.tomcat.max-threads=200 server.session-timeout=60 log4j.logger.java.sql.Connection=DEBUG #dubbo dubbo.application.name=abel-user-provider dubbo.registry.group=abel dubbo.registry.address=127.0.0.1:2181 dubbo.registry.version=1.0.0 dubbo.protocol.port=12885 dubbo.protocol.rest.port=12886 dubbo.annotation.package=cn.abel.user dubbo.log.file=./logs/abel-user-provider/abel-user-provider-dubbo.log #db spring.datasource.url=jdbc:mysql://127.0.0.1:3306/shiro?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver #DataSource spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.hikari.minimum-idle=10 spring.datasource.hikari.maximum-pool-size=30 spring.datasource.hikari.idle-timeout=120000 spring.datasource.hikari.max-lifetime=1800000 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.validation-timeout=3000 spring.datasource.hikari.connection-test-query=SELECT 1 #mybatis logging.level.cn.abel.user.dao=info mybatis.type-aliases-package=cn.abel.user.model mybatis.mapper-locations=classpath*:mapper/*Mapper.xml #PageHelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql logging.file=./logs/abel-user-provider/abel-user-provider.log ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/local/logback-spring.xml ================================================ abel_user %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/mapper/PermissionDaoMapper.xml ================================================ and id = #{id} and name = #{name} and permission_url = #{permissionUrl} and method = #{method} and description = #{description} SELECT LAST_INSERT_ID() INSERT INTO permission( id, name, permission_url, method, description )VALUES( #{id}, #{name}, #{permissionUrl}, #{method}, #{description} ) UPDATE permission SET name = #{name}, permission_url = #{permissionUrl}, method = #{method}, description = #{description} WHERE id = #{id} DELETE FROM permission WHERE id = #{id} ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/mapper/RoleDaoMapper.xml ================================================ and id = #{id} and name = #{name} and role_level = #{roleLevel} and description = #{description} SELECT LAST_INSERT_ID() INSERT INTO role( id, name, role_level, description )VALUES( #{id}, #{name}, #{roleLevel}, #{description} ) UPDATE role SET name = #{name}, role_level = #{roleLevel}, description = #{description} WHERE id = #{id} DELETE FROM role WHERE id = #{id} ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/resources/mapper/UserDaoMapper.xml ================================================ and id = #{id} and cnname = #{cnname} and username = #{username} and password = #{password} and email = #{email} and mobile_phone = #{mobilePhone} and ( cnname like CONCAT('%', #{keywords},'%') OR username like CONCAT('%', #{keywords},'%') OR mobile_phone like CONCAT('%', #{keywords},'%') OR email like CONCAT('%', #{keywords},'%') ) SELECT LAST_INSERT_ID() INSERT INTO user( id, cnname, username, password, email, mobile_phone )VALUES( #{id}, #{cnname}, #{username}, #{password}, #{email}, #{mobilePhone} ) UPDATE user SET cnname = #{cnname}, username = #{username}, password = #{password}, email = #{email}, mobile_phone = #{mobilePhone} WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/BaseTest.java ================================================ package cn.abel.user; /** * @author yyb * @time 2020/3/9 */ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest(classes = UserProviderApplication.class) @TestPropertySource("/application.properties") public class BaseTest { @Configuration @ComponentScan(basePackages = {"cn.abel.user"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } @Test public void contextLoads() { } } ================================================ FILE: springboot-dubbo/abel-user-provider/src/main/test/cn/abel/user/service/impl/PermissionServiceImplTest.java ================================================ package cn.abel.user.service.impl; import cn.abel.user.BaseTest; import cn.abel.user.models.Permission; import cn.abel.user.service.PermissionService; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import static org.junit.Assert.*; /** * @author yyb * @time 2020/3/20 */ public class PermissionServiceImplTest extends BaseTest { @Autowired private PermissionService permissionService; @Test public void getByMap() throws Exception { permissionService.getByMap(null); } @Test public void getById() throws Exception { Permission permission = permissionService.getById(1); System.out.println(); } @Test public void create() throws Exception { Permission permission = new Permission(); permission.setDescription("234234"); permission.setName("新增"); permission.setMethod("nicai"); permission.setPermissionUrl("zsdfsf_sf"); permissionService.create(permission); } @Test public void update() throws Exception { Permission permission = new Permission(); permission.setId(1); permission.setDescription("234234"); permission.setName("新增"); permission.setMethod("nicai"); permission.setPermissionUrl("zsdfsf_sf"); permissionService.update(permission); } @Test public void delete() throws Exception { permissionService.delete(1); } } ================================================ FILE: springboot-dynamicDataSource/pom.xml ================================================ 4.0.0 cn.abel springboot-dynamicDataSource 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-freemarker org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2 com.github.pagehelper pagehelper-spring-boot-starter 1.2.5 mysql mysql-connector-java 5.1.40 org.apache.commons commons-lang3 3.4 ================================================ FILE: springboot-dynamicDataSource/sql/news.sql ================================================ /* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50719 Source Host : 127.0.0.1 Source Database : oldMan Target Server Type : MySQL Target Server Version : 50719 File Encoding : utf-8 Date: 04/02/2019 15:38:58 PM */ SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for `news` -- ---------------------------- DROP TABLE IF EXISTS `news`; CREATE TABLE `news` ( `id` int(11) NOT NULL, `title` varchar(100) DEFAULT NULL, `content` text, `image_path` varchar(100) DEFAULT NULL, `read_sum` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; SET FOREIGN_KEY_CHECKS = 1; ================================================ FILE: springboot-dynamicDataSource/sql/user.sql ================================================ /* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50719 Source Host : 127.0.0.1 Source Database : oldMan Target Server Type : MySQL Target Server Version : 50719 File Encoding : utf-8 Date: 04/02/2019 15:27:32 PM */ SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `address` varchar(200) DEFAULT NULL, `mobile` varchar(50) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `role` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; SET FOREIGN_KEY_CHECKS = 1; ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/Application.java ================================================ package cn.abel; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/3/26 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/bean/News.java ================================================ package cn.abel.bean; public class News { private Integer id; private String title; private String content; private String imagePath; private Integer readSum; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } public Integer getReadSum() { return readSum; } public void setReadSum(Integer readSum) { this.readSum = readSum; } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/bean/User.java ================================================ package cn.abel.bean; import java.util.Date; public class User { private Integer id; private String name; private String address; private String mobile; private String email; private Date createTime; private Integer role; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Integer getRole() { return role; } public void setRole(Integer role) { this.role = role; } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSource.java ================================================ package cn.abel.config; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @author yyb * @time 2019/3/27 */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDatabaseType(); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceConfig.java ================================================ package cn.abel.config; import cn.abel.enums.DatabaseTypeEnum; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * @author yyb * @time 2019/3/27 */ @Configuration @MapperScan(basePackages = "cn.abel.dao") public class DynamicDataSourceConfig { @Value("${spring.datasource.primary.url}") private String primaryUrl; @Value("${spring.datasource.user.url}") private String userUrl; @Value("${mybatis.mapper-locations}") private String resources; //当两个数据库连接账号密码不一样时 // @Value("${spring.datasource.user.username}") // private String userName; // @Value("${spring.datasource.user.password}") // private String password; @Autowired private HikariConfig hikariConfig; @Primary @Bean(name = "primaryDataSource") public DataSource getPrimaryDataSource() { return hikariConfig.getHikariDataSource(primaryUrl); } @Bean(name = "userDataSource") public DataSource getUserDataSource() { return hikariConfig.getHikariDataSource(userUrl); } //当两个数据库连接账号密码不一样时使用 // @Bean(name = "userDataSource") // public DataSource getUserDataSource() { // return hikariConfig.getHikariDataSource(userUrl, userName, password); // } @Bean("dynamicDataSource") public DynamicDataSource dynamicDataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource, @Qualifier("userDataSource") DataSource userDataSource) { Map targetDataSources = new HashMap<>(); targetDataSources.put(DatabaseTypeEnum.PRIMARY, primaryDataSource); targetDataSources.put(DatabaseTypeEnum.USER, userDataSource); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法 dataSource.setDefaultTargetDataSource(primaryDataSource);// 默认的datasource设置为myTestDbDataSource return dataSource; } /** * 根据数据源创建SqlSessionFactory */ @Bean public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dynamicDataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(resources)); return bean.getObject(); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/config/DynamicDataSourceContextHolder.java ================================================ package cn.abel.config; import cn.abel.enums.DatabaseTypeEnum; /** * @author yyb * @time 2019/3/27 */ public class DynamicDataSourceContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal<>(); public static void setDatabaseType(DatabaseTypeEnum type){ contextHolder.set(type); } public static DatabaseTypeEnum getDatabaseType(){ return contextHolder.get(); } public static void resetDatabaseType() { contextHolder.set(DatabaseTypeEnum.PRIMARY); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/config/HikariConfig.java ================================================ package cn.abel.config; import com.zaxxer.hikari.HikariDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; /** * @author yyb * @time 2019/3/27 */ @Service public class HikariConfig { @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${spring.datasource.min-idle}") private Integer minIdle; @Value("${spring.datasource.max-active}") private Integer maxActive; @Value("${spring.datasource.validation-query}") private String validationQuery; @Value("${spring.datasource.connection-timeout}") private Integer connectionTimeout; @Value("${spring.datasource.max-left-time}") private Integer maxLeftTime; @Value("${spring.datasource.validation-time-out}") private Integer validationTimeout; @Value("${spring.datasource.idle-time-out}") private Integer idleTimeout; @Value("${spring.datasource.connection-init-sql}") private String connectionInitSql; /** * 配置Hikari数据连接池 * * @param url 数据源 * @return 连接池对象 */ public HikariDataSource getHikariDataSource(String url) { com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig(); config.setMinimumIdle(minIdle); config.setMaximumPoolSize(maxActive); config.setConnectionTestQuery(validationQuery); config.setJdbcUrl(url); config.setUsername(userName); config.setPassword(password); config.setDriverClassName(driverClassName); config.setConnectionTimeout(connectionTimeout); config.setMaxLifetime(maxLeftTime); config.setValidationTimeout(validationTimeout); config.setConnectionInitSql(connectionInitSql); return new HikariDataSource(config); } /** * 用于两个库账号密码不一样的时候 * * @param url * @param userName * @param passwod * @return */ public HikariDataSource getHikariDataSource(String url, String userName, String passwod) { com.zaxxer.hikari.HikariConfig config = new com.zaxxer.hikari.HikariConfig(); config.setMinimumIdle(minIdle); config.setMaximumPoolSize(maxActive); config.setConnectionTestQuery(validationQuery); config.setJdbcUrl(url); config.setUsername(userName); config.setPassword(passwod); config.setConnectionTimeout(connectionTimeout); config.setDriverClassName(driverClassName); config.setMaxLifetime(maxLeftTime); config.setValidationTimeout(validationTimeout); config.setConnectionInitSql(connectionInitSql); return new HikariDataSource(config); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/dao/NewsDao.java ================================================ package cn.abel.dao; import java.util.List; import java.util.Map; import cn.abel.bean.News; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Repository @Mapper public interface NewsDao { List getByMap(Map map); News getById(Integer id); Integer create(News news); int update(News news); int delete(Integer id); } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/dao/UserDao.java ================================================ package cn.abel.dao; import java.util.List; import java.util.Map; import cn.abel.bean.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Repository @Mapper public interface UserDao { List getByMap(Map map); User getById(Integer id); Integer create(User user); int update(User user); int delete(Integer id); } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/enums/DatabaseTypeEnum.java ================================================ package cn.abel.enums; /** * @author yyb * @time 2019/3/27 */ public enum DatabaseTypeEnum { PRIMARY("1"), USER("2"); private String code; DatabaseTypeEnum(String code) { this.code = code; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public static DatabaseTypeEnum getDatabaseTypeEnum(String code) { for (DatabaseTypeEnum databaseTypeEnum : DatabaseTypeEnum.values()) { if (databaseTypeEnum.getCode().equals(code)) { return databaseTypeEnum; } } return null; } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/service/NewsService.java ================================================ package cn.abel.service; import java.util.List; import java.util.Map; import cn.abel.config.DynamicDataSource; import cn.abel.config.DynamicDataSourceContextHolder; import cn.abel.enums.DatabaseTypeEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import cn.abel.dao.NewsDao; import cn.abel.bean.News; @Service public class NewsService { @Autowired private NewsDao newsDao; public List getByMap(Map map) { DynamicDataSourceContextHolder.resetDatabaseType(); return newsDao.getByMap(map); } public News getById(Integer id) { DynamicDataSourceContextHolder.resetDatabaseType(); return newsDao.getById(id); } public News create(News news) { DynamicDataSourceContextHolder.resetDatabaseType(); newsDao.create(news); return news; } public News update(News news) { DynamicDataSourceContextHolder.resetDatabaseType(); newsDao.update(news); return news; } public int delete(Integer id) { DynamicDataSourceContextHolder.resetDatabaseType(); return newsDao.delete(id); } } ================================================ FILE: springboot-dynamicDataSource/src/main/java/cn/abel/service/UserService.java ================================================ package cn.abel.service; import java.util.List; import java.util.Map; import cn.abel.config.DynamicDataSourceContextHolder; import cn.abel.enums.DatabaseTypeEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import cn.abel.dao.UserDao; import cn.abel.bean.User; @Service public class UserService { @Autowired private UserDao userDao; public List getByMap(Map map){ DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); return userDao.getByMap(map); } public User getById(Integer id){ DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); return userDao.getById(id); } public User create(User user){ DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); userDao.create(user); return user; } public User update(User user){ DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); userDao.update(user); return user; } public int delete(Integer id){ DynamicDataSourceContextHolder.setDatabaseType(DatabaseTypeEnum.USER); return userDao.delete(id); } } ================================================ FILE: springboot-dynamicDataSource/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=8009 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.abel.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=springboot-dynamicDataSource application.main=cn.abel.Application ## LOG logging.file=./logs/springboot-dynamicDataSource.log ## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 spring.datasource.primary.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.user.url=jdbc:mysql://localhost:3306/rules?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource #\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.datasource.min-idle=5 #\u6700\u5927\u8FDE\u63A5\u6570\u91CF spring.datasource.max-active=100 #\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 spring.datasource.validation-query=select 1 from dual #\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.connection-timeout=60000 #\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.max-left-time=60000 #\u751F\u6548\u8D85\u65F6 spring.datasource.validation-time-out=3000 #\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.idle-time-out=60000 #\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 spring.datasource.connection-init-sql= set names utf8mb4 logging.level.cn.abel.dao=debug #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E mybatis.mapper-locations=classpath*:mapper/*Mapper.xml smybatis.type-aliases-package=cn.abel.bean #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E ## pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql ================================================ FILE: springboot-dynamicDataSource/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-dynamicDataSource/src/main/resources/local/logback-spring.xml ================================================ springboot-dataSource %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-dynamicDataSource/src/main/resources/mapper/NewsDaoMapper.xml ================================================ and id = #{id} and title = #{title} and content = #{content} and image_path = #{imagePath} and read_sum = #{readSum} SELECT LAST_INSERT_ID() INSERT INTO news( id, title, content, image_path, read_sum )VALUES( #{id}, #{title}, #{content}, #{imagePath}, #{readSum} ) UPDATE news SET title = #{title}, content = #{content}, image_path = #{imagePath}, read_sum = #{readSum} WHERE id = #{id} DELETE FROM news WHERE id = #{id} ================================================ FILE: springboot-dynamicDataSource/src/main/resources/mapper/UserDaoMapper.xml ================================================ and id = #{id} and name = #{name} and address = #{address} and mobile = #{mobile} and email = #{email} and role = #{role} SELECT LAST_INSERT_ID() INSERT INTO user( id, name, address, mobile, email, create_time, role )VALUES( #{id}, #{name}, #{address}, #{mobile}, #{email}, NOW(), #{role} ) UPDATE user SET name = #{name}, address = #{address}, mobile = #{mobile}, email = #{email}, role = #{role} WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-dynamicDataSource/src/test/java/cn/abel/BaseTest.java ================================================ package cn.abel; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; /** * @author yyb * @time 2019/3/27 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @TestPropertySource("/application.properties") public class BaseTest { @Configuration @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } @Test public void contextLoads() { } } ================================================ FILE: springboot-dynamicDataSource/src/test/java/cn/abel/service/ServiceTest.java ================================================ package cn.abel.service; import cn.abel.BaseTest; import cn.abel.bean.News; import cn.abel.bean.User; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * @author yyb * @time 2019/3/27 */ public class ServiceTest extends BaseTest { @Autowired private NewsService newsService; @Autowired private UserService userService; @Test public void dynamicDataSourceTest() throws Exception { List newsList = newsService.getByMap(null); List userList = userService.getByMap(null); System.out.println("newsList----" + newsList.size() + "--userList---" + userList.size()); } } ================================================ FILE: springboot-elasticsearch/README.md ================================================ ## springboot-elasticsearch * 本项目是speingboot结合es 的小李子。 * 演示了同一个项目配置多个es 数据源 * es操作是用es的rest api 进行操作,操作语句是 通过 JSONObject 对象进行拼接,可以执行增、删、改、查 行为。 具体的操作命令可以查看 Es RESTful API 官方文档 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html ================================================ FILE: springboot-elasticsearch/pom.xml ================================================ 4.0.0 cn.abel springboot-elasticserach 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-freemarker org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2 com.github.pagehelper pagehelper-spring-boot-starter 1.2.5 mysql mysql-connector-java 5.1.40 org.apache.commons commons-lang3 3.4 org.elasticsearch.client elasticsearch-rest-client 6.8.0 com.alibaba fastjson 1.2.40 ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/Application.java ================================================ package cn.abel; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/3/26 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/bean/User.java ================================================ package cn.abel.bean; import java.util.Date; public class User { private Integer id; private String name; private String address; private String mobile; private String email; private Date createTime; private Integer role; private String idCard; private int type; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Integer getRole() { return role; } public void setRole(Integer role) { this.role = role; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } public int getType() { return type; } public void setType(int type) { this.type = type; } } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClient2Config.java ================================================ package cn.abel.config; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 第二数据源 * @author yyb * @time 2020/4/2 */ @Configuration public class ESRestClient2Config { public static final String NAME = "ESRestClient2Config"; @Value("${elasticsearch2.userName}") private String userName; @Value("${elasticsearch2.password}") private String password; @Value("${elasticsearch2.rest.hostNames}") private String hostName; @Value("${elasticsearch2.rest.port}") private Integer port; @Bean(name = NAME, destroyMethod = "close") public RestClient getRestClient() { final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password)); RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostName, port)); //配置身份验证 restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); } }); return restClientBuilder.build(); } } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/config/ESRestClientConfig.java ================================================ package cn.abel.config; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 第一数据源 * @author yangyibo * @time 2019/4/2 */ @Configuration public class ESRestClientConfig { public static final String NAME = "ESRestClientConfig"; @Value("${elasticsearch.userName}") private String userName; @Value("${elasticsearch.password}") private String password; @Value("${elasticsearch.rest.hostNames}") private String hostName; @Value("${elasticsearch.rest.port}") private Integer port; @Bean(name = NAME, destroyMethod = "close") public RestClient getRestClient() { final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password)); RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostName, port)); //配置身份验证 restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); } }); return restClientBuilder.build(); } } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/constants/Constants.java ================================================ package cn.abel.constants; /** * @author yangyibo * @time 2019/4/3 */ public class Constants { /** * es 查询query 拼接 前缀 */ public static final String ES_QUERY_JSON_PREFIX = "{\n" + " \"query\": {\n" + " \"term\": {\n" + " \"userId\": {\n" + " \"value\": \""; /** * es 查询query 拼接后缀 */ public static final String ES_QUERY_JSON_SUFFIX = "\"\n" + " }\n" + " }\n" + " }\n" + "}\n"; /** * 需要查询的es的 index */ public static final String ES_INDEX_PATH = "/logstash_indes/_search"; } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/dao/UserDao.java ================================================ package cn.abel.dao; import java.util.List; import java.util.Map; import cn.abel.bean.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Repository @Mapper public interface UserDao { List getByMap(Map map); User getById(Integer id); Integer create(User user); int update(User user); int delete(Integer id); } ================================================ FILE: springboot-elasticsearch/src/main/java/cn/abel/service/UserService.java ================================================ package cn.abel.service; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; import cn.abel.config.ESRestClient2Config; import cn.abel.config.ESRestClientConfig; import cn.abel.constants.Constants; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.entity.ContentType; import org.apache.http.nio.entity.NStringEntity; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import cn.abel.dao.UserDao; import cn.abel.bean.User; /** * @author yyb */ @Service public class UserService { private static final Logger logger = LoggerFactory.getLogger(UserService.class); protected static final ObjectMapper mapper = new ObjectMapper(); @Autowired private UserDao userDao; /** * 数据源1 */ @Autowired @Qualifier(ESRestClientConfig.NAME) private RestClient restClient; /** * 数据源2 */ @Autowired @Qualifier(ESRestClient2Config.NAME) private RestClient restClient2; public List getByMap(Map map) { return userDao.getByMap(map); } public User getById(Integer id) throws Exception { //拼接es 的查询query String json = Constants.ES_QUERY_JSON_PREFIX + id + Constants.ES_QUERY_JSON_SUFFIX; HttpEntity entry = new NStringEntity(json, ContentType.APPLICATION_JSON); Response response = restClient.performRequest(HttpGet.METHOD_NAME, Constants.ES_INDEX_PATH, Collections.emptyMap(), entry); JSONObject responseJson = JSONObject.parseObject(EntityUtils.toString(response.getEntity())); //es 中查询的结果 System.out.println(responseJson); return userDao.getById(id); } /** * 查询用户列表 * * @param keyword 关键字用户名字/用户手机号/用户身份证号 * @param type 用户类型/1:注册用户/2:转化用户 * @param startTime 时间范围 起始时间 * @param endTime 时间范围 结束时间 * @param pageSize * @param pageIndex * @return * @throws Exception */ public JSONObject getList(String keyword, Integer type, String startTime, String endTime, int pageSize, int pageIndex) throws Exception { JsonNode searchResponse; JSONObject response = new JSONObject(); JSONObject search = searchListQuery(keyword, type, startTime, endTime, pageSize, pageIndex); //根据档案英文名切换不同的索引 String endpoint = "/user_Info_index/user/_search"; searchResponse = esSearch(search, endpoint, restClient); if (null == searchResponse) { return response; } JsonNode hitsNode = searchResponse.get("hits"); ArrayNode hitsArray = (ArrayNode) hitsNode.get("hits"); response.put("total", hitsNode.get("total").intValue()); JSONArray list = new JSONArray(); for (JsonNode hit : hitsArray) { JSONObject result = (JSONObject) JSONObject.parse(hit.get("_source").toString()); list.add(result); } response.put("list", list); return response; } public User create(User user) { userDao.create(user); return user; } public User update(User user) { userDao.update(user); return user; } public int delete(Integer id) { return userDao.delete(id); } /** * 拼装列表查询query * * @param keyword * @return */ private JSONObject searchListQuery(String keyword, Integer type, String startTime, String endTime, int pageSize, int pageIndex) { //只返回列表所需数据 String[] source = new String[]{"id", "user_name", "id_card", "user_name", "mobile", "type", "create_time"}; JSONObject search = new JSONObject(); search.put("_source", source); if (pageIndex <= 0) { pageIndex = 1; } JSONObject bool = new JSONObject(); JSONArray sort = new JSONArray(); //查询类型 JSONArray mustArray = new JSONArray(); if (null != type) { mustArray.add(getJSONObject("term", getJSONObject("type", type))); } bool.put("must", mustArray); //关键字查询 if (StringUtils.isNotEmpty(keyword)) { JSONObject multiMatch = new JSONObject(); multiMatch.put("query", keyword); multiMatch.put("fields", new String[]{"user_name.keyword", "user_name"}); //查询条件 JSONArray shouldArray = new JSONArray(); //虚化查询 shouldArray.add(getJSONObject("term", getJSONObject("id_card", keyword))); shouldArray.add(getJSONObject("term", getJSONObject("mobile", keyword))); shouldArray.add(getJSONObject("multi_match", multiMatch)); //关键字评分排序 sort.add(getJSONObject("_score", getJSONObject("order", "desc"))); //should 必须命中一个 bool.put("minimum_should_match", 1); bool.put("should", shouldArray); } //排序和时间过滤 JSONObject rangeField = new JSONObject(); //筛选创建时间大于 startTime 小于 endTime 的数据 rangeField.put("gte", startTime); rangeField.put("lte", endTime); JSONObject range = new JSONObject(); range.put("range", getJSONObject("create_time", rangeField)); //按照创建时间规则倒叙排序 sort.add(getJSONObject("create_time", getJSONObject("order", "desc"))); bool.put("filter", range); search.put("sort", sort); search.put("query", getJSONObject("bool", bool)); return setPage(pageIndex, pageSize, search); } /** * ES查询 * * @param search * @return */ public JsonNode esSearch(JSONObject search, String endpoint, RestClient restClient) { JsonNode responseNode = null; try { logger.info("查询es语句为 {}, endpoint 为:{}", search, endpoint.toString()); Request request = new Request(HttpGet.METHOD_NAME, endpoint); if (search != null) { String data = search.toString(); request.setJsonEntity(data); } try { restClient.performRequest(request); } catch (IOException e) { logger.error("查询es语句报错为 {}", e.getMessage()); } Response response = restClient.performRequest(request); String responseStr = EntityUtils.toString(response.getEntity()); logger.info("查询结果为", responseStr); responseNode = mapper.readTree(responseStr); } catch (IOException e) { logger.error("查询失败", e); } return responseNode; } /** * 设置页面 * * @param pageIndex * @param pageSize * @param search * @return */ public static JSONObject setPage(Integer pageIndex, Integer pageSize, JSONObject search) { search.put("from", (pageIndex - 1) * pageSize); search.put("size", pageSize); return search; } /** * 获取json 对象 * * @param key * @param value * @return */ public static JSONObject getJSONObject(String key, Object value) { JSONObject term = new JSONObject(); term.put(key, value); return term; } } ================================================ FILE: springboot-elasticsearch/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=8009 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.es.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=springboot-elasticsearch application.main=cn.abel.Application ## LOG logging.file=./logs/springboot-elasticsearch.log ## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 spring.datasource.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource #\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.datasource.min-idle=5 #\u6700\u5927\u8FDE\u63A5\u6570\u91CF spring.datasource.max-active=100 #\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 spring.datasource.validation-query=select 1 from dual #\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.connection-timeout=60000 #\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.max-left-time=60000 #\u751F\u6548\u8D85\u65F6 spring.datasource.validation-time-out=3000 #\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.idle-time-out=60000 #\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 spring.datasource.connection-init-sql= set names utf8mb4 logging.level.cn.abel.dao=debug #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E mybatis.mapper-locations=classpath*:mapper/*Mapper.xml smybatis.type-aliases-package=cn.abel.bean #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E ## pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql #es\u670D\u52A1\u5668\u5730\u5740\u914D\u7F6E elasticsearch.userName= elasticsearch.password= elasticsearch.rest.hostNames=127.0.0.1 elasticsearch.rest.port=9200 #es2\u670D\u52A1\u5668\u5730\u5740\u914D\u7F6E elasticsearch2.userName= elasticsearch2.password= elasticsearch2.rest.hostNames=127.0.0.1 elasticsearch2.rest.port=9200 ================================================ FILE: springboot-elasticsearch/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-elasticsearch/src/main/resources/local/logback-spring.xml ================================================ springboot-es %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-elasticsearch/src/main/resources/mapper/UserDaoMapper.xml ================================================ and id = #{id} and name = #{name} and address = #{address} and mobile = #{mobile} and email = #{email} and role = #{role} SELECT LAST_INSERT_ID() INSERT INTO user( id, name, address, mobile, email, create_time, role )VALUES( #{id}, #{name}, #{address}, #{mobile}, #{email}, NOW(), #{role} ) UPDATE user SET name = #{name}, address = #{address}, mobile = #{mobile}, email = #{email}, role = #{role} WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-elasticsearch/src/test/java/cn/abel/BaseTest.java ================================================ package cn.abel; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; /** * @author yyb * @time 2019/3/27 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @TestPropertySource("/application.properties") public class BaseTest { @Configuration @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } @Test public void contextLoads() { } } ================================================ FILE: springboot-elasticsearch/src/test/java/cn/abel/service/ServiceTest.java ================================================ package cn.abel.service; import cn.abel.BaseTest; import cn.abel.bean.User; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; /** * @author yyb * @time 2019/3/27 */ public class ServiceTest extends BaseTest { @Autowired private UserService userService; @Test public void dynamicDataSourceTest() throws Exception { User user = userService.getById(1); System.out.println("--userList---" + user.toString()); } } ================================================ FILE: springboot-jpa/pom.xml ================================================ 4.0.0 com.us springboot-jpa 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.apache.commons commons-lang3 3.4 ================================================ FILE: springboot-jpa/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/bean/User.java ================================================ package com.us.example.bean; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity @Table(name = "sec_user") public class User { @Id @GeneratedValue private Integer id; @Column(name = "name") private String name; @Column(name = "password") private String password; @Column(name = "username") private String username; @Column(name = "division_id") private Integer divisionId; @Column(name = "email") private String email; @Column(name = "gender") private String gender; @Column(name = "mobilephone") private String mobilephone; @Column(name = "telephone") private String telephone; @Column(name = "user_type") private Integer userType; @Column(name = "create_by") private String createBy; @Column(name = "create_time") private Date createTime; @Column(name = "update_by") private String updateBy; @Column(name = "update_time") private Date updateTime; @Column(name = "disabled") private Integer disabled; @Column(name = "theme") private String theme; @Column(name = "is_ldap") private Integer isLdap; public String getName() { return name; } public void setName(String name) { this.name = name; } @JsonIgnore public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getDivisionId() { return divisionId; } public void setDivisionId(Integer divisionId) { this.divisionId = divisionId; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String getMobilephone() { return mobilephone; } public void setMobilephone(String mobilephone) { this.mobilephone = mobilephone; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public Integer getUserType() { return userType; } public void setUserType(Integer userType) { this.userType = userType; } public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public Integer getDisabled() { return disabled; } public void setDisabled(Integer disabled) { this.disabled = disabled; } public String getTheme() { return theme; } public void setTheme(String theme) { this.theme = theme; } public Integer getIsLdap() { return isLdap; } public void setIsLdap(Integer isLdap) { this.isLdap = isLdap; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/config/DBConfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/config/JpaConfig.java ================================================ package com.us.example.config; import java.util.HashMap; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableJpaRepositories("com.us.example.dao") @EnableTransactionManagement @ComponentScan public class JpaConfig { @Autowired private DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); //vendorAdapter.setShowSql(true); //vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.us.example.bean"); factory.setDataSource(dataSource); Map jpaProperties = new HashMap(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.jdbc.batch_size",50); //jpaProperties.put("hibernate.show_sql",true); factory.setJpaPropertyMap(jpaProperties); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/controller/UserController.java ================================================ package com.us.example.controller; import javax.servlet.http.HttpServletRequest; import java.util.Map; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.us.example.service.UserService; import com.us.example.util.CommonUtil; @Controller @RequestMapping(value = "/users") public class UserController { private static final Logger logger = Logger.getLogger(UserController.class); @Autowired private UserService userService; /** * 通过spring data jpa 调用方法 * api :localhost:8099/users/byname?username=xxx * @param request * @return */ @RequestMapping(value = "/byname", method = RequestMethod.GET) @ResponseBody public ResponseEntity getUser(HttpServletRequest request) { Map map = CommonUtil.getParameterMap(request); String username = (String) map.get("username"); return new ResponseEntity<>(userService.getUserByName(username), HttpStatus.OK); } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/dao/UserJpaDao.java ================================================ package com.us.example.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.us.example.bean.User; /** * The Interface UserJpaDao. * @author abel */ public interface UserJpaDao extends JpaRepository { /** * Find by name. * * @param name the name * @return the user */ User findByName(String name); } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/service/UserService.java ================================================ package com.us.example.service; import java.util.Map; import com.us.example.bean.User; /** * The Interface UserService. */ public interface UserService { /** * Gets the user by name. * * @param username the user name * @return the user by name */ public User getUserByName(String username); } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/serviceImpl/UserServiceImpl.java ================================================ package com.us.example.serviceImpl; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.us.example.dao.UserJpaDao; import com.us.example.bean.User; import com.us.example.service.UserService; /** * * @ClassName UserServiceImpl * @author abel * @date 2016年11月10日 */ @Service public class UserServiceImpl implements UserService { @Autowired private UserJpaDao userJpaDao; /** * * @param username * @return */ @Override public User getUserByName(String username) { return userJpaDao.findByName(username); } } ================================================ FILE: springboot-jpa/src/main/java/com/us/example/util/CommonUtil.java ================================================ package com.us.example.util; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; public class CommonUtil { /** * 从request中获得参数Map,并返回可读的Map. * * @param request the request * @return the parameter map */ public static Map getParameterMap(HttpServletRequest request) { // 参数Map Map properties = request.getParameterMap(); //返回值Map Map returnMap = new HashMap(); Set keySet = properties.keySet(); for(String key: keySet){ String[] values = properties.get(key); String value = ""; if(values != null && (values.length==1&&StringUtils.isNotBlank(values[0]))?true:false){ for(int i=0;i 4.0.0 cn.abel springboot-kafka 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test com.alibaba fastjson 1.2.40 org.springframework.kafka spring-kafka org.projectlombok lombok true ================================================ FILE: springboot-kafka/src/main/java/cn/abel/Application.java ================================================ package cn.abel; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; /** * Created by yyb on 2018/12/12. */ @SpringBootApplication(exclude = KafkaAutoConfiguration.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-kafka/src/main/java/cn/abel/config/KafkaConfig.java ================================================ package cn.abel.config; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.common.serialization.StringDeserializer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.kafka.annotation.EnableKafka; import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; import org.springframework.kafka.config.KafkaListenerContainerFactory; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.core.DefaultKafkaConsumerFactory; import java.util.HashMap; import java.util.Map; /** * Created by yyb on 2018/12/12. */ @Configuration @EnableKafka public class KafkaConfig { /** * kafka地址 */ @Value("${spring.kafka.bootstrap-servers}") private String bootstrapServers; /** * 默认组 */ @Value("${spring.kafka.consumer.group-id}") private String groupId; /** * 自动消费设定 */ @Value("${spring.kafka.consumer.auto-offset-reset}") private String autoOffsetReset; /** * 一次批量处理的数据量 */ @Value("${spring.kafka.consumer.max-poll-records}") private int maxPollRecords; /** * 一次批量处理的时间间隔 */ @Value("${spring.kafka.consumer.max-poll-interval-ms}") private int maxPollIntervalMs; @Value("${spring.kafka.listener.concurrency}") private int cocurrency; @Value("${spring.kafka.consumer.auto-commit-interval}") private Integer commitInterval; @Bean(name = "kafkaListenerContainerFactory") public KafkaListenerContainerFactory batchFactory() { ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); factory.setConcurrency(cocurrency); //设置为批量消费,每个批次数量在Kafka配置参数中设置ConsumerConfig.MAX_POLL_RECORDS_CONFIG factory.setBatchListener(true); return factory; } @Bean public ConsumerFactory consumerFactory() { return new DefaultKafkaConsumerFactory<>(consumerConfigs()); } @Bean public Map consumerConfigs() { Map props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, commitInterval); props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "15000"); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); //每一批数量 props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, maxPollRecords); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset); return props; } } ================================================ FILE: springboot-kafka/src/main/java/cn/abel/service/prehandle/KafkaConsumerService.java ================================================ package cn.abel.service.prehandle; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; import java.util.List; /** * Created by yyb on 2018/12/10. */ @Component public class KafkaConsumerService { @Autowired private SplitService splitService; @KafkaListener(topics = "${log.statistical.kafka.topic}", containerFactory = "kafkaListenerContainerFactory") public void processMessage(List> records) { for (ConsumerRecord record : records) { String message = (String) record.value(); splitService.saveAndSplitLog(message); } } } ================================================ FILE: springboot-kafka/src/main/java/cn/abel/service/prehandle/SplitService.java ================================================ package cn.abel.service.prehandle; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; /** * Created by yyb on 2018/12/10. */ @Service @Slf4j public class SplitService { private static final Logger logger = LoggerFactory.getLogger(SplitService.class); public void saveAndSplitLog(String message) { JSONObject jsonObject = JSONObject.parseObject(message); // 从kafka 中获取到数据 String content = jsonObject.getString("message"); } } ================================================ FILE: springboot-kafka/src/main/resources/local/application.properties ================================================ server.port=8090 spring.kafka.bootstrap-servers=127.0.0.1:9092 spring.kafka.consumer.group-id=springboot-kafka spring.kafka.consumer.auto-offset-reset=latest spring.kafka.consumer.enable-auto-commit=true spring.kafka.consumer.auto-commit-interval=2000 spring.kafka.listener.concurrency= 1 spring.kafka.consumer.max-poll-records=50 spring.kafka.consumer.max-poll-interval-ms=4000 # topic log.statistical.kafka.topic=nginx_log logging.file=./logs/springboot-kafka.log ================================================ FILE: springboot-kafka/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-kafka/src/main/resources/local/logback-spring.xml ================================================ springboot-kafka %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 30 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: springboot-mybatis/docker-it.sh ================================================ #!/bin/sh ######################### # based on docker bin packageName=$1 imageVersion=$2 dockerDestFolder=$3 env=$4 packageTZ=Asia/Shanghai if [ "${packageName}" = "" ]; then echo [ERROR] "Please provide image name as first param" exit 1 fi if [ "${imageVersion}" = "" ]; then echo [ERROR] "Please provide image version as second param" exit 1 fi if [ "${dockerDestFolder}" = "" ]; then echo [ERROR] "Please provide docker dest folder" exit 1 fi if [ "${env}" = "" ]; then echo [ERROR] "Please provide env folder" exit 1 fi COUNT=`docker -v 2>&1 | grep 'version' | grep -v grep | wc -l` if [ ${COUNT} != 1 ]; then echo [ERROR] "Cannot find docker command" exit 1 fi echo [INFO] "Remove old image from docker repository..." count=`docker images | grep "${packageName}" | grep "${imageVersion}" | wc -l` if [ ${count} != 1 ]; then echo [WARN] "image ${packageName} with version ${imageVersion} does not exist in docker repo" else docker rmi -f ${packageName}:${imageVersion} fi #generate Dockerfile dynamically echo [INFO] "generating Dockerfile..." warName=${packageName}-${imageVersion}.war dateVersion=`date +%Y%m%d-%H%M%S` #cat out to Dockerfile with content begin/end with EOF cat > target/Dockerfile < /etc/timezone RUN cd ${dockerDestFolder} \ && ln -svnf ${dateVersion} current \ && cd current \ && touch docker-entrypoint.sh \ && chmod +x docker-entrypoint.sh \ && echo "/opt/apps/java/bin/java -jar ${dockerDestFolder}/current/*.war --spring.config.location=${dockerDestFolder}/current/env/application.properties >/dev/null 2>&1" > docker-entrypoint.sh CMD .${dockerDestFolder}/current/docker-entrypoint.sh EOF # echo $TZ > /etc/timezone TO someString to one file. # To set the right time. # ENV TZ=Asia/Shanghai # RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone # COPY conf/${env}/*.cer ${dockerDestFolder}/${dateVersion}/ #read Dockerfile echo [INFO] "Building image..." docker build -t ${packageName}:${imageVersion} -f target/Dockerfile . || exit 1 echo [INFO] "Exporting image to target folder..." docker save ${packageName}:${imageVersion} > target/${packageName}-${imageVersion}.image ================================================ FILE: springboot-mybatis/env/dev/application.properties ================================================ # EMBEDDED SERVER CONFIGURATION (ServerProperties) server.port=8099 ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/msm?useSSL=false&useUnicode=true&characterEncoding=UTF-8 ms.db.username=root ms.db.password=admin ms.db.maxActive=500 ================================================ FILE: springboot-mybatis/env/dev/env.properties ================================================ #dev ################ ##this property file is used to export shell session-scoped variables by command 'source *.properties' ################ #app root prop_appRoot=/opt/apps #run postinstall or not.(It is not used any more.) prop_runPreinstall=false prop_runPostinstall=false #the package name prop_package=springboot-mybatis #the package version prop_packageVersion=v1 #Your Java Home prop_javaHome=/opt/apps/jdk/current #owner and group for package prop_ownerGroup=root:root #folders which need to be created manually, the folder path will be relative to the app home folder #seperate multi folders with space, don't forget the double " prop_manualFolders="var/logs" #manual folders mode prop_manualFolderMode=777 ################### #Cluster config ################### #used by install.sh to decide the install mode: cluster or single node(default false) prop_isCluster=false #single prop_singleNode=springboot-mybatis-dev #cluster #all the nodes for the cluster, only is is accepted now #seperated by , sign (EX di,d2,192.168.100.2)(If you want to use d1 d2,you must config the url in etc/local) prop_clusterNodes=d1 ################### #springboot config ################### prop_springbootWarName=${prop_package} prop_springbootWarVersion=${prop_packageVersion} prop_springbootProcessKeyWord=${prop_springbootWarName}-${prop_springbootWarVersion}.war ############## #docker config ############## prop_dockerDestFolder=${prop_appRoot}/${prop_package} #docker daemon.(Docker is online or not.) prop_dockerProcessKeyWord='docker' #docker image name, e.g. cliff/nginx or nginx prop_dockerImageName=${prop_package} #docker image version, e.g. v1/v2 or latest prop_dockerImageVersion=${prop_packageVersion} #docker container count in each host server(1 in most situation.) prop_dockerContainerCount=1 #docker config file mapping, multiple file mappings is supported so you can specify multiple -v xx:xx prop_dockerConfigFileMapping="env:${prop_dockerDestFolder}/current/env" prop_dockerLogFolderMapping="var/logs/nodexxx:${prop_dockerDestFolder}/var/logs" prop_dockerUploadFolderMapping="uploadFiles:${prop_dockerDestFolder}/uploadFiles" # It is not used any more. Add command `--net=host` prop_dockerPortMappings=80:8081 ########################################## #seconds config before start and stop ########################################## #the sleep time to wail for each node starting up after another, the unit is second prop_startAllSleep=2 #the sleep time to wail for one node starting up. #sometimes we start up server by backend job so we need wait some time prop_startOneSleep=8 #stop node timeout, if timeout we will kill -9, the unit is second prop_stopNodeTimeout=2 ================================================ FILE: springboot-mybatis/env/dev/log4j.properties ================================================ # Output pattern : date [thread] priority category - message log4j.rootLogger=INFO, Console, R #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=logs/cmbms.log log4j.appender.R.MaxFileSize=50kB log4j.appender.R.MaxBackupIndex=5 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender log4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd log4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout #log4j.appender.ServerDailyRollingFile.Append=true log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n ================================================ FILE: springboot-mybatis/env/local/application.properties ================================================ # EMBEDDED SERVER CONFIGURATION (ServerProperties) server.port=8099 ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/msm?useSSL=false&useUnicode=true&characterEncoding=UTF-8 ms.db.username=root ms.db.password=admin ms.db.maxActive=500 ================================================ FILE: springboot-mybatis/env/local/env.properties ================================================ #local ################ ##this property file is used to export shell session-scoped variables by command 'source *.properties' ################ #app root prop_appRoot=/opt/apps #run postinstall or not.(It is not used any more.) prop_runPreinstall=false prop_runPostinstall=false #the package name prop_package=springboot-mybatis #the package version prop_packageVersion=v1 #Your Java Home prop_javaHome=/opt/apps/java/Contents/Home #owner and group for package prop_ownerGroup=root:root #folders which need to be created manually, the folder path will be relative to the app home folder #seperate multi folders with space, don't forget the double " prop_manualFolders="var/logs" #manual folders mode prop_manualFolderMode=777 ################### #Cluster config ################### #used by install.sh to decide the install mode: cluster or single node(default false) prop_isCluster=false #single prop_singleNode=local #cluster #all the nodes for the cluster, only is is accepted now #seperated by , sign (EX di,d2,192.168.100.2)(If you want to use d1 d2,you must config the url in etc/local) prop_clusterNodes=d1 ################### #springboot config ################### prop_springbootWarName=${prop_package} prop_springbootWarVersion=${prop_packageVersion} prop_springbootProcessKeyWord=${prop_springbootWarName}-${prop_springbootWarVersion}.war ############## #docker config ############## prop_dockerDestFolder=${prop_appRoot}/${prop_package} #docker daemon.(Docker is online or not.) prop_dockerProcessKeyWord='docker' #docker image name, e.g. cliff/nginx or nginx prop_dockerImageName=${prop_package} #docker image version, e.g. v1/v2 or latest prop_dockerImageVersion=${prop_packageVersion} #docker container count in each host server(1 in most situation.) prop_dockerContainerCount=1 #docker config file mapping, multiple file mappings is supported so you can specify multiple -v xx:xx prop_dockerConfigFileMapping="env:${prop_dockerDestFolder}/current/env" prop_dockerLogFolderMapping="var/logs/nodexxx:${prop_dockerDestFolder}/var/logs" prop_dockerUploadFolderMapping="uploadFiles:${prop_dockerDestFolder}/uploadFiles" prop_dockerPortMappings=8080:8080 ########################################## #seconds config before start and stop ########################################## #the sleep time to wail for each node starting up after another, the unit is second prop_startAllSleep=2 #the sleep time to wail for one node starting up. #sometimes we start up server by backend job so we need wait some time prop_startOneSleep=8 #stop node timeout, if timeout we will kill -9, the unit is second prop_stopNodeTimeout=2 ================================================ FILE: springboot-mybatis/env/local/log4j.properties ================================================ # Output pattern : date [thread] priority category - message log4j.rootLogger=INFO, Console, R #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=logs/cmbms.log log4j.appender.R.MaxFileSize=50kB log4j.appender.R.MaxBackupIndex=5 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender log4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd log4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout #log4j.appender.ServerDailyRollingFile.Append=true log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n ================================================ FILE: springboot-mybatis/package.sh ================================================ #!/bin/bash ##################### # bash only # usage ./package.sh ##################### #declare -a: define an array #declare -i: define an integer declare -i index=1 declare -a envMap declare -a formatMap=(["1"]="docker" ["2"]="springboot") #GET THE URL OF CURRENT PATH CURRENT_DIR=`dirname $0` cd $CURRENT_DIR ######################### # confirm the env ######################### index=1 #scan the envs from conf/* for i in env/* ; do if [ -d ${i} ]; then envMap["${index}"]="`basename ${i}`" index=index+1 fi done #Print the choice env=1 echo "Please choose the environment by typing the number [default ${env}]" for i in ${!envMap[@]} ;do echo [${i}]:${envMap[${i}]} done #Read the envTmp . Set The finalEnv. Pay Attention 'read' NOT 'Read' read envTmp # echo "${envTmp}" if [ "${envTmp}" != "" ]; then env=${envTmp} fi # echo "${env}" finalEnv=${envMap[${env}]} echo "${finalEnv}" echo "[INFO] You are choosing environment: ${finalEnv}" echo "[INFO] Set the env properties by env/${finalEnv}/env.properties" #Load the env/${finalEnv}/env.properties . env/${finalEnv}/env.properties echo "" echo "" ######################### # confirm the format ######################### format=1 for i in ${!formatMap[@]};do echo [${i}]: ${formatMap[${i}]} done read formatTmp if [ "${formatTmp}" != "" ]; then format=${formatTmp} fi finalFormat=${formatMap[${format}]} ######################### # confirm the package ######################### finalPackage=${prop_package} echo "[INFO] You are choosing package version: ${finalPackage}" echo "" echo "" ######################### # confirm the version ######################### finalPackageVersion=${prop_packageVersion} echo "[INFO] You are choosing package version: ${finalPackageVersion}" echo "" echo "" ###################### # begin packing ###################### if [ -n "${finalFormat}" ] && [ "${finalFormat}" = "springboot" ]; then ############################## # generate executable war file ############################## #noneed.properties The .properties is outside the war . So it is no need any more. theCommand="./war-it.sh ${finalPackage} ${finalPackageVersion} ${finalEnv} 'noneed.properties'" echo [INFO] ${theCommand} eval ${theCommand} || exit 1 else ############################## # generate executable war file ############################## theCommand="./war-it.sh ${finalPackage} ${finalPackageVersion} ${finalEnv} 'noneed.properties'" echo [INFO] ${theCommand} eval ${theCommand} || exit 1 ##################################### # generate docker image and export it ##################################### theCommand="./docker-it.sh ${finalPackage} ${finalPackageVersion} ${prop_dockerDestFolder} ${finalEnv}" echo [INFO] ${theCommand} eval ${theCommand} || exit 1 fi theCommand="./tar-it.sh ${finalEnv} ${finalPackage} ${finalPackageVersion} ${finalFormat}" echo [INFO] ${theCommand} eval ${theCommand} || exit 1 echo "[INFO] package is done successfully" ================================================ FILE: springboot-mybatis/pom.xml ================================================ 4.0.0 com.u springboot-mybatis v1 war org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.example.Application 3.2.7 1.2.2 1.8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-logging mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} com.jf page-mysql 1.0 org.apache.commons commons-lang3 3.4 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-log4j org.springframework.boot spring-boot-maven-plugin package repackage ${start-class} org.apache.maven.plugins maven-war-plugin ${start-class} ${project.build.directory}/springboot-mybatisma src/main/webapp env/${package.environment} ${package.resources} WEB-INF/classes default-war package war maven-assembly-plugin 2.5.5 ${package}-${package.version} true false ${basedir}/scripts/${package.format}/common/package.xml org.apache.maven.plugins maven-resources-plugin ${project.build.sourceEncoding} org.apache.maven.plugins maven-surefire-plugin methods 10 -Dfile.encoding=UTF-8 true **/*Test.java default-test test test ================================================ FILE: springboot-mybatis/scripts/docker/common/common-env.sh ================================================ #ident "%W%" #!/bin/sh -x #SCRIPT_PATH must be defined firstly by calling script echo "[INFO] calling common-env.sh" if [ "${SCRIPT_PATH}" = "" ]; then echo "[ERROR] SCRIPT_PATH is not defined in calling script" exit 1 else ############# # define own function ############# #print out command into console (and log file if there is one) and then execute it myexecute () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theCommand=${1} echo "${dt}: [COMMAND] ${theCommand}" if [ "${LOG}" != "" ]; then echo "${dt}: [COMMAND] ${theCommand}" >> ${LOG} fi ${theCommand} return $? } myexecute2 () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theCommand=${1} echo "${dt}: [COMMAND] ${theCommand}" if [ "${LOG}" != "" ]; then echo "${dt}: [COMMAND] ${theCommand}" >> ${LOG} fi eval ${theCommand} return $? } #print out log into console (and log file if there is one) mylog () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theLog=${1} echo "${dt}: ${theLog}" if [ "${LOG}" != "" ]; then echo "${dt}: ${theLog}" >> ${LOG} fi } #print out log into console (and log file if there is one), and transate \n into new line mylog2 () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theLog=${1} echo -e "${dt}: ${theLog}" if [ "${LOG}" != "" ]; then echo -e "${dt}: ${theLog}" >> ${LOG} fi } #check it is a number or not isNumber () { var=${1} if [ ${var} -eq ${var} 2> /dev/null ] then return 0 else return 1 fi } ############ # to export variables ############ #export all variables in env.properties echo "[INFO] export all variables in env.properties" if [ -f ${SCRIPT_PATH}/../env/env.properties ]; then myexecute "source ${SCRIPT_PATH}/../env/env.properties" elif [ -f ${SCRIPT_PATH}/../env/env.properties ]; then myexecute "source ${SCRIPT_PATH}/../env/env.properties" else echo "[ERROR] cannot find env.properties" exit 1 fi fi echo "[INFO] common-env.sh is done" #exit 0 is not allowed here which is stop calling script from going on executing ================================================ FILE: springboot-mybatis/scripts/docker/common/install-cluster.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used for cluster install ############################### #the path of this script when running if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh if [ "${prop_runPreinstall}" = "true" ]; then myexecute "${SCRIPT_PATH}/preinstall.sh" if [ $? != 0 ]; then exit 1 fi fi mylog "[INFO] Begin install-cluster.sh" APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log APPROOT=${prop_appRoot} APPNAME=${prop_package} APPHOME=${APPROOT}/${APPNAME} HOSTNAME=`hostname` CLUSTER_NODES=${prop_clusterNodes} #replace ',' with space CLUSTER_NODES=${CLUSTER_NODES//,/ } #replace '"' with null CLUSTER_NODES=${CLUSTER_NODES//\"/} MANUAL_FOLDERS=${prop_manualFolders} MANUAL_FOLDER_MODE=${prop_manualFolderMode} for i in ${CLUSTER_NODES} do mylog "" mylog "-----------------------------" mylog "[INFO] Connecting to host ${i}" #create app home folder and new version folder myexecute "ssh -oStrictHostKeyChecking=no root@${i} mkdir -p ${APPHOME}/${APPVERSION}" mylog "[INFO] Folder ${APPHOME}/${APPVERSION} is created successfully on host <<${i}>>" #copy files from current host to another node by scp command #-p preserves modification times, access times, and modes from the original file mylog "[INFO] copying files to host <<${i}>> by scp command" myexecute "scp -rp ${SCRIPT_PATH}/../* root@${i}:${APPHOME}/${APPVERSION}/" mylog "[INFO] Copy is done!" #change owner and group for app package mylog "[INFO] changing owner and group recursively" myexecute "ssh -oStrictHostKeyChecking=no root@${i} chown -R ${prop_ownerGroup} ${APPHOME}/${APPVERSION}/" mylog "[INFO] Owner and group set up done!" #create manual folders if [ "${MANUAL_FOLDERS}" != "" ]; then theCommand="ssh -oStrictHostKeyChecking=no root@${i} \"pwd " for MANUAL_FOLDER in ${MANUAL_FOLDERS} do theCommand="${theCommand} && mkdir -p ${APPHOME}/${MANUAL_FOLDER}" if [ "${MANUAL_FOLDER_MODE}" != "" ]; then theCommand="${theCommand} && chmod -R ${MANUAL_FOLDER_MODE} ${APPHOME}/${MANUAL_FOLDER}" fi done theCommand="${theCommand} \" " myexecute2 "${theCommand}" fi #create soft link named 'current', -s:soft link -v:debug mode -n:treate link as normal file if it linking to a folder #-f:force create it is already there mylog "[INFO] Create soft link named 'current'" myexecute "ssh -oStrictHostKeyChecking=no root@${i} ln -svnf ${APPHOME}/${APPVERSION} ${APPHOME}/current" mylog "[INFO] Link creation is done!" if [ "${prop_runPostinstall}" = "true" ]; then myexecute "ssh -oStrictHostKeyChecking=no root@${i} ${APPHOME}/current/scripts/postinstall.sh" mylog "[INFO] postinstall is done on node ${i}" fi mylog "--------------------------------" done mylog "[INFO] Cluster installation is done successfully, for more detail please check log ${LOG}" exit 0 ================================================ FILE: springboot-mybatis/scripts/docker/common/install-single.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used for single server install ############################### #the path of this script when running if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh if [ "${prop_runPreinstall}" = "true" ]; then myexecute ". ${SCRIPT_PATH}/preinstall.sh" if [ $? != 0 ]; then exit 1 fi fi mylog "[INFO] Begin install-single.sh" APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log APPROOT=${prop_appRoot} APPNAME=${prop_package} APPHOME=${APPROOT}/${APPNAME} HOSTNAME=`hostname` SINGLE_NODE=${prop_singleNode} MANUAL_FOLDERS=${prop_manualFolders} MANUAL_FOLDER_MODE=${prop_manualFolderMode} mylog "" mylog "-----------------------------" mylog "[INFO] Installing on host ${SINGLE_NODE}" #create app home folder and new version folder myexecute "mkdir -p ${APPHOME}/${APPVERSION}" mylog "[INFO] Folder ${APPHOME}/${APPVERSION} is created successfully on host <<${SINGLE_NODE}>>" #copy files from current folder to app home folder #-p reserve the specified attributes (default: mode,ownership,timestamps) mylog "[INFO] copying files to host <<${SINGLE_NODE}>> by cp command" myexecute "cp -rp ${SCRIPT_PATH}/../* ${APPHOME}/${APPVERSION}/" mylog "[INFO] Copy is done!" #change owner and group for app package mylog "[INFO] changing owner and group recursively" myexecute "chown -R ${prop_ownerGroup} ${APPHOME}/${APPVERSION}" mylog "[INFO] Owner and group set up done!" #create manual folders if [ "${MANUAL_FOLDERS}" != "" ]; then for MANUAL_FOLDER in ${MANUAL_FOLDERS} do myexecute "mkdir -p ${APPHOME}/${MANUAL_FOLDER}" if [ "${MANUAL_FOLDER_MODE}" != "" ]; then myexecute "chmod -R ${MANUAL_FOLDER_MODE} ${APPHOME}/${MANUAL_FOLDER}" fi done fi #create soft link named 'current', -s:soft link -v:debug mode -n:treate link as normal file if it linking to a folder #-f:force create it ignoring if it is already there mylog "[INFO] Create soft link named 'current'" myexecute "ln -svnf ${APPHOME}/${APPVERSION} ${APPHOME}/current" mylog "[INFO] Link creation is done!" mylog "--------------------------------" mylog "[INFO] Installation is done successfully, for more detail please check log ${LOG}" mylog "------------------------------------" mylog "------------------------------------" if [ "${prop_runPostinstall}" = "true" ]; then myexecute ". ${SCRIPT_PATH}/postinstall.sh" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/docker/common/install.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used to install package ############################### #the path of this script when running if cd "`dirname $0`"; then export SCRIPT_PATH=${PWD} echo "[INFO] export SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log mylog "[INFO] Begin install.sh" #check it is a single node installation or a cluster installation if [ "${prop_isCluster}" = "true" ]; then mylog "[INFO] checked you are doing CLUSTER installation" myexecute "${SCRIPT_PATH}/install-cluster.sh" else mylog "[INFO] checked you are doing SINGLE NODE installation" myexecute "${SCRIPT_PATH}/install-single.sh" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/docker/common/package.xml ================================================ 0.1 tar scripts/${package.format}/manager /scripts 0755 scripts/${package.format}/common /scripts 0755 install-cluster.sh install-single.sh install.sh common-env.sh env/${package.environment} /env target/${package}-${package.version}.image / ${package}-${package.version}.img.tar 0755 ================================================ FILE: springboot-mybatis/scripts/docker/manager/check-os.sh ================================================ #ident "%W%" #!/bin/sh -x ####################### ###for redhat 7 only ####################### 1. close whole firewall issue: all port like 80/20 and so on cannot be accessed check: systemctl list-unit-files|grep enabled | grep firewall (if not null, firewall is open) fix: systemctl stop firewalld.service systemctl disable firewalld.service rollabck: systemctl enable firewalld.service systemctl start firewalld.service ================================================ FILE: springboot-mybatis/scripts/docker/manager/setenv.sh ================================================ #ident "%W%" #!/bin/sh -x echo "[INFO] calling setenv.sh" #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi ############ # call common-env.sh ############ . ${SCRIPT_PATH}/common-env.sh #other env setup #xxx #xxx echo "[INFO] setenv.sh is done" #exit 0 is not allowed here which will stop calling script from going on executing ================================================ FILE: springboot-mybatis/scripts/docker/manager/start.sh ================================================ #ident "%W%" #!/bin/sh -x #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh mylog "[INFO] calling start.sh" HOSTNAME=`hostname` APPNAME=${prop_package} APPROOT=${prop_appRoot} APPHOME=${APPROOT}/${APPNAME} LOG=/tmp/start-${APPNAME}.log PROCESS_ID=`ps -ef | grep "${prop_dockerProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` isNumber ${PROCESS_ID} #$? represents the result of last unix command numberCheck=$? if [ numberCheck ]; then #kill -0 will send a signal to the process to check if the process exists, 0 menas exists and 1 vice visa if kill -0 ${PROCESS_ID} > /dev/null 2>&1; then mylog "" else mylog "[ERROR] docker daemon is not running on server <<${HOSTNAME}>>, pleae start it first" exit 1 fi fi #check docker image:version running or not count=`docker ps --no-trunc=true | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} = ${prop_dockerContainerCount} ]; then mylog "[WARN] ${prop_dockerContainerCount} containers for ${APPNAME} are already running on server <<${HOSTNAME}>>, will do nothing " exit 0 elif [ ${count} = 0 ]; then mylog "[INFO] checked no any ${APPNAME} is running on server <<${HOSTNAME}>>" else mylog "[ERROR] ${count} containers for ${APPNAME} are already running, but ${prop_dockerContainerCount} is expected. Please check why" exit 0 fi #check docker image name and version existing or not in doc repo count=`docker images | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} != 0 ]; then mylog "[INFO] image ${prop_dockerImageName} with version ${prop_dockerImageVersion} already exists in docker repo on host <<${HOSTNAME}>>" remove="yes" mylog "[????] Do you want to remove it and reload the image (default ${remove}):" read removeTmp if [ "${removeTmp}" != "" ]; then remove=${removeTmp} fi if [[ "yes" = "${remove}" || "YES" = "${remove}" ]]; then mylog "[COMMAND] docker rmi -f ${prop_dockerImageName}:${prop_dockerImageVersion}" docker rmi -f ${prop_dockerImageName}:${prop_dockerImageVersion} #check remove result count=`docker images | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} != 0 ]; then mylog "[ERROR] failed to remove image, please check why or remove it manually" exit 1 fi fi fi count=`docker images | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} = 0 ]; then imageTar=${prop_dockerImageName}-${prop_dockerImageVersion}.img.tar mylog "[WARN] image ${prop_dockerImageName} with version ${prop_dockerImageVersion} does not exist in docker repo on host <<${HOSTNAME}>>" mylog "[COMMAND] docker load < ${APPHOME}/current/${imageTar}" docker load < ${APPHOME}/current/${imageTar} #check loading result count=`docker images | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} != 1 ]; then mylog "[ERROR] failed to load image, please check why or load it manually" exit 1 fi fi DOCKER_PORT_MAPPINGS=${prop_dockerPortMappings} #replace ',' with space DOCKER_PORT_MAPPINGS=${DOCKER_PORT_MAPPINGS//,/ } DOCKER_CONFIG_FOLDER_MAPPING="${APPHOME}/current/${prop_dockerConfigFileMapping}" DOCKER_LOG_FOLDER_MAPPING="${APPHOME}/${prop_dockerLogFolderMapping}" DOCKER_UPLOAD_FOLDER_MAPPING="${APPHOME}/${prop_dockerUploadFolderMapping}" #for port mapping, each time a new container will increate the port no. #e.g for mapping 9200:9200, container 1 will have 9200:9200, container 2 will 9201:9200 i=0 while [ $i -le `expr ${prop_dockerContainerCount} - 1` ] do #concatenate each port mapping FINAL_PORT_MAPPING="" for k in ${DOCKER_PORT_MAPPINGS} do SOURCE_PORT=`echo ${k} | awk '{ split($0,array,":")} END {print array[1]}'` TARGET_PORT=`echo ${k} | awk '{ split($0,array,":")} END {print array[2]}'` FINAL_PORT_MAPPING="${FINAL_PORT_MAPPING} -p `expr ${SOURCE_PORT} + ${i}`:${TARGET_PORT}" done DOCKER_NODE_NAME="Node${i}-${HOSTNAME}" #replace xxx with node name, each node will have seperate data folder/log folder FINAL_LOG_FOLDER_MAPPING=${DOCKER_LOG_FOLDER_MAPPING//nodexxx/${DOCKER_NODE_NAME}} #create the mapping folder if not existing in host # and change folder mode to 777 in case that docker containers cannot write to host folder SOURCE_LOG_FOLDER=`echo ${FINAL_LOG_FOLDER_MAPPING} | awk '{ split($0,array,":")} END {print array[1]}'` #create source folder is not existing myexecute "mkdir -p ${SOURCE_LOG_FOLDER}" #change mode in case that docker container cannot write data to host folder myexecute "chmod -R 777 ${SOURCE_LOG_FOLDER}" mylog "[INFO] starting new docker container for ${APPNAME} on host <<${HOSTNAME}>>" myexecute "docker run \ --net=host \ -d \ ${FINAL_PORT_MAPPING} \ -v ${prop_javaHome}:/opt/apps/java \ -v ${DOCKER_CONFIG_FOLDER_MAPPING} \ -v ${FINAL_LOG_FOLDER_MAPPING} \ -v ${DOCKER_UPLOAD_FOLDER_MAPPING} \ ${prop_dockerImageName}:${prop_dockerImageVersion} \ " #i++ i=`expr $i + 1` #sleep to wait server process up myexecute "sleep ${prop_startOneSleep}" mylog "------------------------------------" mylog "" done count=`docker ps --no-trunc=true | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} = ${prop_dockerContainerCount} ]; then mylog "[INFO] ${prop_dockerContainerCount} docker containers for ${APPNAME} started successfully on server <<${HOSTNAME}>>" elif [ ${count} = 0 ]; then mylog "[ERROR] All containers for ${APPNAME} failed to start on server <<${HOSTNAME}>>, yon can check log by /var/lib/docker/containers/xxx/*.log" else mylog "[ERROR] ${prop_dockerContainerCount} containers for ${APPNAME} are expected, but only ${count} started on server <<${HOSTNAME}>>, yon can check log by /var/lib/docker/containers/xxx/*.log" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/docker/manager/stop.sh ================================================ #ident "%W%" #!/bin/sh -x #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh mylog "[INFO] calling stop.sh" APPNAME=${prop_package} HOSTNAME=`hostname` STOP_TIMEOUT=${prop_stopNodeTimeout} mylog "[INFO] Stopping containers for ${APPNAME} on host ${HOSTNAME}" PROCESS_ID=`ps -ef | grep "${prop_dockerProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` isNumber ${PROCESS_ID} #$? represents the result of last unix command numberCheck=$? if [ numberCheck ]; then #kill -0 will send a signal to the process to check if the process exists, 0 menas exists and 1 vice visa if kill -0 ${PROCESS_ID} > /dev/null 2>&1; then mylog "[DEBUG] checked docker daemon is running well on server <<${HOSTNAME}>> with pid: ${PROCESS_ID}" else mylog "[ERROR] docker daemon is not running on server <<${HOSTNAME}>>, pleae start it first" exit 0 fi fi #check nginx container existing or not count=`docker ps | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} != 0 ]; then mylog "[INFO] checked total ${count} containers for ${APPNAME} are running, gonna stop them" CONTAINER_IDS=`docker ps | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | awk '{ print $1 }'` for i in $CONTAINER_IDS do mylog "[INFO] stopping container id <<${i}>>" myexecute "docker stop ${i}" myexecute "sleep ${STOP_TIMEOUT}" #check again if the container is stopped successfully count=`docker ps | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | grep ${i} | wc -l` if [ ${count} != "0" ]; then mylog "[WARN] failed to stop the container <<${i}>>, gonna kill it" myexecute "docker kill ${i}" fi done else mylog "[INFO] no any container for ${APPNAME} is running, will do nothing" exit 0; fi #check finally count=`docker ps | grep "${prop_dockerImageName}" | grep "${prop_dockerImageVersion}" | wc -l` if [ ${count} != "0" ]; then mylog "[ERROR] failed to stop/kill all containers for ${APPNAME}, please stop it manually" fi mylog "[INFO] all containers for ${APPNAME} are stopped successfully on server <<${HOSTNAME}>>" exit 0 ================================================ FILE: springboot-mybatis/scripts/springboot/common/common-env.sh ================================================ #ident "%W%" #!/bin/sh -x #SCRIPT_PATH must be defined firstly by calling script echo "[INFO] calling common-env.sh" if [ "${SCRIPT_PATH}" = "" ]; then echo "[ERROR] SCRIPT_PATH is not defined in calling script" exit 1 else ############# # define own function ############# #print out command into console (and log file if there is one) and then execute it myexecute () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theCommand=${1} echo "${dt}: [COMMAND] ${theCommand}" if [ "${LOG}" != "" ]; then echo "${dt}: [COMMAND] ${theCommand}" >> ${LOG} fi ${theCommand} } myexecute2 () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theCommand=${1} echo "${dt}: [COMMAND] ${theCommand}" if [ "${LOG}" != "" ]; then echo "${dt}: [COMMAND] ${theCommand}" >> ${LOG} fi eval ${theCommand} } #print out log into console (and log file if there is one) mylog () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theLog=${1} echo "${dt}: ${theLog}" if [ "${LOG}" != "" ]; then echo "${dt}: ${theLog}" >> ${LOG} fi } #print out log into console (and log file if there is one), and transate \n into new line mylog2 () { local dt=`date +%Y-%m-%d\ %H:%M:%S` local theLog=${1} echo -e "${dt}: ${theLog}" if [ "${LOG}" != "" ]; then echo -e "${dt}: ${theLog}" >> ${LOG} fi } #check it is a number or not isNumber () { var=${1} if [ ${var} -eq ${var} 2> /dev/null ] then return 0 else return 1 fi } ############ # to export variables ############ #export all variables in env.properties echo "[INFO] export all variables in env.properties" if [ -f ${SCRIPT_PATH}/../env/env.properties ]; then myexecute "source ${SCRIPT_PATH}/../env/env.properties" elif [ -f ${SCRIPT_PATH}/../env/env.properties ]; then myexecute "source ${SCRIPT_PATH}/../env/env.properties" else echo "[ERROR] cannot find env.properties" exit 1 fi fi echo "[INFO] common-env.sh is done" #exit 0 is not allowed here which is stop calling script from going on executing ================================================ FILE: springboot-mybatis/scripts/springboot/common/install-cluster.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used for cluster install ############################### #the path of this script when running if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh # The preinstall.sh has been lost.(It is unused.) if [ "${prop_runPreinstall}" = "true" ]; then myexecute "${SCRIPT_PATH}/preinstall.sh" if [ $? != 0 ]; then exit 1 fi fi mylog "[INFO] Begin install-cluster.sh" APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log APPROOT=${prop_appRoot} APPNAME=${prop_package} APPHOME=${APPROOT}/${APPNAME} HOSTNAME=`hostname` CLUSTER_NODES=${prop_clusterNodes} #replace ',' with space CLUSTER_NODES=${CLUSTER_NODES//,/ } #replace '"' with null CLUSTER_NODES=${CLUSTER_NODES//\"/} MANUAL_FOLDERS=${prop_manualFolders} MANUAL_FOLDER_MODE=${prop_manualFolderMode} for i in ${CLUSTER_NODES} do mylog "" mylog "-----------------------------" mylog "[INFO] Connecting to host ${i}" #create app home folder and new version folder myexecute "ssh -oStrictHostKeyChecking=no root@${i} mkdir -p ${APPHOME}/${APPVERSION}" mylog "[INFO] Folder ${APPHOME}/${APPVERSION} is created successfully on host <<${i}>>" #copy files from current host to another node by scp command #-p preserves modification times, access times, and modes from the original file mylog "[INFO] copying files to host <<${i}>> by scp command" myexecute "scp -rp ${SCRIPT_PATH}/../* root@${i}:${APPHOME}/${APPVERSION}/" mylog "[INFO] Copy is done!" #change owner and group for app package mylog "[INFO] changing owner and group recursively" myexecute "ssh -oStrictHostKeyChecking=no root@${i} chown -R ${prop_ownerGroup} ${APPHOME}/${APPVERSION}/" mylog "[INFO] Owner and group set up done!" #create manual folders if [ "${MANUAL_FOLDERS}" != "" ]; then theCommand="ssh -oStrictHostKeyChecking=no root@${i} \"pwd " for MANUAL_FOLDER in ${MANUAL_FOLDERS} do theCommand="${theCommand} && mkdir -p ${APPHOME}/${MANUAL_FOLDER}" if [ "${MANUAL_FOLDER_MODE}" != "" ]; then theCommand="${theCommand} && chmod -R ${MANUAL_FOLDER_MODE} ${APPHOME}/${MANUAL_FOLDER}" fi done theCommand="${theCommand} \" " myexecute2 "${theCommand}" fi #create soft link named 'current', -s:soft link -v:debug mode -n:treate link as normal file if it linking to a folder #-f:force create it is already there mylog "[INFO] Create soft link named 'current'" myexecute "ssh -oStrictHostKeyChecking=no root@${i} ln -svnf ${APPHOME}/${APPVERSION} ${APPHOME}/current" mylog "[INFO] Link creation is done!" if [ "${prop_runPostinstall}" = "true" ]; then myexecute "ssh -oStrictHostKeyChecking=no root@${i} ${APPHOME}/current/scripts/postinstall.sh" mylog "[INFO] postinstall is done on node ${i}" fi mylog "--------------------------------" done mylog "[INFO] Cluster installation is done successfully, for more detail please check log ${LOG}" exit 0 ================================================ FILE: springboot-mybatis/scripts/springboot/common/install-single.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used for single server install ############################### #the path of this script when running if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh # The preinstall.sh has been lost.(It is unused.) if [ "${prop_runPreinstall}" = "true" ]; then myexecute ". ${SCRIPT_PATH}/preinstall.sh" if [ $? != 0 ]; then exit 1 fi fi mylog "[INFO] Begin install-single.sh" APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log APPROOT=${prop_appRoot} APPNAME=${prop_package} APPHOME=${APPROOT}/${APPNAME} HOSTNAME=`hostname` SINGLE_NODE=${prop_singleNode} MANUAL_FOLDERS=${prop_manualFolders} MANUAL_FOLDER_MODE=${prop_manualFolderMode} mylog "" mylog "-----------------------------" mylog "[INFO] Installing on host ${SINGLE_NODE}" #create app home folder and new version folder myexecute "mkdir -p ${APPHOME}/${APPVERSION}" mylog "[INFO] Folder ${APPHOME}/${APPVERSION} is created successfully on host <<${SINGLE_NODE}>>" #copy files from current folder to app home folder #-p reserve the specified attributes (default: mode,ownership,timestamps) mylog "[INFO] copying files to host <<${SINGLE_NODE}>> by cp command" myexecute "cp -rp ${SCRIPT_PATH}/../* ${APPHOME}/${APPVERSION}/" mylog "[INFO] Copy is done!" #change owner and group for app package mylog "[INFO] changing owner and group recursively" myexecute "chown -R ${prop_ownerGroup} ${APPHOME}/${APPVERSION}" mylog "[INFO] Owner and group set up done!" #create manual folders if [ "${MANUAL_FOLDERS}" != "" ]; then for MANUAL_FOLDER in ${MANUAL_FOLDERS} do myexecute "mkdir -p ${APPHOME}/${MANUAL_FOLDER}" if [ "${MANUAL_FOLDER_MODE}" != "" ]; then myexecute "chmod -R ${MANUAL_FOLDER_MODE} ${APPHOME}/${MANUAL_FOLDER}" fi done fi #create soft link named 'current', -s:soft link -v:debug mode -n:treate link as normal file if it linking to a folder #-f:force create it ignoring if it is already there mylog "[INFO] Create soft link named 'current'" myexecute "ln -svnf ${APPHOME}/${APPVERSION} ${APPHOME}/current" mylog "[INFO] Link creation is done!" mylog "--------------------------------" mylog "[INFO] Installation is done successfully, for more detail please check log ${LOG}" mylog "------------------------------------" mylog "------------------------------------" # The postinstall.sh has been lost.(It is unused.) if [ "${prop_runPostinstall}" = "true" ]; then myexecute ". ${SCRIPT_PATH}/postinstall.sh" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/springboot/common/install.sh ================================================ #ident "%W%" #!/bin/sh -x ############################### ## used to install package ############################### #the path of this script when running if cd "`dirname $0`"; then export SCRIPT_PATH=${PWD} echo "[INFO] export SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh APPVERSION=`date +%Y%m%d-%H%M%S` LOG=/tmp/install-${prop_package}-${APPVERSION}.log mylog "[INFO] Begin install.sh" #check it is a single node installation or a cluster installation if [ "${prop_isCluster}" = "true" ]; then mylog "[INFO] checked you are doing CLUSTER installation" myexecute "${SCRIPT_PATH}/install-cluster.sh" else mylog "[INFO] checked you are doing SINGLE NODE installation" myexecute "${SCRIPT_PATH}/install-single.sh" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/springboot/common/package.xml ================================================ 0.1 tar scripts/${package.format}/manager /scripts 0755 scripts/${package.format}/common /scripts 0755 install-cluster.sh install-single.sh install.sh common-env.sh env/${package.environment} /env target/${package}-${package.version}.war / ${package}-${package.version}.war 0755 ================================================ FILE: springboot-mybatis/scripts/springboot/manager/setenv.sh ================================================ #ident "%W%" #!/bin/sh -x echo "[INFO] calling setenv.sh" #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi ############ # call common-env.sh ############ . ${SCRIPT_PATH}/common-env.sh #other env setup #xxx #xxx echo "[INFO] setenv.sh is done" #exit 0 is not allowed here which will stop calling script from going on executing ================================================ FILE: springboot-mybatis/scripts/springboot/manager/start.sh ================================================ #ident "%W%" #!/bin/sh -x #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh mylog "[INFO] calling start.sh" HOSTNAME=`hostname` APPNAME=${prop_package} APPROOT=${prop_appRoot} APPHOME=${APPROOT}/${APPNAME} LOG=/tmp/start-${APPNAME}.log #check java home JAVA_HOME=${prop_javaHome} if [ "${JAVA_HOME}" = "" ]; then mylog "[ERROR] JAVA_HOME cannot be null" exit 1 elif [ ! -d ${JAVA_HOME} ]; then mylog "[ERROR] ${JAVA_HOME} does not exist as JAVA_HOME" exit 1 fi #check if springboot process is up or not PROCESS_ID=`ps -ef | grep java | grep "${prop_springbootProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` if [ ${PROCESS_ID} ]; then mylog "[WARN] ${APPNAME} is already running with process id ${PROCESS_ID} on server <<${HOSTNAME}>>" exit 0 else mylog "[INFO] checked no ${APPNAME} running process on server <<${HOSTNAME}>>, will start it" fi #start up new process springbootExecutableWar=${APPHOME}/current/${prop_springbootWarName}-${prop_springbootWarVersion}.war myexecute2 "nohup ${JAVA_HOME}/bin/java -jar ${springbootExecutableWar} --spring.config.location=${APPHOME}/current/env/application.properties >/dev/null 2>&1 &" myexecute2 "sleep ${prop_startOneSleep}" PROCESS_ID=`ps -ef | grep java | grep "${prop_springbootProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` if [ ${PROCESS_ID} ]; then mylog "[INFO] ${APPNAME} started successfully with process id ${PROCESS_ID} on server <<${HOSTNAME}>>" else mylog "[ERROR] ${APPNAME} failed to start up on server <<${HOSTNAME}>>, you can check log ${LOG}" fi exit 0 ================================================ FILE: springboot-mybatis/scripts/springboot/manager/stop.sh ================================================ #ident "%W%" #!/bin/sh -x #find out the absolute path of the script when being executed if cd "`dirname $0`"; then SCRIPT_PATH=${PWD} echo "[INFO] SCRIPT_PATH=${SCRIPT_PATH}" cd "${OLDPWD}" || exit 1 else echo "[ERROR] cannot find script folder path" exit 1 fi #call setenv . ${SCRIPT_PATH}/setenv.sh mylog "[INFO] calling stop.sh" APPNAME=${prop_package} HOSTNAME=`hostname` STOP_TIMEOUT=${prop_stopNodeTimeout} mylog "[INFO] Stopping ${APPNAME} on host ${HOSTNAME}" #check if springboot process is up or not PROCESS_ID=`ps -ef | grep java | grep "${prop_springbootProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` if [ ${PROCESS_ID} ]; then mylog "[INFO] found running ${APPNAME} process with id = ${PROCESS_ID} on server <<${HOSTNAME}>>, will stop it" #stop running process myexecute2 "kill -9 ${PROCESS_ID}" myexecute2 "sleep ${prop_stopNodeTimeout}" else mylog "[WARN] no running ${APPNAME} process on server <<${HOSTNAME}>>" exit 0 fi #check again PROCESS_ID=`ps -ef | grep java | grep "${prop_springbootProcessKeyWord}" | grep -v grep | awk '{ print $2 }'` if [ ${PROCESS_ID} ]; then mylog "[ERROR] failed to stop running ${APPNAME} process with id = ${PROCESS_ID} on server <<${HOSTNAME}>>, you can check log ${LOG}" exit 1 else mylog "[INFO] ${APPNAME} is stopped successfully on server <<${HOSTNAME}>>" fi exit 0 ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import org.springframework.scheduling.annotation.EnableScheduling; import static org.springframework.boot.SpringApplication.*; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example,com.jf") @SpringBootApplication @EnableScheduling public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/bean/User.java ================================================ package com.us.example.bean; import java.util.Date; public class User { private Integer id; /** The name. */ private String name; /** The password. */ private String password; /** The rePassword. */ private String rePassword; /** The username. */ private String username; /** The division id. */ private Integer divisionId; /** The email. */ private String email; /** The gender. */ private String gender; /** The mobilephone. */ private String mobilephone; /** The telephone. */ private String telephone; /** The user type. */ private Integer userType; /** The create by. */ private String createBy; /** The create time. */ private Date createTime; /** The update by. */ private String updateBy; /** The update time. */ private Date updateTime; /** The disabled. */ private Integer disabled; /** The theme. */ private String theme; /** The is ldap. */ private Integer isLdap; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } /** * Get the name. * * @return the name */ public String getName() { return name; } /** * Set the name. * * @param name the name */ public void setName(String name) { this.name = name; } /** * Get the re password. * * @return the re password */ public String getRePassword() { return rePassword; } /** * Set the re password. * * @param rePassword the re password */ public void setRePassword(String rePassword) { this.rePassword = rePassword; } /** * Get the password. * * @return the password */ public String getPassword() { return password; } /** * Set the password. * * @param password the password */ public void setPassword(String password) { this.password = password; } /** * Get the username. * * @return the username */ public String getUsername() { return username; } /** * Set the username. * * @param username the username */ public void setUsername(String username) { this.username = username; } /** * Get the division id. * * @return the division id */ public Integer getDivisionId() { return divisionId; } /** * Set the division id. * * @param divisionId the division id */ public void setDivisionId(Integer divisionId) { this.divisionId = divisionId; } /** * Get the email. * * @return the email */ public String getEmail() { return email; } /** * Set the email. * * @param email the email */ public void setEmail(String email) { this.email = email; } /** * Get the gender. * * @return the gender */ public String getGender() { return gender; } /** * Set the gender. * * @param gender the gender */ public void setGender(String gender) { this.gender = gender; } /** * Get the mobilephone. * * @return the mobilephone */ public String getMobilephone() { return mobilephone; } /** * Set the mobilephone. * * @param mobilephone the mobilephone */ public void setMobilephone(String mobilephone) { this.mobilephone = mobilephone; } /** * Get the telephone. * * @return the telephone */ public String getTelephone() { return telephone; } /** * Set the telephone. * * @param telephone the telephone */ public void setTelephone(String telephone) { this.telephone = telephone; } /** * Get the user type. * * @return the user type */ public Integer getUserType() { return userType; } /** * Set the user type. * * @param userType the user type */ public void setUserType(Integer userType) { this.userType = userType; } /** * Get the creates the by. * * @return the creates the by */ public String getCreateBy() { return createBy; } /** * Set the creates the by. * * @param createBy the creates the by */ public void setCreateBy(String createBy) { this.createBy = createBy; } /** * Get the creates the time. * * @return the creates the time */ public Date getCreateTime() { return createTime; } /** * Set the creates the time. * * @param createTime the creates the time */ public void setCreateTime(Date createTime) { this.createTime = createTime; } /** * Get the update by. * * @return the update by */ public String getUpdateBy() { return updateBy; } /** * Set the update by. * * @param updateBy the update by */ public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } /** * Get the update time. * * @return the update time */ public Date getUpdateTime() { return updateTime; } /** * Set the update time. * * @param updateTime the update time */ public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } /** * Get the disabled. * * @return the disabled */ public Integer getDisabled() { return disabled; } /** * Set the disabled. * * @param disabled the disabled */ public void setDisabled(Integer disabled) { this.disabled = disabled; } /** * Get the theme. * * @return the theme */ public String getTheme() { return theme; } /** * Set the theme. * * @param theme theme */ public void setTheme(String theme) { this.theme = theme; } /** * Get the checks if is ldap. * * @return the checks if is ldap */ public Integer getIsLdap() { return isLdap; } /** * Set the checks if is ldap. * * @param isLdap the checks if is ldap */ public void setIsLdap(Integer isLdap) { this.isLdap = isLdap; } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/config/DBConfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/config/MyBatisConfig.java ================================================ package com.us.example.config; import javax.sql.DataSource; import com.jf.page.interceptor.PageInterceptor; import org.apache.ibatis.plugin.Interceptor; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()}); sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/config/MyBatisScannerConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/config/TransactionConfig.java ================================================ package com.us.example.config; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/controller/UserController.java ================================================ package com.us.example.controller; import javax.servlet.http.HttpServletRequest; import java.util.Map; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.us.example.service.UserService; import com.us.example.util.CommonUtil; /** * * @ClassName UserController * @author abel * @date 2016年11月10日 */ @Controller @RequestMapping(value = "/users") public class UserController { private static final Logger logger = Logger.getLogger(UserController.class); @Autowired private UserService userService; /*** * api :localhost:8099/users?id=99 * http://localhost:8099/users?limit=2&page=2 * @param request * @return */ @RequestMapping(method = RequestMethod.GET, produces = "application/json;charset=UTF-8") @ResponseBody public ResponseEntity list(HttpServletRequest request) { Map map = CommonUtil.getParameterMap(request); return new ResponseEntity<>(userService.getList(map), HttpStatus.OK); } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/dao/UserDao.java ================================================ package com.us.example.dao; import java.util.List; import java.util.Map; import com.us.example.bean.User; public interface UserDao { List getList(Map map); } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/service/Impl/UserServiceImpl.java ================================================ package com.us.example.service.Impl; import java.util.Date; import java.util.Map; import com.jf.page.annotation.Page; import javafx.scene.input.DataFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import com.us.example.dao.UserDao; import com.us.example.service.UserService; /** * * @ClassName UserServiceImpl * @author abel * @date 2016年11月10日 */ @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; /** * * @param map * @return */ @Page @Override public Object getList(Map map) { return userDao.getList(map); } //每一秒调用一次 -- 用于测试 @Scheduled(cron = "0/30 * * * * ?") @Override public void printName() { System.out.println(new Date()); System.out.println("my name is yang "); } } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/service/UserService.java ================================================ package com.us.example.service; import java.util.Map; import com.us.example.bean.User; /** * The Interface UserService. */ public interface UserService { /** * Gets the list. * * @param map the map * @return the list */ Object getList(Map map); void printName(); } ================================================ FILE: springboot-mybatis/src/main/java/com/us/example/util/CommonUtil.java ================================================ package com.us.example.util; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; public class CommonUtil { /** * 从request中获得参数Map,并返回可读的Map. * * @param request the request * @return the parameter map */ public static Map getParameterMap(HttpServletRequest request) { // 参数Map Map properties = request.getParameterMap(); //返回值Map Map returnMap = new HashMap(); Set keySet = properties.keySet(); for(String key: keySet){ String[] values = properties.get(key); String value = ""; if(values != null && (values.length==1&&StringUtils.isNotBlank(values[0]))?true:false){ for(int i=0;i and ID = #{id} and NAME = #{name} and PASSWORD = #{password} and USERNAME = #{username} and DIVISION_ID = #{divisionId} and EMAIL = #{email} and GENDER = #{gender} and MOBILEPHONE = #{mobilephone} and TELEPHONE = #{telephone} and USER_TYPE = #{userType} and DISABLED = #{disabled} and THEME = #{theme} and (name like CONCAT('%', #{keywords},'%') OR username like CONCAT('%', #{keywords},'%') OR telephone like CONCAT('%', #{keywords},'%') OR email like CONCAT('%', #{keywords},'%') ) ================================================ FILE: springboot-mybatis/src/test/java/com/us/example/BaseTest.java ================================================ package com.us.example; import com.us.example.config.DBConfig; import com.us.example.config.MyBatisConfig; import com.us.example.config.MyBatisScannerConfig; import org.junit.Assert; import org.junit.runner.RunWith; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * Created by yangyibo on 17/2/10. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {BaseTest.ComponentScanConfig.class, DBConfig.class, MyBatisScannerConfig.class, MyBatisConfig.class}) @TestPropertySource("/application.properties") public class BaseTest extends AbstractTransactionalJUnit4SpringContextTests { @Configuration @ComponentScan(basePackages = {"com.us.example"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } public void assertNotNull(Object obj) { System.out.println(obj); Assert.assertNotNull(obj); } } ================================================ FILE: springboot-mybatis/src/test/java/com/us/example/service/UserServiceTest.java ================================================ package com.us.example.service; import com.us.example.BaseTest; import org.springframework.beans.factory.annotation.Autowired; import org.junit.Test; import java.util.HashMap; import java.util.Map; /** * Created by yangyibo on 17/2/10. */ public class UserServiceTest extends BaseTest { @Autowired UserService userService; @Test public void getListTest() { Map map = new HashMap(); map.put("id", 1); userService.getList(map); } } ================================================ FILE: springboot-mybatis/tar-it.sh ================================================ #!/bin/bash ################################ # based on maven assembly plugin environment=$1 package=$2 packageVersion=$3 packageFormat=$4 if [ "${environment}" = "" ]; then echo [ERROR] "Please provide env as first param" exit 1 fi if [ "${package}" = "" ]; then echo [ERROR] "Please provide package name as second param" exit 1 fi if [ "${packageVersion}" = "" ]; then echo [ERROR] "Please provide version as third param" exit 1 fi if [ "${packageFormat}" = "" ]; then echo [ERROR] "Please provide package format as forth param" exit 1 fi theCommand="mvn -e assembly:single -Dpackage=${package} -Dpackage.version=${packageVersion} -Dpackage.environment=${environment} -Dpackage.format=${packageFormat}" echo ${theCommand} ${theCommand} ================================================ FILE: springboot-mybatis/war-it.sh ================================================ #!/bin/sh # the java must be goal .I think it may be not very good. (Sean 20170216) COUNT=`java -version 2>&1 | grep 'java version' | grep 1.8 | grep -v grep | wc -l` if [ ${COUNT} != 1 ]; then COUNT=`echo $JAVA_HOME | grep 1.8 | grep -v grep | wc -l` if [ ${COUNT} != 1 ]; then echo [ERROR] "Cannot find java 8" exit 1 fi fi package=$1 version=$2 env=$3 resources=$4 if [ "${package}" = "" ]; then echo [ERROR] "Please provide package name as first param" exit 1 fi if [ "${version}" = "" ]; then echo [ERROR] "Please provide package version as second param" exit 1 fi if [ "${env}" = "" ]; then echo [ERROR] "Please provide env as third param" exit 1 fi #在pom.xml文件里面定义的 maven的参数 详细请看 maven -D 命令的含义 #-X To debug the command. theCommand="mvn clean package -Dpackage=${package} -Dpackage.version=${version} -Dpackage.environment=${env} -Dpackage.resources=${resources} " echo [INFO] ${theCommand} exec ${theCommand} ================================================ FILE: springboot-mybatis2/pom.xml ================================================ 4.0.0 cn.abel springboot-mybatis2 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-freemarker org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2 com.github.pagehelper pagehelper-spring-boot-starter 1.2.5 mysql mysql-connector-java 5.1.40 org.apache.commons commons-lang3 3.4 ================================================ FILE: springboot-mybatis2/sql/user.sql ================================================ /* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 50719 Source Host : 127.0.0.1 Source Database : oldMan Target Server Type : MySQL Target Server Version : 50719 File Encoding : utf-8 Date: 04/02/2019 15:27:32 PM */ SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for `user` -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL, `address` varchar(200) DEFAULT NULL, `mobile` varchar(50) DEFAULT NULL, `email` varchar(100) DEFAULT NULL, `create_time` datetime DEFAULT NULL, `role` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4; SET FOREIGN_KEY_CHECKS = 1; ================================================ FILE: springboot-mybatis2/src/main/java/cn/abel/Application.java ================================================ package cn.abel; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/3/26 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-mybatis2/src/main/java/cn/abel/bean/User.java ================================================ package cn.abel.bean; import java.util.Date; public class User { private Integer id; private String name; private String address; private String mobile; private String email; private Date createTime; private Integer role; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Integer getRole() { return role; } public void setRole(Integer role) { this.role = role; } } ================================================ FILE: springboot-mybatis2/src/main/java/cn/abel/dao/UserDao.java ================================================ package cn.abel.dao; import java.util.List; import java.util.Map; import cn.abel.bean.User; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository; @Repository @Mapper public interface UserDao { List getByMap(Map map); User getById(Integer id); Integer create(User user); int update(User user); int delete(Integer id); } ================================================ FILE: springboot-mybatis2/src/main/java/cn/abel/service/UserService.java ================================================ package cn.abel.service; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import cn.abel.dao.UserDao; import cn.abel.bean.User; @Service public class UserService { @Autowired private UserDao userDao; public List getByMap(Map map){ return userDao.getByMap(map); } public User getById(Integer id){ return userDao.getById(id); } public User create(User user){ userDao.create(user); return user; } public User update(User user){ userDao.update(user); return user; } public int delete(Integer id){ return userDao.delete(id); } } ================================================ FILE: springboot-mybatis2/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=8009 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.risk.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=springboot-mybatis2 application.main=cn.abel.Application ## LOG logging.file=./logs/springboot-mybatis2.log ## \u4E3B\u6570\u636E\u6E90\uFF0C\u9ED8\u8BA4\u7684 spring.datasource.url=jdbc:mysql://localhost:3306/oldMan?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=admin spring.datasource.driverClassName=com.mysql.jdbc.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource #\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.datasource.min-idle=5 #\u6700\u5927\u8FDE\u63A5\u6570\u91CF spring.datasource.max-active=100 #\u68C0\u6D4B\u6570\u636E\u5E93\u7684\u67E5\u8BE2\u8BED\u53E5 spring.datasource.validation-query=select 1 from dual #\u7B49\u5F85\u8FDE\u63A5\u6C60\u5206\u914D\u8FDE\u63A5\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.connection-timeout=60000 #\u4E00\u4E2A\u8FDE\u63A5\u7684\u751F\u547D\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.max-left-time=60000 #\u751F\u6548\u8D85\u65F6 spring.datasource.validation-time-out=3000 #\u4E00\u4E2A\u8FDE\u63A5idle\u72B6\u6001\u7684\u6700\u5927\u65F6\u957F\uFF08\u6BEB\u79D2\uFF09 spring.datasource.idle-time-out=60000 #\u8BBE\u7F6E\u9ED8\u8BA4\u5B57\u7B26\u96C6 spring.datasource.connection-init-sql= set names utf8mb4 logging.level.cn.abel.dao=debug #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E mybatis.mapper-locations=classpath*:mapper/*Mapper.xml smybatis.type-aliases-package=cn.abel.bean #Mapper.xml\u6240\u5728\u7684\u4F4D\u7F6E ## pagehelper pagehelper.helperDialect=mysql pagehelper.reasonable=true pagehelper.supportMethodsArguments=true pagehelper.params=count=countSql ================================================ FILE: springboot-mybatis2/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-mybatis2/src/main/resources/local/logback-spring.xml ================================================ abel_user %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-mybatis2/src/main/resources/mapper/NewsDaoMapper.xml ================================================ and id = #{id} and title = #{title} and content = #{content} and image_path = #{imagePath} and read_sum = #{readSum} SELECT LAST_INSERT_ID() INSERT INTO news( id, title, content, image_path, read_sum )VALUES( #{id}, #{title}, #{content}, #{imagePath}, #{readSum} ) UPDATE news SET title = #{title}, content = #{content}, image_path = #{imagePath}, read_sum = #{readSum} WHERE id = #{id} DELETE FROM news WHERE id = #{id} ================================================ FILE: springboot-mybatis2/src/main/resources/mapper/UserDaoMapper.xml ================================================ and id = #{id} and name = #{name} and address = #{address} and mobile = #{mobile} and email = #{email} and role = #{role} SELECT LAST_INSERT_ID() INSERT INTO user( id, name, address, mobile, email, create_time, role )VALUES( #{id}, #{name}, #{address}, #{mobile}, #{email}, NOW(), #{role} ) UPDATE user SET name = #{name}, address = #{address}, mobile = #{mobile}, email = #{email}, role = #{role} WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-mybatis2/src/test/java/cn/abel/BaseTest.java ================================================ package cn.abel; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; /** * @author yyb * @time 2019/3/27 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @TestPropertySource("/application.properties") public class BaseTest { @Configuration @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } @Test public void contextLoads() { } } ================================================ FILE: springboot-mybatis2/src/test/java/cn/abel/service/ServiceTest.java ================================================ package cn.abel.service; import cn.abel.BaseTest; import cn.abel.bean.User; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * @author yyb * @time 2019/3/27 */ public class ServiceTest extends BaseTest { @Autowired private UserService userService; @Test public void dynamicDataSourceTest() throws Exception { List userList = userService.getByMap(null); System.out.println("--userList---" + userList.size()); } } ================================================ FILE: springboot-neo4j/pom.xml ================================================ 4.0.0 cn.abel springboot-neo4j 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-freemarker org.mybatis.spring.boot mybatis-spring-boot-starter 1.3.2 com.github.pagehelper pagehelper-spring-boot-starter 1.2.5 mysql mysql-connector-java 5.1.40 org.apache.commons commons-lang3 3.4 com.alibaba fastjson 1.2.40 org.springframework.boot spring-boot-starter-data-neo4j org.neo4j neo4j-ogm-http-driver org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/Application.java ================================================ package cn.abel.neo4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * @author yyb * @time 2019/3/26 */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/bean/King.java ================================================ package cn.abel.neo4j.bean; import cn.abel.neo4j.bean.relation.FatherAndSonRelation; import org.neo4j.ogm.annotation.NodeEntity; import org.neo4j.ogm.annotation.Relationship; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * 皇帝 * * @author yyb * @time 2020/3/23 */ @NodeEntity(label = "King") public class King extends Person implements Serializable { /** * 名字 */ private String name; /** * 家系:家族关系 */ private String clan; /** * 年号:生活的时代 */ private String times; /** * 谥号:人死之后,后人给予评价 */ private String posthumousTitle; /** * 庙号:君主于庙中被供奉时所称呼的名号 */ private String TempleNumber; /** * 陵墓 */ private String tomb; /** * 大事件 */ private String remark; @Relationship(type = "传位") King successor; /** * 第二种保存关系的方式 */ @Relationship List sons; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClan() { return clan; } public void setClan(String clan) { this.clan = clan; } public String getTimes() { return times; } public void setTimes(String times) { this.times = times; } public String getPosthumousTitle() { return posthumousTitle; } public void setPosthumousTitle(String posthumousTitle) { this.posthumousTitle = posthumousTitle; } public String getTempleNumber() { return TempleNumber; } public void setTempleNumber(String templeNumber) { TempleNumber = templeNumber; } public String getTomb() { return tomb; } public void setTomb(String tomb) { this.tomb = tomb; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public King getSuccessor() { return successor; } public void setSuccessor(King successor) { this.successor = successor; } public List getSons() { return sons; } public void setSons(List sons) { this.sons = sons; } /** * 添加友谊的关系 * @param */ public void addRelation(FatherAndSonRelation fatherAndSonRelation){ if(this.sons == null){ this.sons = new ArrayList<>(); } this.sons.add(fatherAndSonRelation); } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Person.java ================================================ package cn.abel.neo4j.bean; import org.neo4j.ogm.annotation.GeneratedValue; import org.neo4j.ogm.annotation.Id; import org.neo4j.ogm.annotation.Index; /** * @author yyb * @time 2020/3/23 */ public class Person { @Id // @GeneratedValue 该注解应去除否则插入不成功 @Index private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/bean/Queen.java ================================================ package cn.abel.neo4j.bean; import org.neo4j.ogm.annotation.Relationship; /** * 皇后 * * @author yyb * @time 2020/3/23 */ public class Queen extends Person { /** * 名字 */ private String name; /** * 家系:家族关系 */ private String clan; /** * 年号:生活的时代 */ private String times; /** * 庙号:君主于庙中被供奉时所称呼的名号 */ private String TempleNumber; /** * 谥号:人死之后,后人给予评价 */ private String posthumousTitle; /** * 陵墓 */ private String son; /** * 备注 */ private String remark; /** * 关系指向自己 */ @Relationship(type = "皇后", direction = Relationship.INCOMING) private King king; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClan() { return clan; } public void setClan(String clan) { this.clan = clan; } public String getTimes() { return times; } public void setTimes(String times) { this.times = times; } public String getTempleNumber() { return TempleNumber; } public void setTempleNumber(String templeNumber) { TempleNumber = templeNumber; } public String getPosthumousTitle() { return posthumousTitle; } public void setPosthumousTitle(String posthumousTitle) { this.posthumousTitle = posthumousTitle; } public String getSon() { return son; } public void setSon(String son) { this.son = son; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public King getKing() { return king; } public void setKing(King king) { this.king = king; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/bean/relation/FatherAndSonRelation.java ================================================ package cn.abel.neo4j.bean.relation; import cn.abel.neo4j.bean.King; import org.neo4j.ogm.annotation.EndNode; import org.neo4j.ogm.annotation.Id; import org.neo4j.ogm.annotation.RelationshipEntity; import org.neo4j.ogm.annotation.StartNode; /** * 父子关系实体 * @author yyb * @time 2020/3/24 */ @RelationshipEntity(type = "father_son") public class FatherAndSonRelation { @Id private long id; @StartNode private King from; @EndNode private King to; public long getId() { return id; } public void setId(long id) { this.id = id; } public King getFrom() { return from; } public void setFrom(King from) { this.from = from; } public King getTo() { return to; } public void setTo(King to) { this.to = to; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/controller/KingController.java ================================================ package cn.abel.neo4j.controller; import cn.abel.neo4j.bean.King; import cn.abel.neo4j.service.KingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.List; /** * @author yyb * @time 2020/3/23 */ @Controller @RequestMapping("/king") public class KingController { @Autowired private KingService kingService; @RequestMapping(value = "/save/{id}", method = RequestMethod.GET) @ResponseBody public String save(@PathVariable long id){ List kingList = new ArrayList<>(); King king = new King(); king.setId(id); king.setName("朱元璋"); king.setClan("创业者"); king.setPosthumousTitle("高皇帝"); king.setTimes("洪武(1368年——1398年)"); king.setTempleNumber("太祖"); king.setTomb("孝陵"); king.setRemark("空印案,胡惟庸案"); kingList.add(king); kingService.saveKing(kingList); return "ok"; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/dao/KingDao.java ================================================ package cn.abel.neo4j.dao; import cn.abel.neo4j.bean.King; import org.springframework.data.neo4j.annotation.Query; import org.springframework.data.neo4j.repository.Neo4jRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * 使用Springboot - data - neo4j 生成 * * @author yyb * @time 2020/3/23 */ @Repository @Transactional(rollbackFor = Exception.class) public interface KingDao extends Neo4jRepository { /** * 通过名字查找King * * @param name * @return */ King findByName(String name); /** * 获取当前节点下的所有king * * @param name * @return */ @Query("match p=(a:King)-[r:`传位`*0..]->(b:King) where a.name={0} return p") List getKings(String name); } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jDao.java ================================================ package cn.abel.neo4j.dao; import org.neo4j.ogm.config.Configuration; import org.neo4j.ogm.config.ConfigurationSource; import org.neo4j.ogm.session.SessionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Repository; import java.util.Properties; /** * @author yyb * @time 2020/3/23 */ @Repository public class Neo4jDao { private static final Logger logger = LoggerFactory.getLogger(Neo4jDao.class); private static final String packages = "cn.abel.neo4j.bean"; private SessionFactory sessionFactory = null; @Value("${neo4j.url}") private String boltUri; @Value("${neo4j.username}") private String username; @Value("${neo4j.password}") private String password; /** * 打开一个到neo4j的连接会话。 */ public Neo4jSession open() { SessionFactory factory = getSessionFactory(); Neo4jSession session = new Neo4jSession(factory); return session; } private synchronized SessionFactory getSessionFactory() { if (sessionFactory == null) { ConfigurationSource props = () -> { Properties properties = new Properties(); properties.setProperty("URI", boltUri); properties.setProperty("username", username); properties.setProperty("password", password); return properties; }; Configuration configuration = new Configuration.Builder(props).build(); sessionFactory = new SessionFactory(configuration, packages); } return sessionFactory; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/dao/Neo4jSession.java ================================================ package cn.abel.neo4j.dao; import org.neo4j.ogm.session.Session; import org.neo4j.ogm.session.SessionFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.Iterator; import java.util.Map; /** * @author yyb * @time 2020/3/23 */ public class Neo4jSession { private static final Logger logger = LoggerFactory.getLogger(Neo4jSession.class); private Session session; private static final int DEPTH_ENTITY = 1; public Neo4jSession(SessionFactory factory) { session = factory.openSession(); } /** * 执行cypher命令。 * 增、删、改、查的 cypher 命令都可以用此方法操作 * * @param cypher * @return */ public Iterator> exec(String cypher) { long time = System.currentTimeMillis(); Iterator> it = session.query(cypher, Collections.EMPTY_MAP).iterator(); logger.info("ExecCypher {} cost:{}ms", cypher, System.currentTimeMillis() - time); return it; } /** * 存储对象 * * @param o * @return */ public void execSave(Object o) { long time = System.currentTimeMillis(); session.clear(); session.save(o); logger.info("ExecCypher {} cost:{}ms", o.toString(), System.currentTimeMillis() - time); } /** * 清空 session 缓存。 */ public void clear() { session.clear(); } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/dto/GraphDTO.java ================================================ package cn.abel.neo4j.dto; import java.util.List; /** * 用于输出图 * @author yyb * @time 2020/3/24 */ public class GraphDTO { private List nodes; private List links; public List getNodes() { return nodes; } public void setNodes(List nodes) { this.nodes = nodes; } public List getLinks() { return links; } public void setLinks(List links) { this.links = links; } } ================================================ FILE: springboot-neo4j/src/main/java/cn/abel/neo4j/service/KingService.java ================================================ package cn.abel.neo4j.service; import cn.abel.neo4j.bean.King; import cn.abel.neo4j.bean.Queen; import cn.abel.neo4j.bean.relation.FatherAndSonRelation; import cn.abel.neo4j.dao.KingDao; import cn.abel.neo4j.dao.Neo4jDao; import cn.abel.neo4j.dao.Neo4jSession; import cn.abel.neo4j.dto.GraphDTO; import org.neo4j.driver.internal.InternalNode; import org.neo4j.driver.internal.InternalPath; import org.neo4j.driver.internal.InternalRelationship; import org.neo4j.driver.v1.types.Node; import org.neo4j.driver.v1.types.Relationship; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * @author yyb * @time 2020/3/23 */ @Service public class KingService { @Autowired private Neo4jDao neo4jDao; @Autowired private KingDao kingDao; /** * 保存皇帝信息 * * @param list */ public void saveKing(List list) { Neo4jSession session = neo4jDao.open(); list.forEach(x -> { session.execSave(x); }); } /** * 保存皇后信息 * * @param list */ public void saveQueen(List list) { Neo4jSession session = neo4jDao.open(); list.forEach(x -> { session.execSave(x); }); } /** * 通过皇帝名字,查到当前的皇后和上一任皇帝 * * @param */ public GraphDTO getKingAndQueen(String kingName) { Neo4jSession session = neo4jDao.open(); String cypher = "match p=(a:King)-[r:`传位`]->(b:King)-[r2:`皇后`*1..]->(c:Queen) where a.name ='" + kingName + "' return p"; // 通过皇帝名字查询到当前皇帝皇后以及上一任皇帝皇后 // match p=(a:King)-[r:`传位`]->(b:King)-[r2:`皇后`*1..]->(c:Queen), (a:King)-[r3:`皇后`*1..]->(d:Queen) where b.name ='朱棣' return a,b,c,d Iterator> iterator = session.exec(cypher); GraphDTO gto = mapToGraph(iterator); return gto; } private GraphDTO mapToGraph( Iterator> neo4jDataIterator) { Map nodeMap = new HashMap<>(); Map linkMap = new HashMap<>(); while (neo4jDataIterator.hasNext()) { Map each = neo4jDataIterator.next(); if (!each.containsKey("p")) { continue; } InternalPath internalPath = (InternalPath) each.get("p"); //归纳出所有节点。 for (Node node : internalPath.nodes()) { InternalNode internalNode = (InternalNode) node; if (nodeMap.containsKey(internalNode.id())) { continue; } nodeMap.put(internalNode.id(), internalNode); } //归纳出所有关系。 for (Relationship relation : internalPath.relationships()) { InternalRelationship internalRelation = (InternalRelationship) relation; if (linkMap.containsKey(internalRelation.id())) { continue; } linkMap.put(internalRelation.id(), internalRelation); } } GraphDTO dto = new GraphDTO(); dto.setNodes(nodeMap.values().stream().collect(Collectors.toList())); dto.setLinks(linkMap.values().stream().collect(Collectors.toList())); return dto; } /** * 查询一个皇帝信息,此处使用spring-data-neo4j 接口 * * @param name */ public King findByName(String name) { King t = kingDao.findByName(name); return t; } /** * 获取当前节点下的所有king * * @param name * @return */ public List getKings(String name) { return kingDao.getKings(name); } /** * 保存父子关系 * * @param fatherName * @param sonName * @return */ public void saveRelation(String fatherName, String sonName) { King from = kingDao.findByName(fatherName); King to = kingDao.findByName(sonName); FatherAndSonRelation fatherAndSonRelation = new FatherAndSonRelation(); fatherAndSonRelation.setFrom(from); fatherAndSonRelation.setTo(to); from.addRelation(fatherAndSonRelation); kingDao.save(from); } } ================================================ FILE: springboot-neo4j/src/main/resources/application.properties ================================================ #application spring.application.name=springboot-neo4j application.main=cn.abel.Application server.port=9657 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 server.tomcat.max-threads=200 server.session-timeout=60 log4j.logger.java.sql.Connection=DEBUG logging.file=./logs/springboot-neo4j/springboot-neo4j.log spring.data.neo4j.url=bolt://localhost:7687 spring.data.neo4j.username=neo4j spring.data.neo4j.password=admin neo4j.url=bolt://localhost:7687 neo4j.username=neo4j neo4j.password=admin ================================================ FILE: springboot-neo4j/src/main/resources/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-neo4j/src/main/resources/logback-spring.xml ================================================ springboot-neo4j %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%method - %msg%n ================================================ FILE: springboot-neo4j/src/test/java/cn/abel/neo4j/BaseTest.java ================================================ package cn.abel.neo4j; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; /** * @author yyb * @time 2019/3/27 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) @TestPropertySource("/application.properties") public class BaseTest { @Configuration @ComponentScan(basePackages = {"cn.abel"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class)) static class ComponentScanConfig { } @Test public void contextLoads() { } } ================================================ FILE: springboot-neo4j/src/test/java/cn/abel/neo4j/service/InitData.java ================================================ package cn.abel.neo4j.service; import cn.abel.neo4j.bean.King; import cn.abel.neo4j.bean.Queen; import java.util.ArrayList; import java.util.List; /** * @author yyb * @time 2020/3/24 */ public class InitData { public static List initKing() { List kingList = new ArrayList<>(); King king1 = new King(); king1.setId(1L); king1.setName("朱元璋"); king1.setClan("朱五四之子朱棣之父"); king1.setPosthumousTitle("高皇帝"); king1.setTimes("洪武(1368年——1398年)"); king1.setTempleNumber("太祖"); king1.setTomb("孝陵"); king1.setRemark("空印案,胡惟庸案"); King king2 = new King(); king2.setId(2L); king2.setName("朱允炆"); king2.setClan("朱元璋之孙朱标次子"); king2.setPosthumousTitle("成皇帝"); king2.setTimes("建文(1399年——1402年)"); king2.setTempleNumber("惠宗"); king2.setTomb("上金贝古墓"); king2.setRemark(""); King king3 = new King(); king3.setId(3L); king3.setName("朱棣"); king3.setClan("朱元璋四子"); king3.setPosthumousTitle("文皇帝"); king3.setTimes("永乐(1403年——1424年)"); king3.setTempleNumber("成祖(原为太宗)"); king3.setTomb("长陵"); king3.setRemark(""); King king4 = new King(); king4.setId(4L); king4.setName("朱高炽"); king4.setClan("朱棣长子"); king4.setPosthumousTitle("昭皇帝"); king4.setTimes("洪熙(1424年——1425年)"); king4.setTempleNumber("仁宗"); king4.setTomb("献陵"); king4.setRemark(""); King king5 = new King(); king5.setId(5L); king5.setName("朱瞻基"); king5.setClan("朱高炽长子"); king5.setPosthumousTitle("章皇帝"); king5.setTimes("宣德(1426年——1435年)"); king5.setTempleNumber("宣宗"); king5.setTomb("景陵"); king5.setRemark(""); King king6 = new King(); king6.setId(6L); king6.setName("朱祁镇"); king6.setClan("朱瞻基长子"); king6.setPosthumousTitle("睿皇帝"); king6.setTimes("正统(1436年——1449年) 天顺(1457年——1464年)"); king6.setTempleNumber("英宗"); king6.setTomb("裕陵"); king6.setRemark(""); King king7 = new King(); king7.setId(7L); king7.setName("朱祁钰"); king7.setClan("朱瞻基次子(庶出),朱祁镇之弟(后英宗复位,代宗被废)"); king7.setPosthumousTitle("景皇帝"); king7.setTimes("景泰(1450年——1457年) "); king7.setTempleNumber("代宗"); king7.setTomb("景泰陵"); king7.setRemark(""); King king8 = new King(); king8.setId(8L); king8.setName("朱见深"); king8.setClan("乃朱祁镇长子(庶出),朱祁钰从子"); king8.setPosthumousTitle("纯皇帝"); king8.setTimes("成化(1465年——1487年)"); king8.setTempleNumber("宪宗"); king8.setTomb("茂陵"); king8.setRemark(""); King king9 = new King(); king9.setId(9L); king9.setName("朱祐樘"); king9.setClan("乃朱见深三子(庶出)"); king9.setPosthumousTitle("敬皇帝"); king9.setTimes("弘治(1488年——1505年)"); king9.setTempleNumber("孝宗"); king9.setTomb("泰陵"); king9.setRemark(""); King king10 = new King(); king10.setId(10L); king10.setName("朱厚照"); king10.setClan("乃朱祐樘长子(武宗无嗣,乃由旁支皇室选择朱厚熜入继大统)"); king10.setPosthumousTitle("高皇帝"); king10.setTimes("洪武(1368年——1398年)"); king10.setTempleNumber("武宗"); king10.setTomb("孝陵"); king10.setRemark(""); King king11 = new King(); king11.setId(11L); king11.setName("朱厚熜"); king11.setClan("乃朱见深四子兴献王朱祐杬(庶出)之嫡长子,朱祐樘从子,朱厚照从弟"); king11.setPosthumousTitle("肃皇帝"); king11.setTimes("嘉靖(1522年——1566年)"); king11.setTempleNumber("世宗"); king11.setTomb("永陵"); king11.setRemark("大仪礼"); King king12 = new King(); king12.setId(12L); king12.setName("朱载垕"); king12.setClan("乃朱厚熜三子(庶出)"); king12.setPosthumousTitle("庄皇帝"); king12.setTimes("隆庆(1567年——1572年)"); king12.setTempleNumber("穆宗"); king12.setTomb("昭陵"); king12.setRemark(""); King king13 = new King(); king13.setId(13L); king13.setName("朱翊钧"); king13.setClan("乃朱载垕三子(庶出)"); king13.setPosthumousTitle("显皇帝"); king13.setTimes("万历(1573年——1620年)"); king13.setTempleNumber("神宗"); king13.setTomb("定陵"); king13.setRemark(""); King king14 = new King(); king14.setId(14L); king14.setName("朱常洛"); king14.setClan("乃朱翊钧长子"); king14.setPosthumousTitle("贞皇帝"); king14.setTimes("泰昌(1620年)实际在位一个月"); king14.setTempleNumber("光宗"); king14.setTomb("庆陵"); king14.setRemark(""); King king15 = new King(); king15.setId(15L); king15.setName("朱由校"); king15.setClan("乃朱常洛长子(庶出)(熹宗死后无嗣,乃诏令五弟信王朱由检入继大统)"); king15.setPosthumousTitle("悊皇帝"); king15.setTimes("天启(1621年——1627年)"); king15.setTempleNumber("熹宗"); king15.setTomb("德陵"); king15.setRemark(""); King king16 = new King(); king16.setId(16L); king16.setName("朱由检"); king16.setClan("乃朱常洛五子(庶出)(毅宗死后,明朝覆灭,宗室乃于南方割据)"); king16.setPosthumousTitle("烈皇帝"); king16.setTimes("崇祯(1628年——1644年)"); king16.setTempleNumber("毅宗(原为思宗)"); king16.setTomb("思陵"); king16.setRemark(""); king1.setSuccessor(king2); king2.setSuccessor(king3); king3.setSuccessor(king4); king4.setSuccessor(king5); king5.setSuccessor(king6); king6.setSuccessor(king7); king7.setSuccessor(king8); king8.setSuccessor(king9); king9.setSuccessor(king10); king10.setSuccessor(king11); king11.setSuccessor(king12); king12.setSuccessor(king13); king13.setSuccessor(king14); king14.setSuccessor(king15); king15.setSuccessor(king16); kingList.add(king1); kingList.add(king2); kingList.add(king3); kingList.add(king4); kingList.add(king5); kingList.add(king6); kingList.add(king7); kingList.add(king8); kingList.add(king9); kingList.add(king10); kingList.add(king11); kingList.add(king12); kingList.add(king13); kingList.add(king14); kingList.add(king15); kingList.add(king16); return kingList; } public static List initQueen() { King king1 = new King(); king1.setId(1L); king1.setName("朱元璋"); king1.setClan("朱五四之子朱棣之父"); king1.setPosthumousTitle("高皇帝"); king1.setTimes("洪武(1368年——1398年)"); king1.setTempleNumber("太祖"); king1.setTomb("孝陵"); king1.setRemark("空印案,胡惟庸案"); King king2 = new King(); king2.setId(2L); king2.setName("朱允炆"); king2.setClan("朱元璋之孙朱标次子"); king2.setPosthumousTitle("成皇帝"); king2.setTimes("建文(1399年——1402年)"); king2.setTempleNumber("惠宗"); king2.setTomb("上金贝古墓"); king2.setRemark(""); King king3 = new King(); king3.setId(3L); king3.setName("朱棣"); king3.setClan("朱元璋四子"); king3.setPosthumousTitle("文皇帝"); king3.setTimes("永乐(1403年——1424年)"); king3.setTempleNumber("成祖(原为太宗)"); king3.setTomb("长陵"); king3.setRemark(""); King king4 = new King(); king4.setId(4L); king4.setName("朱高炽"); king4.setClan("朱棣长子"); king4.setPosthumousTitle("昭皇帝"); king4.setTimes("洪熙(1424年——1425年)"); king4.setTempleNumber("仁宗"); king4.setTomb("献陵"); king4.setRemark(""); King king5 = new King(); king5.setId(5L); king5.setName("朱瞻基"); king5.setClan("朱高炽长子"); king5.setPosthumousTitle("章皇帝"); king5.setTimes("宣德(1426年——1435年)"); king5.setTempleNumber("宣宗"); king5.setTomb("景陵"); king5.setRemark(""); King king6 = new King(); king6.setId(6L); king6.setName("朱祁镇"); king6.setClan("朱瞻基长子"); king6.setPosthumousTitle("睿皇帝"); king6.setTimes("正统(1436年——1449年) 天顺(1457年——1464年)"); king6.setTempleNumber("英宗"); king6.setTomb("裕陵"); king6.setRemark(""); King king7 = new King(); king7.setId(7L); king7.setName("朱祁钰"); king7.setClan("朱瞻基次子(庶出),朱祁镇之弟(后英宗复位,代宗被废)"); king7.setPosthumousTitle("景皇帝"); king7.setTimes("景泰(1450年——1457年) "); king7.setTempleNumber("代宗"); king7.setTomb("景泰陵"); king7.setRemark(""); King king8 = new King(); king8.setId(8L); king8.setName("朱见深"); king8.setClan("乃朱祁镇长子(庶出),朱祁钰从子"); king8.setPosthumousTitle("纯皇帝"); king8.setTimes("成化(1465年——1487年)"); king8.setTempleNumber("宪宗"); king8.setTomb("茂陵"); king8.setRemark(""); King king9 = new King(); king9.setId(9L); king9.setName("朱祐樘"); king9.setClan("乃朱见深三子(庶出)"); king9.setPosthumousTitle("敬皇帝"); king9.setTimes("弘治(1488年——1505年)"); king9.setTempleNumber("孝宗"); king9.setTomb("泰陵"); king9.setRemark(""); King king10 = new King(); king10.setId(10L); king10.setName("朱厚照"); king10.setClan("乃朱祐樘长子(武宗无嗣,乃由旁支皇室选择朱厚熜入继大统)"); king10.setPosthumousTitle("高皇帝"); king10.setTimes("洪武(1368年——1398年)"); king10.setTempleNumber("武宗"); king10.setTomb("孝陵"); king10.setRemark(""); King king11 = new King(); king11.setId(11L); king11.setName("朱厚熜"); king11.setClan("乃朱见深四子兴献王朱祐杬(庶出)之嫡长子,朱祐樘从子,朱厚照从弟"); king11.setPosthumousTitle("肃皇帝"); king11.setTimes("嘉靖(1522年——1566年)"); king11.setTempleNumber("世宗"); king11.setTomb("永陵"); king11.setRemark("大仪礼"); King king12 = new King(); king12.setId(12L); king12.setName("朱载垕"); king12.setClan("乃朱厚熜三子(庶出)"); king12.setPosthumousTitle("庄皇帝"); king12.setTimes("隆庆(1567年——1572年)"); king12.setTempleNumber("穆宗"); king12.setTomb("昭陵"); king12.setRemark(""); King king13 = new King(); king13.setId(13L); king13.setName("朱翊钧"); king13.setClan("乃朱载垕三子(庶出)"); king13.setPosthumousTitle("显皇帝"); king13.setTimes("万历(1573年——1620年)"); king13.setTempleNumber("神宗"); king13.setTomb("定陵"); king13.setRemark(""); King king14 = new King(); king14.setId(14L); king14.setName("朱常洛"); king14.setClan("乃朱翊钧长子"); king14.setPosthumousTitle("贞皇帝"); king14.setTimes("泰昌(1620年)实际在位一个月"); king14.setTempleNumber("光宗"); king14.setTomb("庆陵"); king14.setRemark(""); King king15 = new King(); king15.setId(15L); king15.setName("朱由校"); king15.setClan("乃朱常洛长子(庶出)(熹宗死后无嗣,乃诏令五弟信王朱由检入继大统)"); king15.setPosthumousTitle("悊皇帝"); king15.setTimes("天启(1621年——1627年)"); king15.setTempleNumber("熹宗"); king15.setTomb("德陵"); king15.setRemark(""); King king16 = new King(); king16.setId(16L); king16.setName("朱由检"); king16.setClan("乃朱常洛五子(庶出)(毅宗死后,明朝覆灭,宗室乃于南方割据)"); king16.setPosthumousTitle("烈皇帝"); king16.setTimes("崇祯(1628年——1644年)"); king16.setTempleNumber("毅宗(原为思宗)"); king16.setTomb("思陵"); king16.setRemark(""); /** * 初始化皇后信息 */ List queenList = new ArrayList<>(); Queen queen1 = new Queen(); queen1.setId(101L); queen1.setPosthumousTitle("孝慈高皇后"); queen1.setName("马秀英"); queen1.setRemark("安徽宿州人,早年丧母,被郭子兴夫妇收养为义女。1382年(洪武十五年)五十一岁的马皇后病逝。"); queen1.setTimes("1368年1月-1382年"); queen1.setSon("明兴宗朱标、秦愍王朱樉、晋恭王朱㭎、明成祖朱棣、周定王朱橚(五子皆存疑),宁国公主,安庆公主"); queen1.setKing(king1); Queen queen2 = new Queen(); queen2.setId(102L); queen2.setPosthumousTitle("孝愍让皇后"); queen2.setName("马全女"); queen2.setRemark("洪武二十八年十月,册后为皇太孙妃。建文改元,立为后。生二子,文煃、文圭。"); queen2.setTimes("1399年-1402年"); queen2.setSon("和简太子朱文奎,润怀王朱文圭"); queen2.setKing(king2); Queen queen3 = new Queen(); queen3.setId(103L); queen3.setPosthumousTitle("孝文皇后"); queen3.setName("徐氏 "); queen3.setTimes("1402年11月-1407年"); queen3.setSon("明仁宗朱高炽、汉王朱高煦、赵王朱高燧"); queen3.setRemark("洪武九年(1376年)册封为燕王妃,朱棣称帝册封为皇后。永乐五年(1407年)七月四日去世,享年46岁。"); queen3.setKing(king3); Queen queen4 = new Queen(); queen4.setId(104L); queen4.setPosthumousTitle("诚孝昭皇后"); queen4.setName("张氏"); queen4.setRemark("仁宗元配,永城人,指挥使赠彭城侯张麒诚孝昭皇后画像之女。洪武二十八年(1395年)封燕王世子妃,永乐二年(1404年)封皇太子妃。仁宗即位,册立为皇后。宣宗即位,尊为皇太后。英宗即位,尊为太皇太后。正统七年(1442年)十月十八日去世."); queen4.setTimes("1424年7月-1442年"); queen4.setSon("明宣宗朱瞻基、越靖王朱瞻墉、襄宪王朱瞻墡、嘉兴公主"); queen4.setKing(king4); Queen queen5 = new Queen(); queen5.setId(105L); queen5.setPosthumousTitle("恭让章皇后"); queen5.setName("胡善祥"); queen5.setTimes("1426年-1428年"); queen5.setSon("顺德公主"); queen5.setRemark("皇后,后被废黜,后被追谥为恭让章皇后"); queen5.setKing(king5); Queen queen51 = new Queen(); queen51.setId(106L); queen51.setPosthumousTitle("孝翼皇后"); queen51.setName("吴氏"); queen51.setSon("明代宗朱祁钰"); queen51.setRemark("太子妾,贤妃,后成皇太后,后被废,南明追谥孝翼温惠淑慎慈仁匡天锡圣太后"); queen51.setKing(king5); Queen queen52 = new Queen(); queen52.setId(107L); queen52.setPosthumousTitle("孝恭章皇后"); queen52.setName("孙氏"); queen52.setTimes("1426年-1462年"); queen52.setSon("常德公主、明英宗(存疑)"); queen52.setRemark(""); queen52.setKing(king5); Queen queen6 = new Queen(); queen6.setId(108L); queen6.setPosthumousTitle("孝庄睿皇后"); queen6.setName("钱氏"); queen6.setTimes("1442年-1468年6月"); queen6.setRemark("英宗元配,海州人,都指挥佥事(后封安昌伯)钱贵女。正统七年(1442年)立为皇后。宪宗即位,尊为皇太后,加“慈懿”徽号。成化四年(1468年)六月二十六日,钱氏病故。 "); queen6.setKing(king6); Queen queen61 = new Queen(); queen61.setId(109L); queen61.setPosthumousTitle("孝肃后"); queen61.setName("周氏"); queen61.setTimes("1464年-1504"); queen61.setSon("重庆公主、明宪宗朱见深、崇简王朱见泽"); queen61.setRemark("宪宗生母,昌平州文宁里柳林村(今属北京市海淀区)人,锦衣卫千户追封庆云侯赠宁国公周能的女儿。正统十二年(1447年)生宪宗皇帝,天顺元年(1457年)册封为贵妃。宪宗即位,尊为皇太后。孝宗即位后,尊为太皇太后。弘治十七年(1504年)三月一日去世."); queen61.setKing(king6); Queen queen7 = new Queen(); queen7.setId(110L); queen7.setPosthumousTitle("孝渊皇后"); queen7.setName("汪氏"); queen7.setTimes("1449年-1452年"); queen7.setSon("固安公主、二公主(出家)"); queen7.setRemark("北京人,祖父汪泉世为金吾左卫指挥使。正统十年(1445),郕王朱祁钰18岁,册封汪氏为郕王妃。正统十四年(1449) 册封王妃汪氏为皇后。进汪皇后祖父汪泉为都指挥同知;,汪氏去世与景帝合葬金山。"); queen7.setKing(king7); Queen queen71 = new Queen(); queen71.setId(111L); queen71.setPosthumousTitle("肃孝皇后"); queen71.setName("杭氏"); queen71.setSon("怀献太子朱见济"); queen71.setTimes("1452年-1453年"); queen71.setRemark("妾,后为贵妃,后成皇后,后被明英宗追废"); queen71.setKing(king7); Queen queen8 = new Queen(); queen8.setId(112L); queen8.setPosthumousTitle("皇后"); queen8.setName("吴氏"); queen8.setTimes("1464年7月27日-1464年8月28日"); queen8.setSon("曾抚养明孝宗朱祐樘"); queen8.setRemark("皇后,后被废黜,在位仅31日。为明朝在位时期最短的皇后。"); queen8.setKing(king8); Queen queen81 = new Queen(); queen81.setId(113L); queen81.setPosthumousTitle("孝贞纯皇后"); queen81.setName("王氏"); queen81.setTimes("1464年10月12日-1518年2月"); queen81.setRemark("皇后,后成皇太后"); queen81.setKing(king8); Queen queen82 = new Queen(); queen82.setId(114L); queen82.setPosthumousTitle("孝穆皇后"); queen82.setName("纪氏"); queen82.setSon("明孝宗朱祐樘"); queen82.setRemark("宫人,后成淑妃,后被追谥孝穆皇后, 瑶族人。暴死"); queen82.setKing(king8); Queen queen83 = new Queen(); queen83.setId(115L); queen83.setPosthumousTitle("孝惠皇后"); queen83.setName("邵氏"); queen83.setSon("宸妃,后成贵妃,嘉靖帝尊为寿安皇太后,后被追谥孝惠皇后"); queen83.setRemark("宫人,后成淑妃,后被追谥孝穆皇后, 瑶族人。暴死"); queen83.setKing(king8); Queen queen9 = new Queen(); queen9.setId(116L); queen9.setPosthumousTitle("孝成敬皇后"); queen9.setName("张氏"); queen9.setTimes("1486年-1541年"); queen9.setSon("明武宗朱厚照、朱厚炜、太康公主朱秀荣"); queen9.setRemark("皇后,后成皇伯母皇太后,追谥孝康敬皇后,后改谥孝成敬皇后,丈夫孝宗在世期间未曾册封嫔妃,是中国历史上唯一终生一夫一妻的皇帝"); queen9.setKing(king9); Queen queen10 = new Queen(); queen10.setId(117L); queen10.setPosthumousTitle("孝静皇后"); queen10.setName("夏氏"); queen10.setTimes("1506年-1535年1月"); queen10.setRemark("皇后,嘉靖帝尊封为皇嫂庄肃皇后"); queen10.setKing(king10); Queen queen11 = new Queen(); queen11.setId(118L); queen11.setPosthumousTitle("孝洁肃皇后"); queen11.setName("陈氏"); queen11.setTimes("1522年-1528年10月"); queen11.setRemark("皇后,谥悼灵皇后,后改谥孝洁恭懿慈睿安庄相天翊圣肃皇后, 受惊流产而亡"); queen11.setKing(king11); Queen queen12 = new Queen(); queen12.setId(119L); queen12.setPosthumousTitle("孝懿庄皇后"); queen12.setName("李氏"); queen12.setTimes("?-1558年4月"); queen12.setSon("宪怀太子朱翊、蓬莱公主"); queen12.setRemark("结髪之妻,正室,后被追谥为孝懿贞惠顺哲恭仁俪天襄圣庄皇后"); queen12.setKing(king12); Queen queen121 = new Queen(); queen121.setId(120L); queen121.setPosthumousTitle("孝安皇后"); queen121.setName("陈氏"); queen121.setTimes("1567年3月-1596年7月"); queen121.setSon("太和公主"); queen121.setRemark("继室,后为皇后,后成皇太后,后被追谥为孝安贞懿恭纯温惠佐天弘圣皇后"); queen121.setKing(king12); Queen queen13 = new Queen(); queen13.setId(121L); queen13.setPosthumousTitle("孝端皇后"); queen13.setName("王喜姐"); queen13.setTimes("1578年-1620年"); queen13.setRemark("荣昌公主朱轩媖"); queen13.setKing(king13); Queen queen14 = new Queen(); queen14.setId(122L); queen14.setPosthumousTitle("孝元贞皇后"); queen14.setName("郭氏"); queen14.setSon("怀淑公主朱徽娟"); queen14.setRemark("结髪之妻,正室太子妃,后被追谥为孝元昭懿哲惠庄仁合天弼圣贞皇后"); queen14.setKing(king14); Queen queen15 = new Queen(); queen15.setId(123L); queen15.setPosthumousTitle("孝哀悊皇后"); queen15.setName("张氏"); queen15.setTimes("1621年4月-1644年2月28日"); queen15.setSon("太子朱慈燃"); queen15.setRemark("皇后,崇祯帝尊封为皇嫂懿安皇后,南明追谥孝哀慈靖恭惠温贞偕天协圣悊皇后,明亡时自缢身亡。"); queen15.setKing(king15); Queen queen16 = new Queen(); queen16.setId(124L); queen16.setPosthumousTitle("孝节烈皇后"); queen16.setName("周氏"); queen16.setTimes("1628年-1644年2月28日"); queen16.setSon("坤仪公主、明悼帝朱慈烺、怀隐王朱慈烜、定哀王朱慈炯"); queen16.setRemark("结髪之妻,正室,后成皇后,清追谥为庄烈愍皇后,南明追谥孝节贞肃渊恭庄毅奉天靖圣烈皇后,自杀"); queen16.setKing(king16); queenList.add(queen1); queenList.add(queen2); queenList.add(queen3); queenList.add(queen4); queenList.add(queen5); queenList.add(queen5); queenList.add(queen51); queenList.add(queen52); queenList.add(queen6); queenList.add(queen61); queenList.add(queen7); queenList.add(queen71); queenList.add(queen8); queenList.add(queen81); queenList.add(queen82); queenList.add(queen83); queenList.add(queen9); queenList.add(queen10); queenList.add(queen11); queenList.add(queen12); queenList.add(queen121); queenList.add(queen13); queenList.add(queen14); queenList.add(queen15); queenList.add(queen16); return queenList; } } ================================================ FILE: springboot-neo4j/src/test/java/cn/abel/neo4j/service/KingServiceTest.java ================================================ package cn.abel.neo4j.service; import cn.abel.neo4j.BaseTest; import cn.abel.neo4j.bean.King; import cn.abel.neo4j.bean.Queen; import cn.abel.neo4j.dao.KingDao; import cn.abel.neo4j.dto.GraphDTO; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * @author yyb * @time 2020/3/23 */ public class KingServiceTest extends BaseTest { @Autowired private KingService kingService; @Autowired private KingDao kingDao; @Test public void saveKing() throws Exception { List kingList = InitData.initKing(); kingService.saveKing(kingList); } @Test public void saveQueen() throws Exception { List queenList = InitData.initQueen(); kingService.saveQueen(queenList); } @Test public void saveRelation() throws Exception { kingService.saveRelation("朱元璋", "朱棣"); } @Test public void getOneKing() throws Exception { King king = kingService.findByName("朱棣"); System.out.println(); } @Test public void getKingAndQueen() throws Exception { GraphDTO graphDTO = kingService.getKingAndQueen("朱棣"); System.out.println(); } } ================================================ FILE: springboot-redis-queue/pom.xml ================================================ 4.0.0 cn.abel springboot-redis-queue 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2 org.springframework.boot spring-boot-autoconfigure redis.clients jedis 3.0.1 org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-surefire-plugin 2.18.1 true ================================================ FILE: springboot-redis-queue/src/main/java/cn/abel/queue/Application.java ================================================ package cn.abel.queue; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/8/13 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-redis-queue/src/main/java/cn/abel/queue/config/RedisConfig.java ================================================ package cn.abel.queue.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; /** * @author yyb * @time 2019/8/13 */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { /** * logger */ private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); @Value("${spring.redis.database}") private Integer database; @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private Integer port; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.lettuce.pool.max-active}") private Integer maxActive; @Value("${spring.redis.lettuce.pool.max-wait}") private Integer maxWait; @Value("${spring.redis.lettuce.pool.max-idle}") private Integer maxIdle; @Value("${spring.redis.lettuce.pool.min-idle}") private Integer minIdle; @Value("${spring.redis.lettuce.shutdown-timeout}") private Integer timeout; /** * 在使用@Cacheable时,如果不指定key,则使用这个默认的key生成器生成的key * * @return */ @Override @Bean public KeyGenerator keyGenerator() { return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); }; } @Bean(name = "redisTemplate") public RedisTemplate redisTemplate() { return getTemplate(redisConnectionFactory()); } private RedisConnectionFactory redisConnectionFactory() { return connectionFactory(maxActive, maxIdle, minIdle, maxWait, host, password, timeout, port, database); } /** * 创建连接 * * @param maxActive * @param maxIdle * @param minIdle * @param maxWait * @param host * @param password * @param timeout * @param port * @param database * @return */ private RedisConnectionFactory connectionFactory(Integer maxActive, Integer maxIdle, Integer minIdle, Integer maxWait, String host, String password, Integer timeout, Integer port, Integer database) { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPort(port); redisStandaloneConfiguration.setDatabase(database); redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxTotal(maxActive); poolConfig.setMinIdle(minIdle); poolConfig.setMaxIdle(maxIdle); poolConfig.setMaxWaitMillis(maxWait); LettuceClientConfiguration lettucePoolingConfig = LettucePoolingClientConfiguration.builder() .poolConfig(poolConfig).shutdownTimeout(Duration.ofMillis(timeout)).build(); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettucePoolingConfig); connectionFactory.afterPropertiesSet(); return connectionFactory; } /** * 创建 RedisTemplate 连接类型,此处为hash * * @param factory * @return */ private RedisTemplate getTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setValueSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); template.afterPropertiesSet(); return template; } /** * 对value 进行序列化 * * @param objectMapper * @return */ private Jackson2JsonRedisSerializer jackson2JsonRedisSerializer(ObjectMapper objectMapper) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); return jackson2JsonRedisSerializer; } } ================================================ FILE: springboot-redis-queue/src/main/java/cn/abel/queue/controller/PublisherController.java ================================================ package cn.abel.queue.controller; import cn.abel.queue.service.ProducerService; import cn.abel.queue.service.ReceiverService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; /** * @author yyb * @time 2019/8/13 */ @RestController @RequestMapping("/publisher") public class PublisherController { @Autowired private ProducerService producerService; @Autowired private ReceiverService receiverService; @RequestMapping(value = "{name}",method = RequestMethod.GET) public String sendMessage(@PathVariable("name") String name) { return producerService.sendMessage(name); } @RequestMapping(value = "/get",method =RequestMethod.GET ) public String getMessage() { return receiverService.getMessage(); } } ================================================ FILE: springboot-redis-queue/src/main/java/cn/abel/queue/service/ProducerService.java ================================================ package cn.abel.queue.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; /** * @author yyb * @time 2019/8/13 */ @Service public class ProducerService { @Autowired private StringRedisTemplate redisTemplate; public String sendMessage(String name) { try { redisTemplate.opsForList().leftPush("quere", name); return "消息发送成功了"; } catch (Exception e) { e.printStackTrace(); return "消息发送失败了"; } } } ================================================ FILE: springboot-redis-queue/src/main/java/cn/abel/queue/service/ReceiverService.java ================================================ package cn.abel.queue.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; /** * @author yyb * @time 2019/8/13 */ @Service public class ReceiverService { @Autowired private StringRedisTemplate redisTemplate; public String getMessage() { String value = redisTemplate.opsForList().rightPop("quere"); return value; } } ================================================ FILE: springboot-redis-queue/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=9666 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=redis-queue application.main=cn.abel.queue.Application ## LOG logging.file=./logs/redis-queue.log ## spring cache #\u7F13\u5B58\u7684\u540D\u79F0\u96C6\u5408\uFF0C\u591A\u4E2A\u91C7\u7528\u9017\u53F7\u5206\u5272 #spring.cache.cache-names=admin,role #\u7F13\u5B58\u7684\u7C7B\u578B\uFF0C\u5B98\u65B9\u63D0\u4F9B\u4E86\u5F88\u591A\uFF0C\u8FD9\u91CC\u6211\u4EEC\u586B\u5199redis spring.cache.type=redis #\u662F\u5426\u7F13\u5B58null\u6570\u636E\uFF0C\u9ED8\u8BA4\u662Ffalse #spring.cache.redis.cache-null-values=false #redis\u4E2D\u7F13\u5B58\u8D85\u65F6\u7684\u65F6\u95F4\uFF0C\u9ED8\u8BA460000ms #spring.cache.redis.time-to-live=60000 #\u7F13\u5B58\u6570\u636Ekey\u662F\u5426\u4F7F\u7528\u524D\u7F00\uFF0C\u9ED8\u8BA4\u662Ftrue #spring.cache.redis.use-key-prefix=true #\u7F13\u5B58\u6570\u636Ekey\u7684\u524D\u7F00\uFF0C\u5728\u4E0A\u9762\u7684\u914D\u7F6E\u4E3Atrue\u65F6\u6709\u6548\uFF0C # Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u5E93\uFF09 spring.redis.database=2 # Redis\u670D\u52A1\u5668\u5730\u5740 spring.redis.host=127.0.0.1 # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u7AEF\u53E3 spring.redis.port=6379 # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09 spring.redis.password= # \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 spring.redis.lettuce.pool.max-active=100 # \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09 spring.redis.lettuce.pool.max-wait=1000 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5 spring.redis.lettuce.pool.max-idle=50 # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5 spring.redis.lettuce.pool.min-idle=0 # \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09 spring.redis.lettuce.shutdown-timeout=0 ================================================ FILE: springboot-redis-queue/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-redis-queue/src/main/resources/local/logback-spring.xml ================================================ demo %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: springboot-rocketmq/pom.xml ================================================ 4.0.0 cn.abel springboot-rocketmq 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.apache.commons commons-pool2 org.springframework.boot spring-boot-autoconfigure org.apache.rocketmq rocketmq-client 4.3.0 org.codehaus.groovy groovy org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-surefire-plugin 2.18.1 true ================================================ FILE: springboot-rocketmq/src/main/java/cn/abel/queue/Application.java ================================================ package cn.abel.queue; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/8/13 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-rocketmq/src/main/java/cn/abel/queue/config/JmsConfig.java ================================================ package cn.abel.queue.config; /** * @author yyb * @time 2019/11/26 */ public class JmsConfig { /** * Name Server 地址,因为是集群部署 所以有多个用 分号 隔开 */ public static final String NAME_SERVER = "10.33.20.223:9876"; /** * 主题名称 主题一般是服务器设置好 而不能在代码里去新建topic( 如果没有创建好,生产者往该主题发送消息 会报找不到topic错误) */ public static final String TOPIC = "stock_change"; } ================================================ FILE: springboot-rocketmq/src/main/java/cn/abel/queue/controller/PublisherController.java ================================================ package cn.abel.queue.controller; import cn.abel.queue.config.JmsConfig; import cn.abel.queue.service.ProducerService; import cn.abel.queue.service.ReceiverService; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.common.message.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; /** * @author yyb * @time 2019/8/13 */ @RestController @RequestMapping("/publisher") public class PublisherController { @Autowired private ProducerService producerService; @Autowired private ReceiverService receiverService; private List mesList; /** * 初始化消息 */ public PublisherController() { mesList = new ArrayList<>(); mesList.add("小小"); mesList.add("爸爸"); mesList.add("妈妈"); mesList.add("爷爷"); mesList.add("奶奶"); } @RequestMapping("/text/rocketmq") public Object callback() throws Exception { //总共发送五次消息 for (String s : mesList) { //创建生产信息 Message message = new Message(JmsConfig.TOPIC, "testtag", ("小小一家人的称谓:" + s).getBytes()); //发送 SendResult sendResult = producerService.getProducer().send(message); System.out.println(String.format("输出生产者信息={ %s }",sendResult)); } return "成功"; } } ================================================ FILE: springboot-rocketmq/src/main/java/cn/abel/queue/service/ProducerService.java ================================================ package cn.abel.queue.service; import cn.abel.queue.config.JmsConfig; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; /** * @author yyb * @time 2019/8/13 */ @Service @Component public class ProducerService { private String producerGroup = "test_producer"; private DefaultMQProducer producer; public ProducerService(){ //示例生产者 producer = new DefaultMQProducer(producerGroup); //不开启vip通道 开通口端口会减2 producer.setVipChannelEnabled(false); //绑定name server producer.setNamesrvAddr(JmsConfig.NAME_SERVER); start(); } /** * 对象在使用之前必须要调用一次,只能初始化一次 */ public void start(){ try { this.producer.start(); } catch (MQClientException e) { e.printStackTrace(); } } public DefaultMQProducer getProducer(){ return this.producer; } /** * 一般在应用上下文,使用上下文监听器,进行关闭 */ public void shutdown(){ this.producer.shutdown(); } } ================================================ FILE: springboot-rocketmq/src/main/java/cn/abel/queue/service/ReceiverService.java ================================================ package cn.abel.queue.service; import cn.abel.queue.config.JmsConfig; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.consumer.ConsumeFromWhere; import org.apache.rocketmq.common.message.Message; import org.springframework.stereotype.Service; import java.io.UnsupportedEncodingException; /** * @author yyb * @time 2019/8/13 */ @Service public class ReceiverService { /** * 消费者实体对象 */ private DefaultMQPushConsumer consumer; /** * 消费者组 */ public static final String CONSUMER_GROUP = "test_consumer"; /** * 通过构造函数 实例化对象 */ public ReceiverService() throws MQClientException { consumer = new DefaultMQPushConsumer(CONSUMER_GROUP); consumer.setNamesrvAddr(JmsConfig.NAME_SERVER); //消费模式:一个新的订阅组第一次启动从队列的最后位置开始消费 后续再启动接着上次消费的进度开始消费 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); //订阅主题和 标签( * 代表所有标签)下信息 consumer.subscribe(JmsConfig.TOPIC, "*"); // //注册消费的监听 并在此监听中消费信息,并返回消费的状态信息 consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> { // msgs中只收集同一个topic,同一个tag,并且key相同的message // 会把不同的消息分别放置到不同的队列中 try { for (Message msg : msgs) { //消费者获取消息 这里只输出 不做后面逻辑处理 String body = new String(msg.getBody(), "utf-8"); System.out.println(String.format("Consumer-获取消息-主题topic为={ %s }, 消费消息为={ %s }", msg.getTopic(), body)); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); return ConsumeConcurrentlyStatus.RECONSUME_LATER; } return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }); consumer.start(); System.out.println("消费者 启动成功======="); } } ================================================ FILE: springboot-rocketmq/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=9666 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=rocketmq-queue application.main=cn.abel.queue.Application ## LOG logging.file=./logs/rocketmq-queue.log ================================================ FILE: springboot-rocketmq/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-rocketmq/src/main/resources/local/logback-spring.xml ================================================ demo %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: springboot-rocketmq-ali/pom.xml ================================================ 4.0.0 cn.abel springboot-rocketmq-ali 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 2.0.4.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.apache.commons commons-pool2 org.springframework.boot spring-boot-autoconfigure com.aliyun.openservices ons-client 1.8.3.Final com.alibaba fastjson 1.2.58 org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin org.apache.maven.plugins maven-surefire-plugin 2.18.1 true ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/Application.java ================================================ package cn.abel.queue; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author yyb * @time 2019/8/13 */ @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiConsumerClient.java ================================================ package cn.abel.queue.config; import cn.abel.queue.service.MessageHandler; import com.aliyun.openservices.ons.api.MessageListener; import com.aliyun.openservices.ons.api.PropertyKeyConst; import com.aliyun.openservices.ons.api.bean.ConsumerBean; import com.aliyun.openservices.ons.api.bean.Subscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * @author yyb * @time 2020/3/25 */ @Configuration public class ALiConsumerClient { private static final Logger logger = LoggerFactory.getLogger(ALiConsumerClient.class); /** * topic tag。 */ private static final String TOPIC_TAG = "*"; /** * 消费者线程数。 */ private static final int CONSUMER_THREAD_COUNT = 10; /** * 重新消费次数。 */ private static final int RECONSUME_TIMES = 2; private MessageHandler handler; @Value("${ali.rocket.mq.access-key}") private String accessKey; @Value("${ali.rocket.mq.secret-key}") private String secretKey; @Value("${ali.rocket.mq.name-srv-addr}") private String nameSrvAddr; @Value("${ali.rocket.mq.test-topic}") private String topic; @Value("${ali.rocket.mq.test-group-id}") private String group; @Bean(initMethod = "start", destroyMethod = "shutdown") public ConsumerBean buildConsumer() { ConsumerBean consumerBean = new ConsumerBean(); Properties properties = new Properties(); properties.setProperty(PropertyKeyConst.AccessKey, accessKey); properties.setProperty(PropertyKeyConst.SecretKey, secretKey); properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, nameSrvAddr); properties.setProperty(PropertyKeyConst.GROUP_ID, group); properties.setProperty(PropertyKeyConst.ConsumeThreadNums, String.valueOf(CONSUMER_THREAD_COUNT)); properties.setProperty(PropertyKeyConst.MaxReconsumeTimes, String.valueOf(RECONSUME_TIMES)); consumerBean.setProperties(properties); Map subscriptionTable = new HashMap<>(); Subscription subscription = new Subscription(); subscription.setTopic(topic); subscription.setExpression(TOPIC_TAG); subscriptionTable.put(subscription, handler); consumerBean.setSubscriptionTable(subscriptionTable); logger.info("初始化rocketMq完成 config:{}"); return consumerBean; } @Autowired public ALiConsumerClient(MessageHandler handler) { this.handler = handler; } } ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiMqConfig.java ================================================ package cn.abel.queue.config; import com.aliyun.openservices.ons.api.PropertyKeyConst; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Properties; /** * @author yyb * @time 2020/3/25 */ @Component @ConfigurationProperties(prefix = "ali.rocket.mq") public class ALiMqConfig { private String accessKey; private String secretKey; private String nameSrvAddr; private String testTopic; private String testGroupId; private String testTag; public Properties getMqProperties() { Properties properties = new Properties(); properties.setProperty(PropertyKeyConst.AccessKey, this.accessKey); properties.setProperty(PropertyKeyConst.SecretKey, this.secretKey); properties.setProperty(PropertyKeyConst.GROUP_ID, testGroupId); properties.setProperty(PropertyKeyConst.NAMESRV_ADDR, this.nameSrvAddr); return properties; } public String getAccessKey() { return accessKey; } public void setAccessKey(String accessKey) { this.accessKey = accessKey; } public String getSecretKey() { return secretKey; } public void setSecretKey(String secretKey) { this.secretKey = secretKey; } public String getNameSrvAddr() { return nameSrvAddr; } public void setNameSrvAddr(String nameSrvAddr) { this.nameSrvAddr = nameSrvAddr; } public String getTestTopic() { return testTopic; } public void setTestTopic(String testTopic) { this.testTopic = testTopic; } public String getTestGroupId() { return testGroupId; } public void setTestGroupId(String testGroupId) { this.testGroupId = testGroupId; } public String getTestTag() { return testTag; } public void setTestTag(String testTag) { this.testTag = testTag; } } ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/config/ALiProducerClient.java ================================================ package cn.abel.queue.config; import com.aliyun.openservices.ons.api.bean.ProducerBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; /** * @author yyb * @time 2020/3/25 */ @Component public class ALiProducerClient { @Autowired private ALiMqConfig aLiMqConfig; @Bean(name = "producer", initMethod = "start", destroyMethod = "shutdown") public ProducerBean build() { ProducerBean bean = new ProducerBean(); bean.setProperties(aLiMqConfig.getMqProperties()); return bean; } @Autowired public ALiProducerClient(ALiMqConfig aLiMqConfig) { this.aLiMqConfig = aLiMqConfig; } } ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/MessageHandler.java ================================================ package cn.abel.queue.service; import com.aliyun.openservices.ons.api.Action; import com.aliyun.openservices.ons.api.ConsumeContext; import com.aliyun.openservices.ons.api.Message; import com.aliyun.openservices.ons.api.MessageListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets; /** * @author yyb * @time 2020/3/25 */ @Component public class MessageHandler implements MessageListener { private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class); @Override public Action consume(Message message, ConsumeContext consumeContext) { String msgStr = new String(message.getBody(), StandardCharsets.UTF_8); //接收到消息 logger.info("Receive message msgId:{} retryTimes:{} body:{}", message.getMsgID(), message.getReconsumeTimes(), msgStr); //提交 return Action.CommitMessage; } } ================================================ FILE: springboot-rocketmq-ali/src/main/java/cn/abel/queue/service/ProducerService.java ================================================ package cn.abel.queue.service; import cn.abel.queue.config.ALiMqConfig; import com.alibaba.fastjson.JSON; import com.aliyun.openservices.ons.api.Message; import com.aliyun.openservices.ons.api.OnExceptionContext; import com.aliyun.openservices.ons.api.SendCallback; import com.aliyun.openservices.ons.api.SendResult; import com.aliyun.openservices.ons.api.bean.ProducerBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; import java.util.function.Predicate; /** * @author yyb * @time 2019/8/13 */ @Service public class ProducerService { private static final Logger logger = LoggerFactory.getLogger(ProducerService.class); @Autowired private ALiMqConfig aLiMqConfig; @Autowired private ProducerBean producer; /** * 调用此方法 发送消息,o 为自定义的消息体 */ public void sendMessage(Object o) { Message message = new Message(aLiMqConfig.getStockTopic(), "test", JSON.toJSON(o).toString().getBytes(StandardCharsets.UTF_8)); //向mq发送消息 sendAsync(ProducerBean::isStarted, producer, message); } /** * 向阿里云rocket mq发送消息。 * * @param predicate 断言 * @param bean 发送消息bean * @param message 需要发送的消息 */ private static void sendAsync(Predicate predicate, ProducerBean bean, Message message) { if (predicate.test(bean)) { bean.sendAsync(message, new SendCallback() { @Override public void onSuccess(SendResult sendResult) { logger.info("向mq推送库存消息成功,消息是:{}", sendResult.toString()); } @Override public void onException(OnExceptionContext e) { logger.error("向mq推送库存消息失败,消息id 为 {} 错误是:{}", e.getMessageId(), e.getException().getMessage()); } }); } else { logger.error("mq库存生产端启动失败!!!消息是:{}", message.toString()); } } } ================================================ FILE: springboot-rocketmq-ali/src/main/resources/local/application.properties ================================================ ## tomcat\u914D\u7F6E server.port=9666 #server.tomcat.maxHttpHeaderSize=8192 server.tomcat.uri-encoding=UTF-8 spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true spring.http.encoding.force=true spring.messages.encoding=UTF-8 # tomcat\u6700\u5927\u7EBF\u7A0B\u6570\uFF0C\u9ED8\u8BA4\u4E3A200 server.tomcat.max-threads=800 # session\u6700\u5927\u8D85\u65F6\u65F6\u95F4(\u5206\u949F)\uFF0C\u9ED8\u8BA4\u4E3A30 server.session-timeout=60 ## spring \u914D\u7F6E spring.application.name=rocketmq-ali-queue application.main=cn.abel.queue.Application ## LOG logging.file=./logs/rocketmq-queue-ali.log # rocket mq ali.rocket.mq.access-key=xxxxx ali.rocket.mq.secret-key=xxxxxx ali.rocket.mq.name-srv-addr=127.0.0.1:9876 ali.rocket.mq.test-topic=mq_test ali.rocket.mq.test-group-id=test ali.rocket.mq.test-tag= ================================================ FILE: springboot-rocketmq-ali/src/main/resources/local/banner.txt ================================================ ######################################################## # # # local # # # ######################################################## ================================================ FILE: springboot-rocketmq-ali/src/main/resources/local/logback-spring.xml ================================================ springboot-rocketmq-ali %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ${LOG_FILE} ${LOG_FILE}.%d{yyyy-MM-dd} 60 %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n ================================================ FILE: springboot-shiro/pom.xml ================================================ 4.0.0 com.abel-shiro springboot-shiro 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.unistacks.epp.manager.Application 1.8 1.8 3.2.7 1.2.2 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-logging org.springframework.boot spring-boot-starter-thymeleaf commons-logging commons-logging 1.2 org.apache.shiro shiro-spring 1.2.5 org.apache.shiro shiro-ehcache 1.2.5 com.github.theborakompanioni thymeleaf-extras-shiro 1.2.1 org.apache.kafka kafka_2.11 0.10.1.0 org.slf4j slf4j-log4j12 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} ================================================ FILE: springboot-shiro/src/main/java/com/us/Application.java ================================================ package com.us; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/bean/Event.java ================================================ package com.us.bean; import java.util.Date; public class Event { private Integer id; private Integer rawEventId; private String host; private String ip; private String source; private String type; private Date startTime; private Date endTime; private String content; private String dataType; private String suggest; private Integer businessSystemId; private Integer departmentId; private String status; private Integer occurCount; private String owner; private Date responsedTime; private String responsedBy; private Date resolvedTime; private String resolvedBy; private Date closedTime; private String closedBy; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getRawEventId() { return rawEventId; } public void setRawEventId(Integer rawEventId) { this.rawEventId = rawEventId; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getSource() { return source; } public void setSource(String source) { this.source = source; } public String getType() { return type; } public void setType(String type) { this.type = type; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public String getSuggest() { return suggest; } public void setSuggest(String suggest) { this.suggest = suggest; } public Integer getBusinessSystemId() { return businessSystemId; } public void setBusinessSystemId(Integer businessSystemId) { this.businessSystemId = businessSystemId; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public Integer getOccurCount() { return occurCount; } public void setOccurCount(Integer occurCount) { this.occurCount = occurCount; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public Date getResponsedTime() { return responsedTime; } public void setResponsedTime(Date responsedTime) { this.responsedTime = responsedTime; } public String getResponsedBy() { return responsedBy; } public void setResponsedBy(String responsedBy) { this.responsedBy = responsedBy; } public Date getResolvedTime() { return resolvedTime; } public void setResolvedTime(Date resolvedTime) { this.resolvedTime = resolvedTime; } public String getResolvedBy() { return resolvedBy; } public void setResolvedBy(String resolvedBy) { this.resolvedBy = resolvedBy; } public Date getClosedTime() { return closedTime; } public void setClosedTime(Date closedTime) { this.closedTime = closedTime; } public String getClosedBy() { return closedBy; } public void setClosedBy(String closedBy) { this.closedBy = closedBy; } @Override public String toString() { return "Event{" + "id=" + id + ", rawEventId=" + rawEventId + ", host=" + host + ", ip=" + ip + ", source=" + source + ", type=" + type + ", startTime=" + startTime + ", endTime=" + endTime + ", content=" + content + ", dataType=" + dataType + ", suggest=" + suggest + ", businessSystemId=" + businessSystemId + ", departmentId=" + departmentId + ", status=" + status + ", occurCount=" + occurCount + ", owner=" + owner + ", responsedTime=" + responsedTime + ", responsedBy=" + responsedBy + ", resolvedTime=" + resolvedTime + ", resolvedBy=" + resolvedBy + ", closedTime=" + closedTime + ", closedBy=" + closedBy + '}'; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/bean/Permission.java ================================================ package com.us.bean; public class Permission { private Integer id; private String name; private String permissionUrl; private String method; private String description; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPermissionUrl() { return permissionUrl; } public void setPermissionUrl(String permissionUrl) { this.permissionUrl = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Permission{" + "id=" + id + ", name=" + name + ", permissionUrl=" + permissionUrl + ", method=" + method + ", description=" + description + '}'; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/bean/Role.java ================================================ package com.us.bean; public class Role { private Integer id; private String name; private Integer roleLevel; private String description; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getRoleLevel() { return roleLevel; } public void setRoleLevel(Integer roleLevel) { this.roleLevel = roleLevel; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Role{" + "id=" + id + ", name=" + name + ", roleLevel=" + roleLevel + ", description=" + description + '}'; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/bean/User.java ================================================ package com.us.bean; import com.fasterxml.jackson.annotation.JsonIgnore; import java.util.List; public class User { private Integer id; private String cnname; private String username; @JsonIgnore private String password; private String email; private String telephone; private String mobilePhone; private String wechatId; private String skill; private Integer departmentId; private Integer loginCount; private List roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCnname() { return cnname; } public void setCnname(String cnname) { this.cnname = cnname; } public String getUsername() { return username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getMobilePhone() { return mobilePhone; } public void setMobilePhone(String mobilePhone) { this.mobilePhone = mobilePhone; } public String getWechatId() { return wechatId; } public void setWechatId(String wechatId) { this.wechatId = wechatId; } public String getSkill() { return skill; } public void setSkill(String skill) { this.skill = skill; } public Integer getDepartmentId() { return departmentId; } public void setDepartmentId(Integer departmentId) { this.departmentId = departmentId; } public Integer getLoginCount() { return loginCount; } public void setLoginCount(Integer loginCount) { this.loginCount = loginCount; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } @Override public String toString() { return "User{" + "id=" + id + ", cnname=" + cnname + ", username=" + username + ", password=" + password + ", email=" + email + ", telephone=" + telephone + ", mobilePhone=" + mobilePhone + ", wechatId=" + wechatId + ", skill=" + skill + ", departmentId=" + departmentId + ", loginCount=" + loginCount + '}'; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/config/DataSourceConfig.java ================================================ package com.us.config; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import java.beans.PropertyVetoException; @Configuration public class DataSourceConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("jdbc.driverClassName")); dataSource.setJdbcUrl(env.getProperty("jdbc.url")); dataSource.setUser(env.getProperty("jdbc.username")); dataSource.setPassword(env.getProperty("jdbc.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/config/MapperScannerConfig.java ================================================ package com.us.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MapperScannerConfig { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("**.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/config/MyBatisConfig.java ================================================ package com.us.config; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.util.Properties; @Configuration public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory( ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); configuration.setJdbcTypeForNull(JdbcType.NULL); sessionFactory.setMapperLocations(applicationContext.getResources("classpath:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/config/TransactionConfig.java ================================================ package com.us.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Override @Bean public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/controller/EventController.java ================================================ package com.us.controller; import com.us.bean.Event; import com.us.service.EventService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.List; @RequestMapping(value = "/events") @RestController public class EventController { @Autowired private EventService eventService; @RequestMapping(method = RequestMethod.GET) public List list(HttpServletRequest request) { return eventService.getByMap(null); } @RequestMapping(value = "/{id}", method = RequestMethod.GET) public Event detail(@PathVariable Integer id) { return eventService.getById(id); } @RequestMapping(method = RequestMethod.POST) public Event create(@RequestBody Event event) { return eventService.create(event); } @RequestMapping(method = RequestMethod.PUT) public Event update(@RequestBody Event event) { return eventService.update(event); } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public int delete(@PathVariable Integer id) { return eventService.delete(id); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/controller/LoginController.java ================================================ package com.us.controller; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; /** * Created by cdyoue on 2016/10/21. * 登陆控制器 */ @RestController public class LoginController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @RequestMapping(value = "/login", method = RequestMethod.POST) public String login( @RequestParam(value = "username", required = true) String userName, @RequestParam(value = "password", required = true) String password, @RequestParam(value = "rememberMe", required = true, defaultValue = "false") boolean rememberMe ) { logger.info("==========" + userName + password + rememberMe); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, password); token.setRememberMe(rememberMe); try { subject.login(token); } catch (AuthenticationException e) { e.printStackTrace(); // rediect.addFlashAttribute("errorText", "您的账号或密码输入错误!"); return "{\"Msg\":\"您的账号或密码输入错误\",\"state\":\"failed\"}"; } return "{\"Msg\":\"登陆成功\",\"state\":\"success\"}"; } @RequestMapping("/") @ResponseBody public String index() { return "no permission"; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/controller/UserController.java ================================================ package com.us.controller; import com.us.bean.User; import com.us.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.List; @RequestMapping(value = "/users") @RestController public class UserController { @Autowired private UserService userService; @RequestMapping(method = RequestMethod.GET) public List list(HttpServletRequest request) { return userService.getByMap(null); } @RequestMapping(value = "/{id}", method = RequestMethod.GET) public User detail(@PathVariable Integer id) { return userService.getById(id); } @RequestMapping(method = RequestMethod.POST) public User create(@RequestBody User user) { return userService.create(user); } @RequestMapping(method = RequestMethod.PUT) public User update(@RequestBody User user) { return userService.update(user); } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public int delete(@PathVariable Integer id) { return userService.delete(id); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/dao/EventDao.java ================================================ package com.us.dao; import com.us.bean.Event; import java.util.List; import java.util.Map; public interface EventDao { List getByMap(Map map); Event getById(Integer id); Integer create(Event event); int update(Event event); int delete(Integer id); } ================================================ FILE: springboot-shiro/src/main/java/com/us/dao/PermissionDao.java ================================================ package com.us.dao; import com.us.bean.Permission; import java.util.List; import java.util.Map; public interface PermissionDao { List getByMap(Map map); Permission getById(Integer id); Integer create(Permission permission); int update(Permission permission); int delete(Integer id); List getList(); List getByUserId(Integer userId); } ================================================ FILE: springboot-shiro/src/main/java/com/us/dao/RoleDao.java ================================================ package com.us.dao; import com.us.bean.Role; import java.util.List; import java.util.Map; public interface RoleDao { List getByMap(Map map); Role getById(Integer id); Integer create(Role role); int update(Role role); int delete(Integer id); } ================================================ FILE: springboot-shiro/src/main/java/com/us/dao/UserDao.java ================================================ package com.us.dao; import com.us.bean.User; import java.util.List; import java.util.Map; public interface UserDao { List getByMap(Map map); User getById(Integer id); Integer create(User user); int update(User user); int delete(Integer id); User getByUserName(String userName); } ================================================ FILE: springboot-shiro/src/main/java/com/us/service/EventService.java ================================================ package com.us.service; import com.us.bean.Event; import com.us.dao.EventDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class EventService { @Autowired private EventDao eventDao; public List getByMap(Map map) { return eventDao.getByMap(map); } public Event getById(Integer id) { return eventDao.getById(id); } public Event create(Event event) { eventDao.create(event); return event; } public Event update(Event event) { eventDao.update(event); return event; } public int delete(Integer id) { return eventDao.delete(id); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/service/PermissionService.java ================================================ package com.us.service; import com.us.bean.Permission; import com.us.dao.PermissionDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class PermissionService { @Autowired private PermissionDao permissionDao; public List getByMap(Map map) { return permissionDao.getByMap(map); } public Permission getById(Integer id) { return permissionDao.getById(id); } public Permission create(Permission permission) { permissionDao.create(permission); return permission; } public Permission update(Permission permission) { permissionDao.update(permission); return permission; } public int delete(Integer id) { return permissionDao.delete(id); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/service/RoleService.java ================================================ package com.us.service; import com.us.bean.Role; import com.us.dao.RoleDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class RoleService { @Autowired private RoleDao roleDao; public List getByMap(Map map) { return roleDao.getByMap(map); } public Role getById(Integer id) { return roleDao.getById(id); } public Role create(Role role) { roleDao.create(role); return role; } public Role update(Role role) { roleDao.update(role); return role; } public int delete(Integer id) { return roleDao.delete(id); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/service/UserService.java ================================================ package com.us.service; import com.us.bean.User; import com.us.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class UserService { @Autowired private UserDao userDao; public List getByMap(Map map) { return userDao.getByMap(map); } public User getById(Integer id) { return userDao.getById(id); } public User create(User user) { userDao.create(user); return user; } public User update(User user) { userDao.update(user); return user; } public int delete(Integer id) { return userDao.delete(id); } public User getByUserName(String userName) { return userDao.getByUserName(userName); } } ================================================ FILE: springboot-shiro/src/main/java/com/us/shiro/ShiroConfiguration.java ================================================ package com.us.shiro; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.filter.authc.LogoutFilter; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import javax.servlet.Filter; import java.util.LinkedHashMap; import java.util.Map; /** * shiro配置类 * Created by cdyoue on 2016/10/21. */ @Configuration public class ShiroConfiguration { /** * LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类, * 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。 * 主要是AuthorizingRealm类的子类,以及EhCacheManager类。 */ @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * HashedCredentialsMatcher,这个类是为了对密码进行编码的, * 防止密码在数据库里明码保存,当然在登陆认证的时候, * 这个类也负责对form里输入的密码进行编码。 */ @Bean(name = "hashedCredentialsMatcher") public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); credentialsMatcher.setHashAlgorithmName("MD5"); credentialsMatcher.setHashIterations(2); credentialsMatcher.setStoredCredentialsHexEncoded(true); return credentialsMatcher; } /** * ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm, * 负责用户的认证和权限的处理,可以参考JdbcRealm的实现。 */ @Bean(name = "shiroRealm") @DependsOn("lifecycleBeanPostProcessor") public ShiroRealm shiroRealm() { ShiroRealm realm = new ShiroRealm(); // realm.setCredentialsMatcher(hashedCredentialsMatcher()); return realm; } // /** // * EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来, // * 然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。 // */ // @Bean(name = "ehCacheManager") // @DependsOn("lifecycleBeanPostProcessor") // public EhCacheManager ehCacheManager() { // return new EhCacheManager(); // } /** * SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。 * // */ @Bean(name = "securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); // securityManager.setCacheManager(ehCacheManager()); return securityManager; } /** * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。 * 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。 */ @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); Map filters = new LinkedHashMap(); LogoutFilter logoutFilter = new LogoutFilter(); logoutFilter.setRedirectUrl("/login"); // filters.put("logout",null); shiroFilterFactoryBean.setFilters(filters); Map filterChainDefinitionManager = new LinkedHashMap(); filterChainDefinitionManager.put("/logout", "logout"); filterChainDefinitionManager.put("/user/**", "authc,roles[ROLE_USER]"); filterChainDefinitionManager.put("/events/**", "authc,roles[ROLE_ADMIN]"); // filterChainDefinitionManager.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取 filterChainDefinitionManager.put("/**", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager); shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); return shiroFilterFactoryBean; } /** * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。 */ @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator(); defaultAAP.setProxyTargetClass(true); return defaultAAP; } /** * AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类, * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor(); aASA.setSecurityManager(securityManager()); return aASA; } } ================================================ FILE: springboot-shiro/src/main/java/com/us/shiro/ShiroRealm.java ================================================ package com.us.shiro; import com.us.bean.Permission; import com.us.bean.Role; import com.us.bean.User; import com.us.dao.PermissionDao; import com.us.dao.UserDao; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** * Created by cdyoue on 2016/10/21. */ public class ShiroRealm extends AuthorizingRealm { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private UserDao userService; @Autowired private PermissionDao permissionService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("doGetAuthorizationInfo+"+principalCollection.toString()); User user = userService.getByUserName((String) principalCollection.getPrimaryPrincipal()); //把principals放session中 key=userId value=principals SecurityUtils.getSubject().getSession().setAttribute(String.valueOf(user.getId()),SecurityUtils.getSubject().getPrincipals()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //赋予角色 for(Role userRole:user.getRoles()){ info.addRole(userRole.getName()); } //赋予权限 for(Permission permission:permissionService.getByUserId(user.getId())){ // if(StringUtils.isNotBlank(permission.getPermCode())) info.addStringPermission(permission.getName()); } //设置登录次数、时间 // userService.updateUserLogin(user); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info("doGetAuthenticationInfo +" + authenticationToken.toString()); UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; String userName=token.getUsername(); logger.info(userName+token.getPassword()); User user = userService.getByUserName(token.getUsername()); if (user != null) { // byte[] salt = Encodes.decodeHex(user.getSalt()); // ShiroUser shiroUser=new ShiroUser(user.getId(), user.getLoginName(), user.getName()); //设置用户session Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("user", user); return new SimpleAuthenticationInfo(userName,user.getPassword(),getName()); } else { return null; } // return null; } } ================================================ FILE: springboot-shiro/src/main/resources/application.properties ================================================ #local server.contextPath=/ server.port=8080 jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/epp_manager?useSSL=false&useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=admin spring.mvc.view.prefix=/ spring.mvc.view.suffix=.html logging.config=classpath:log4j.properties ================================================ FILE: springboot-shiro/src/main/resources/log4j.properties ================================================ #local # Output pattern : date [thread] priority category - message log4j.rootLogger=INFO, Console, R #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender #/opt/apps/epp-manager/var/logs/epp-manager.log log4j.appender.R.File=logs/epp-manager.log log4j.appender.R.MaxFileSize=20MB log4j.appender.R.MaxBackupIndex=30 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n #Project defalult level log4j.logger.com.us=INFO #spring default level log4j.logger.org.springframework=INFO log4j.logger.org.springframework.jdbc=INFO #apache log4j.logger.org.apache=INFO log4j.logger.org.activiti=INFO log4j.logger.org.activiti.engine.impl.persistence.entity=INFO log4j.logger.org.activiti.spring.SpringTransactionInterceptor=ERROR #mybatis, debug level to see sql log4j.logger.com.us.cmbms.dao=INFO log4j.logger.com.us.workflow.dao=INFO ================================================ FILE: springboot-shiro/src/main/resources/mapper/EventDaoMapper.xml ================================================ and id = #{id} and raw_event_id = #{rawEventId} and host = #{host} and ip = #{ip} and source = #{source} and type = #{type} and start_time = #{startTime} and end_time = #{endTime} and content = #{content} and data_type = #{dataType} and suggest = #{suggest} and business_system_id = #{businessSystemId} and department_id = #{departmentId} and status = #{status} and occur_count = #{occurCount} and owner = #{owner} and responsed_time = #{responsedTime} and responsed_by = #{responsedBy} and resolved_time = #{resolvedTime} and resolved_by = #{resolvedBy} and closed_time = #{closedTime} and closed_by = #{closedBy} and ( host like CONCAT('%', #{keywords},'%') OR ip like CONCAT('%', #{keywords},'%') OR source like CONCAT('%', #{keywords},'%') OR type like CONCAT('%', #{keywords},'%') OR content like CONCAT('%', #{keywords},'%') OR suggest like CONCAT('%', #{keywords},'%') OR status like CONCAT('%', #{keywords},'%') OR owner like CONCAT('%', #{keywords},'%') OR responsed_by like CONCAT('%', #{keywords},'%') OR resolved_by like CONCAT('%', #{keywords},'%') OR closed_by like CONCAT('%', #{keywords},'%') ) SELECT LAST_INSERT_ID() INSERT INTO event( id, raw_event_id, host, ip, source, type, start_time, end_time, content, data_type, suggest, business_system_id, department_id, status, occur_count, owner, responsed_time, responsed_by, resolved_time, resolved_by, closed_time, closed_by )VALUES( #{id}, #{rawEventId}, #{host}, #{ip}, #{source}, #{type}, #{startTime}, #{endTime}, #{content}, #{dataType}, #{suggest}, #{businessSystemId}, #{departmentId}, #{status}, #{occurCount}, #{owner}, #{responsedTime}, #{responsedBy}, #{resolvedTime}, #{resolvedBy}, #{closedTime}, #{closedBy} ) UPDATE event SET raw_event_id = #{rawEventId}, host = #{host}, ip = #{ip}, source = #{source}, type = #{type}, start_time = #{startTime}, end_time = #{endTime}, content = #{content}, data_type = #{dataType}, suggest = #{suggest}, business_system_id = #{businessSystemId}, department_id = #{departmentId}, status = #{status}, occur_count = #{occurCount}, owner = #{owner}, responsed_time = #{responsedTime}, responsed_by = #{responsedBy}, resolved_time = #{resolvedTime}, resolved_by = #{resolvedBy}, closed_time = #{closedTime}, closed_by = #{closedBy} WHERE id = #{id} DELETE FROM event WHERE id = #{id} ================================================ FILE: springboot-shiro/src/main/resources/mapper/PermissionDaoMapper.xml ================================================ and id = #{id} and name = #{name} and permission_url = #{permissionUrl} and method = #{method} and description = #{description} SELECT LAST_INSERT_ID() INSERT INTO permission( id, name, permission_url, method, description )VALUES( #{id}, #{name}, #{permissionUrl}, #{method}, #{description} ) UPDATE permission SET name = #{name}, permission_url = #{permissionUrl}, method = #{method}, description = #{description} WHERE id = #{id} DELETE FROM permission WHERE id = #{id} ================================================ FILE: springboot-shiro/src/main/resources/mapper/RoleDaoMapper.xml ================================================ and id = #{id} and name = #{name} and role_level = #{roleLevel} and description = #{description} SELECT LAST_INSERT_ID() INSERT INTO role( id, name, role_level, description )VALUES( #{id}, #{name}, #{roleLevel}, #{description} ) UPDATE role SET name = #{name}, role_level = #{roleLevel}, description = #{description} WHERE id = #{id} DELETE FROM role WHERE id = #{id} ================================================ FILE: springboot-shiro/src/main/resources/mapper/UserDaoMapper.xml ================================================ and id = #{id} and cnname = #{cnname} and username = #{username} and password = #{password} and email = #{email} and telephone = #{telephone} and mobile_phone = #{mobilePhone} and wechat_id = #{wechatId} and skill = #{skill} and department_id = #{departmentId} and login_count = #{loginCount} and ( cnname like CONCAT('%', #{keywords},'%') OR username like CONCAT('%', #{keywords},'%') OR telephone like CONCAT('%', #{keywords},'%') OR mobile_phone like CONCAT('%', #{keywords},'%') OR email like CONCAT('%', #{keywords},'%') OR skill like CONCAT('%', #{keywords},'%') OR wechat_id like CONCAT('%', #{keywords},'%') ) SELECT LAST_INSERT_ID() INSERT INTO user( id, cnname, username, password, email, telephone, mobile_phone, wechat_id, skill, department_id, login_count )VALUES( #{id}, #{cnname}, #{username}, #{password}, #{email}, #{telephone}, #{mobilePhone}, #{wechatId}, #{skill}, #{departmentId}, #{loginCount} ) UPDATE user SET cnname = #{cnname}, username = #{username}, password = #{password}, email = #{email}, telephone = #{telephone}, mobile_phone = #{mobilePhone}, wechat_id = #{wechatId}, skill = #{skill}, department_id = #{departmentId}, login_count = #{loginCount} WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-shiro2/README.md ================================================ ##springboot-shior2 是使用shior 框架调取用户权限服务,进行登录权限验证的例子,其中的用户权限服务没有写,都是用TODO 标示出来了,使用时可以根据各自的用户权限服务进行编码替换 springboot-shiro2 也是和dubbo 的结合例子是 消费者的示例。 引入了 abel-user-api 模块 ================================================ FILE: springboot-shiro2/pom.xml ================================================ 4.0.0 cn.abel abel-parent 1.0.0-SNAPSHOT cn.abel springboot-shior2 1.0.0 jar Spring Boot cn.abel abel-util 1.0.0-SNAPSHOT cn.abel abel-user-api 1.0.0-SNAPSHOT org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-quartz org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-freemarker org.springframework.boot spring-boot-starter-test test org.apache.commons commons-pool2 org.apache.commons commons-collections4 com.alibaba fastjson com.alibaba dubbo org.slf4j log4j-over-slf4j org.apache.zookeeper zookeeper org.apache.shiro shiro-spring org.apache.shiro shiro-ehcache org.apache.shiro shiro-quartz org.apache.shiro shiro-ehcache net.mingsoft shiro-freemarker-tags com.fasterxml.jackson.core jackson-databind com.fasterxml.jackson.core jackson-annotations 2.9.9.1 com.fasterxml.jackson.core jackson-core org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/ShiroRestApplication.java ================================================ package cn.abel.rest; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.ImportResource; /** * 无数据库运行 * */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @ImportResource("classpath*:META-INF/spring/*.xml") public class ShiroRestApplication { public static void main(String[] args) { SpringApplication.run(ShiroRestApplication.class, args); } } ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/config/RedisConfig.java ================================================ package cn.abel.rest.config; import java.time.Duration; import java.util.HashMap; import java.util.Map; import cn.abel.rest.constants.Constants; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisPassword; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * redis缓存配置 * */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { /** logger */ private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); /** * serializer */ private static final StringRedisSerializer STRING_SERIALIZER = new StringRedisSerializer(); @Value("${spring.redis.database}") private Integer database; @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private Integer port; @Value("${spring.redis.password}") private String password; @Value("${spring.redis.lettuce.pool.max-active}") private Integer maxActive; @Value("${spring.redis.lettuce.pool.max-wait}") private Integer maxWait; @Value("${spring.redis.lettuce.pool.max-idle}") private Integer maxIdle; @Value("${spring.redis.lettuce.pool.min-idle}") private Integer minIdle; @Value("${spring.redis.lettuce.shutdown-timeout}") private Integer timeout; /** * 在使用@Cacheable时,如果不指定key,则使用这个默认的key生成器生成的key * * @return */ @Override @Bean public KeyGenerator keyGenerator() { return (target, method, params) -> { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); }; } /** * 声明缓存管理器 */ @Override @Bean public CacheManager cacheManager() { //1. entryTtl: 定义默认的cache time-to-live. //2. disableCachingNullValues: 禁止缓存Null对象. 视需求而定. //3. computePrefixWith: 此处定义了cache key的前缀, 避免公司不同项目之间的key名称冲突. //4. serializeKeysWith, serializeValuesWith: 定义key和value的序列化协议, 同时的hash key和hash value也被定义. // 缓存配置 RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues().computePrefixWith(cacheName -> Constants.REDIS_KEY_PRE.concat(":").concat(cacheName).concat(":")).entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT)); Map redisCacheConfigurationMap = new HashMap<>(2); //redisCacheConfigurationMap.put(Constants.CACHE_NAME_PERMISSION, permissionCacheConfiguration); //初始化一个RedisCacheWriter RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()); RedisSerializationContext.SerializationPair valuePair = RedisSerializationContext.SerializationPair.fromSerializer(STRING_SERIALIZER); //RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer(new ObjectMapper())); RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(valuePair); //设置默认过期时间是1天 defaultCacheConfig.entryTtl(Duration.ofDays(Constants.REDIS_TIMEOUT)); //初始化RedisCacheManager RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); cacheManager.afterPropertiesSet(); logger.info("RedisCacheManager config success"); return cacheManager; } @Bean(name = "redisTemplate") @Primary public RedisTemplate redisTemplate() { return getTemplate(redisConnectionFactory()); } @Bean(name = "stringRedisTemplate") public StringRedisTemplate stringRedisTemplate() { return new StringRedisTemplate(redisConnectionFactory()); } private RedisConnectionFactory redisConnectionFactory() { return connectionFactory(maxActive, maxIdle, minIdle, maxWait, host, password, timeout, port, database); } private RedisConnectionFactory connectionFactory(Integer maxActive, Integer maxIdle, Integer minIdle, Integer maxWait, String host, String password, Integer timeout, Integer port, Integer database) { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPort(port); redisStandaloneConfiguration.setDatabase(database); redisStandaloneConfiguration.setPassword(RedisPassword.of(password)); GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxTotal(maxActive); poolConfig.setMaxIdle(maxIdle); poolConfig.setMinIdle(minIdle); poolConfig.setMaxWaitMillis(maxWait); LettuceClientConfiguration lettucePoolingConfig = LettucePoolingClientConfiguration.builder() //.commandTimeout(Duration.ofSeconds(15)) .poolConfig(poolConfig).shutdownTimeout(Duration.ofMillis(timeout)).build(); LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, lettucePoolingConfig); connectionFactory.afterPropertiesSet(); return connectionFactory; } private RedisTemplate getTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(factory); template.setKeySerializer(STRING_SERIALIZER); template.setValueSerializer(jackson2JsonRedisSerializer()); //不能用stringSerializer,有地方使用ShiroUser做key,不能转换 //template.setHashKeySerializer(STRING_SERIALIZER); //template.setHashKeySerializer(jackson2JsonRedisSerializer()); template.afterPropertiesSet(); return template; } private RedisSerializer jackson2JsonRedisSerializer() { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper objectMapper = new ObjectMapper(); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); return jackson2JsonRedisSerializer; } } ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/constants/Constants.java ================================================ package cn.abel.rest.constants; public interface Constants { /** * 第三方登录的token。 */ String THIRD_PARTY_ACCESS_TOKEN_NAME = "accessToken"; /** 用户注册和绑定时的ip */ String CLIENT_IP = "127.0.0.1"; /** redis缓存 key前缀 */ String REDIS_KEY_PRE = "abel-user"; /** 超时时间(天) */ long REDIS_TIMEOUT = 10L; } ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/controller/LoginController.java ================================================ package cn.abel.rest.controller; import cn.abel.response.ResponseEntity; import cn.abel.rest.shiro.ShiroUser; import cn.abel.user.models.User; import cn.abel.user.service.PermissionService; import cn.abel.user.service.RoleService; import cn.abel.user.service.UserService; import com.alibaba.dubbo.config.annotation.Reference; import com.google.common.collect.Sets; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author yyb * @time 2020/3/6 */ @RestController @CrossOrigin @RequestMapping("/") public class LoginController { private static final Logger logger = LoggerFactory.getLogger(LoginController.class); @Reference private UserService userService; /** * @return */ @RequestMapping(value = "/login", method = RequestMethod.POST) public ResponseEntity login() { //TODO:登录日志。 ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal(); user.setToken(SecurityUtils.getSubject().getSession().getId().toString()); return ResponseEntity.ok(user); } /** * 获取当前登录人的登录信息,包括拥有的角色、权限等。 * * @return */ @GetMapping("/logininfo") public ResponseEntity loginInfo() { ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal(); Map map = new HashMap<>(); Set permissions = Sets.newHashSet(); //TODO 获取当前用户所有的权限和角色 User user = userService.getById(shiroUser.getUserId().intValue()); map.put("roleList", user.getRoles()); map.put("permissionList", permissions); map.put("userId", shiroUser.getUserId()); map.put("username", shiroUser.getLoginName()); return ResponseEntity.ok(map); } /** * 注销 * @return */ @PostMapping("/logout") public ResponseEntity logout() { Subject subject = SecurityUtils.getSubject(); subject.logout(); return ResponseEntity.ok(); } } ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultErrorController.java ================================================ package cn.abel.rest.exception; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController; import org.springframework.boot.web.servlet.error.DefaultErrorAttributes; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.servlet.ModelAndView; /** * 404 覆盖默认error处理方法(不设置则在根目录查找error页面) * */ @Controller public class DefaultErrorController extends BasicErrorController { public DefaultErrorController(ServerProperties serverProperties) { super(new DefaultErrorAttributes(), serverProperties.getError()); } /** * 覆盖默认的Json响应 */ @Override public ResponseEntity> error(HttpServletRequest request) { Map body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); //输出自定义的Json格式 Map map = new HashMap<>(2); map.put("status", false); map.put("msg", body.get("message")); return new ResponseEntity<>(map, status); } /** * 覆盖默认的HTML响应 */ @Override public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { //请求的状态 HttpStatus status = getStatus(request); response.setStatus(getStatus(request).value()); Map model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML)); ModelAndView modelAndView = resolveErrorView(request, response, status, model); //指定自定义的视图 return (modelAndView == null ? new ModelAndView("error/error", model) : modelAndView); } } ================================================ FILE: springboot-shiro2/src/main/java/cn/abel/rest/exception/DefaultExceptionHandler.java ================================================ package cn.abel.rest.exception; import cn.abel.exception.ServiceException; import cn.abel.response.ResponseEntity; import org.apache.shiro.authz.UnauthorizedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.ui.Model; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.NativeWebRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.ConstraintViolationException; /** * 统一异常处理 * */ @ControllerAdvice public class DefaultExceptionHandler { /** * logger */ private static final Logger logger = LoggerFactory.getLogger(DefaultExceptionHandler.class); private static final String ERROR_500 = "error/500"; private static final String ERROR_403 = "error/403"; private static final int ARG_ERROR_CODE = 400; /** * 参数验证异常。 * * @param ex * @return */ @ResponseBody @ResponseStatus(HttpStatus.OK) @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleMethodArgumentNotValidException( HttpServletRequest request, HttpServletResponse response, MethodArgumentNotValidException ex) { String errMsg = null; if (ex.getBindingResult() != null && ex.getBindingResult().hasErrors()) { errMsg = ex.getBindingResult().getFieldErrors().get(0).getDefaultMessage(); } return ResponseEntity.error(ARG_ERROR_CODE, errMsg); } /** * 参数验证异常。 * * @param ex * @return */ @ResponseBody @ResponseStatus(HttpStatus.OK) @ExceptionHandler(ConstraintViolationException.class) public ResponseEntity handleConstraintViolationException( HttpServletRequest request, HttpServletResponse response, ConstraintViolationException ex) { String errMsg = ((ConstraintViolationException) ex).getConstraintViolations() .iterator().next().getMessage(); return ResponseEntity.error(ARG_ERROR_CODE, errMsg); } /** * ServiceException异常 * * @param exception * @return */ @ExceptionHandler({ServiceException.class}) @ResponseStatus(HttpStatus.OK) public String processServiceException(Exception exception, Model model) { model.addAttribute("exception", exception.getMessage()); logger.error("rpc接口调用异常。{}", exception.getMessage()); return ERROR_500; } /** * 没有权限 异常 *

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

================================================ FILE: springboot-springCloud/ui/src/main/resources/static/js/app.js ================================================ var uiApp = angular.module("uiApp", ["ui.router"]); uiApp.config(function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise("person"); $stateProvider .state('person', { url: '/person', templateUrl: '/tpl/person.html', controller: 'PersonController' }) .state('some',{ url:'/some', templateUrl: '/tpl/some.html', controller: 'SomeController' }); }); uiApp.controller("PersonController", function ($scope, $http) { $scope.people = ""; $scope.errorMessage = ""; $scope.getMessageResponse = function(personName) { $http.post('/dispatch', personName).success(function(data){ $scope.people = data; $scope.errorMessage = ""; }).error(function() { $scope.errorMessage = "错误"; }); } }); uiApp.controller("SomeController", function ($scope, $http) { $scope.str = ""; $scope.errorMessage = ""; $scope.getSome = function(){ $http.get('/getsome').success(function(data){ $scope.str = data; $scope.errorMessage = ""; }).error(function() { $scope.errorMessage = "错误"; }); } }); ================================================ FILE: springboot-springCloud/ui/src/main/resources/static/tpl/person.html ================================================

通过Person Service保存person

================================================ FILE: springboot-springCloud/ui/src/main/resources/static/tpl/some.html ================================================

从 Some Service获得字符

================================================ FILE: springboot-springCloud/ui/target/classes/application.yml ================================================ server: port: 80 ================================================ FILE: springboot-springCloud/ui/target/classes/bootstrap.yml ================================================ spring: application: name: ui eureka: instance: non-secure-port: ${server.port:80} client: service-url: defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ ================================================ FILE: springboot-springCloud/ui/target/classes/static/css/application.css ================================================ body { padding-top: 60px; } h1, h2, h3, h4, h5, h6 { font-family: microsoft yahei; } p, div { font-family: microsoft yahei; font-size: 12px; } .longtext { word-break:break-all; } ================================================ FILE: springboot-springCloud/ui/target/classes/static/index.html ================================================ 原生云应用
================================================ FILE: springboot-springCloud/ui/target/classes/static/js/app.js ================================================ var uiApp = angular.module("uiApp", ["ui.router"]); uiApp.config(function ($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise("person"); $stateProvider .state('person', { url: '/person', templateUrl: '/tpl/person.html', controller: 'PersonController' }) .state('some',{ url:'/some', templateUrl: '/tpl/some.html', controller: 'SomeController' }); }); uiApp.controller("PersonController", function ($scope, $http) { $scope.people = ""; $scope.errorMessage = ""; $scope.getMessageResponse = function(personName) { $http.post('/dispatch', personName).success(function(data){ $scope.people = data; $scope.errorMessage = ""; }).error(function() { $scope.errorMessage = "错误"; }); } }); uiApp.controller("SomeController", function ($scope, $http) { $scope.str = ""; $scope.errorMessage = ""; $scope.getSome = function(){ $http.get('/getsome').success(function(data){ $scope.str = data; $scope.errorMessage = ""; }).error(function() { $scope.errorMessage = "错误"; }); } }); ================================================ FILE: springboot-springCloud/ui/target/classes/static/tpl/person.html ================================================

通过Person Service保存person

================================================ FILE: springboot-springCloud/ui/target/classes/static/tpl/some.html ================================================

从 Some Service获得字符

================================================ FILE: springboot-springSecurity2/pom.xml ================================================ 4.0.0 com.us springboot-security2 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 3.2.7 1.2.2 org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/config/DBconfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * Created by yangyibo on 17/1/18. */ @Configuration public class DBconfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/config/MyBatisConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration @ComponentScan public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()}); sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/config/MyBatisScannerConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/config/TransactionConfig.java ================================================ package com.us.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/config/WebSecurityConfig.java ================================================ package com.us.example.config; import com.us.example.security.CustomUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; /** * Created by yangyibo on 17/1/18. */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserService customUserService; @Autowired protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService).passwordEncoder(new BCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/users/**") .authenticated() .antMatchers(HttpMethod.POST) .authenticated() .antMatchers(HttpMethod.PUT) .authenticated() .antMatchers(HttpMethod.DELETE) .authenticated() .antMatchers("/**") .permitAll() .and() .sessionManagement() .and() .httpBasic(); } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/controller/HomeController.java ================================================ package com.us.example.controller; import com.us.example.dao.UserDao; import com.us.example.domain.SysUser; import com.us.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.annotation.Secured; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; /** * Created by yangyibo on 17/1/18. */ @Controller @RequestMapping("/users") public class HomeController { @Autowired UserService userService; @RequestMapping(method = RequestMethod.GET) @ResponseBody public String getUsers() { return "getUsers"; } @Secured({"ROLE_ADMIN","ROLE_USER"}) @RequestMapping(method = RequestMethod.POST) @ResponseBody public Object save(@RequestBody SysUser user) { return userService.create(user); } @Secured("ROLE_ADMIN") @RequestMapping(method = RequestMethod.PUT) @ResponseBody public String update() { return "updateUser"; } @Secured("ROLE_ADMIN") @RequestMapping(method = RequestMethod.DELETE) @ResponseBody public String delete() { return "deleteUser"; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/controller/LoginController.java ================================================ package com.us.example.controller; import com.us.example.domain.SysUser; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * Created by yangyibo on 17/3/1. */ @RestController public class LoginController { @RequestMapping(value = "/login") @ResponseBody //用户名密码是用base64 加密 原文为 admin:admin 即 用户名:密码 内容是放在request.getHeader 的 "authorization" 中 public Object login(@AuthenticationPrincipal SysUser loginedUser, @RequestParam(name = "logout", required = false) String logout) { if (logout != null) { return null; } if (loginedUser != null) { return loginedUser; } return null; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/dao/UserDao.java ================================================ package com.us.example.dao; import com.us.example.domain.SysUser; public interface UserDao { SysUser findByUserName(String username); int create (SysUser sysUser); } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/domain/SysRole.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class SysRole { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/domain/SysUser.java ================================================ package com.us.example.domain; import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; /** * Created by yangyibo on 17/1/17. */ public class SysUser implements UserDetails { // implements UserDetails 用于登录时 @AuthenticationPrincipal 标签取值 private Integer id; private String username; @JsonIgnore private String password; private String rawPassword; @JsonIgnore private List roles; private List authorities; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } public String getRawPassword() { return rawPassword; } public void setRawPassword(String rawPassword) { this.rawPassword = rawPassword; } @JsonIgnore @Override public boolean isAccountNonExpired() { return true; } @JsonIgnore @Override public boolean isAccountNonLocked() { return true; } @JsonIgnore @Override public boolean isCredentialsNonExpired() { return true; } @JsonIgnore @Override public boolean isEnabled() { return true; } @JsonIgnore @Override public Collection getAuthorities() { return authorities; } public void setGrantedAuthorities(List authorities) { this.authorities = authorities; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/security/CustomUserService.java ================================================ package com.us.example.security; import com.us.example.dao.UserDao; import com.us.example.domain.SysRole; import com.us.example.domain.SysUser; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/1/18. */ @Service public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口 @Autowired UserDao userDao; private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomUserService.class); @Override public UserDetails loadUserByUsername(String username) { //重写loadUserByUsername 方法获得 userdetails 类型用户 SysUser user = userDao.findByUserName(username); if(user == null){ throw new UsernameNotFoundException("用户名不存在"); } List authorities = new ArrayList<>(); //用于添加用户的权限。只要把用户权限添加到authorities 就万事大吉。 for(SysRole role:user.getRoles()) { authorities.add(new SimpleGrantedAuthority(role.getName())); logger.info("loadUserByUsername: " + user); } user.setGrantedAuthorities(authorities); //用于登录时 @AuthenticationPrincipal 标签取值 return user; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/service/UserService.java ================================================ package com.us.example.service; import com.us.example.dao.UserDao; import com.us.example.domain.SysUser; import com.us.example.util.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; /** * Created by yangyibo on 17/3/2. */ @Service public class UserService { @Autowired UserDao userDao; public SysUser create(SysUser sysUser){ //进行加密 BCryptPasswordEncoder encoder =new BCryptPasswordEncoder(); sysUser.setPassword(encoder.encode(MD5Util.encode(sysUser.getRawPassword().trim()))); userDao.create(sysUser); return sysUser; } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/util/BCryptPasswordEncoderTest.java ================================================ package com.us.example.util; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; /** * Created by yangyibo on 17/3/2. */ public class BCryptPasswordEncoderTest { public static void main(String[] args) { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); System.out.println("encoder: " + encoder.encode("abel")); System.out.println("encoder: " + encoder.encode("admin")); if (encoder.matches("abel", "$2a$10$IAz6WzJ314LH1NXq7Rf.dOYPP2uvzk08g.eAl9l4DRG4YsxavEV4W")) { System.out.println("encoder: true"); } System.out.println("------------华丽的分割线-----------------------"); String Md5Password = MD5Util.encode("abel"); System.out.println("Md5Password: " + Md5Password); System.out.println("encoder: " + encoder.encode(Md5Password)); if (encoder.matches(Md5Password, "$2a$10$37MXEfzlbtC6QSsRTlRhIOmykMRJtO5mU8Y.yiJBjy1x4WYWFR5gG")) { System.out.println("Md5Password: true"); } } } ================================================ FILE: springboot-springSecurity2/src/main/java/com/us/example/util/MD5Util.java ================================================ package com.us.example.util; import java.security.MessageDigest; /** * Created by yangyibo on 9/8/17. */ public class MD5Util { private static final String SALT = "salt"; public static String encode(String password) { password = password + SALT; return processEncode(password); } public static String processEncode(String password) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { throw new RuntimeException(e); } char[] charArray = password.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } public static void main(String[] args) { System.out.println(MD5Util.encode("abel")); System.out.println(MD5Util.encode("admin")); } } ================================================ FILE: springboot-springSecurity2/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?characterEncoding=utf-8&useSSL=false ms.db.username=root ms.db.password=admin ms.db.maxActive=500 server.port=8099 logging.level.org.springframework.security= INFO spring.thymeleaf.cache=false ================================================ FILE: springboot-springSecurity2/src/main/resources/mapper/UserDaoMapper.xml ================================================ SELECT LAST_INSERT_ID() INSERT into Sys_User (username,password) values (#{username},#{password}) ================================================ FILE: springboot-springSecurity3/pom.xml ================================================ 4.0.0 com.us springboot-security3 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 3.2.7 1.2.2 org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/Application.java ================================================ package com.us.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.us.example") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/DBconfig.java ================================================ package com.us.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; /** * Created by yangyibo on 17/1/18. */ @Configuration public class DBconfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/MyBatisConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration @ComponentScan public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory(ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // sessionFactory.setPlugins(new Interceptor[]{new PageInterceptor()}); sessionFactory.setMapperLocations(applicationContext.getResources("classpath*:mapper/*.xml")); return sessionFactory; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/MyBatisScannerConfig.java ================================================ package com.us.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/TransactionConfig.java ================================================ package com.us.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/WebMvcConfig.java ================================================ package com.us.example.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Created by yangyibo on 17/1/18. */ @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter{ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/config/WebSecurityConfig.java ================================================ package com.us.example.config; import com.us.example.service.CustomUserService; import com.us.example.service.MyFilterSecurityInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; /** * Created by yangyibo on 17/1/18. */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyFilterSecurityInterceptor myFilterSecurityInterceptor; @Bean UserDetailsService customUserService() { //注册UserDetailsService 的bean return new CustomUserService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()); //user Details Service验证 } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() //任何请求,登录后可以访问 .and() .formLogin() .loginPage("/login") .failureUrl("/login?error") .permitAll() //登录页面用户任意访问 .and() .logout().permitAll(); //注销行为任意访问 http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class) .csrf().disable(); } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/controller/HomeController.java ================================================ package com.us.example.controller; import com.us.example.domain.Msg; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; /** * Created by yangyibo on 17/1/18. */ @Controller public class HomeController { @RequestMapping("/") public String index(Model model){ Msg msg = new Msg("测试标题","测试内容","欢迎来到HOME页面,您拥有 ROLE_HOME 权限"); model.addAttribute("msg", msg); return "home"; } @RequestMapping("/admin") @ResponseBody public String hello(){ return "hello admin"; } @RequestMapping("/login") public String login(){ return "login"; } @RequestMapping(value = "/user", method = RequestMethod.GET) @ResponseBody public String getList(){ return "hello getList"; } @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseBody public String save(){ return "hello save"; } @RequestMapping(value = "/user", method = RequestMethod.PUT) @ResponseBody public String update(){ return "hello update"; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/dao/PermissionDao.java ================================================ package com.us.example.dao; import com.us.example.domain.Permission; import java.util.List; /** * Created by yangyibo on 17/1/20. */ public interface PermissionDao { public List findAll(); public List findByAdminUserId(int userId); } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/dao/UserDao.java ================================================ package com.us.example.dao; import com.us.example.domain.SysUser; public interface UserDao { public SysUser findByUserName(String username); } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/domain/Msg.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class Msg { private String title; private String content; private String etraInfo; public Msg(String title, String content, String etraInfo) { super(); this.title = title; this.content = content; this.etraInfo = etraInfo; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getEtraInfo() { return etraInfo; } public void setEtraInfo(String etraInfo) { this.etraInfo = etraInfo; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/domain/Permission.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/20. */ public class Permission { private int id; //权限名称 private String name; //权限描述 private String descritpion; //授权链接 private String url; //父节点id private int pid; //请求方法 private String method; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescritpion() { return descritpion; } public void setDescritpion(String descritpion) { this.descritpion = descritpion; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/domain/SysRole.java ================================================ package com.us.example.domain; /** * Created by yangyibo on 17/1/17. */ public class SysRole { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/domain/SysUser.java ================================================ package com.us.example.domain; import java.util.List; /** * Created by yangyibo on 17/1/17. */ public class SysUser { private Integer id; private String username; private String password; private List roles; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/service/CustomUserService.java ================================================ package com.us.example.service; import com.us.example.dao.PermissionDao; import com.us.example.dao.UserDao; import com.us.example.domain.Permission; import com.us.example.domain.SysRole; import com.us.example.domain.SysUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/1/18. */ @Service public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口 @Autowired UserDao userDao; @Autowired PermissionDao permissionDao; public UserDetails loadUserByUsername(String username) { SysUser user = userDao.findByUserName(username); if (user != null) { List permissions = permissionDao.findByAdminUserId(user.getId()); List grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { if (permission != null && permission.getName() != null) { GrantedAuthority grantedAuthority = new MyGrantedAuthority(permission.getUrl(), permission.getMethod()); grantedAuthorities.add(grantedAuthority); } } return new User(user.getUsername(), user.getPassword(), grantedAuthorities); } else { throw new UsernameNotFoundException("admin: " + username + " do not exist!"); } } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/service/MyAccessDecisionManager.java ================================================ package com.us.example.service; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.Iterator; /** * Created by yangyibo on 17/1/19. */ @Service public class MyAccessDecisionManager implements AccessDecisionManager { //decide 方法是判定是否拥有权限的决策方法 @Override public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); String url, method; AntPathRequestMatcher matcher; for (GrantedAuthority ga : authentication.getAuthorities()) { if (ga instanceof MyGrantedAuthority) { MyGrantedAuthority urlGrantedAuthority = (MyGrantedAuthority) ga; url = urlGrantedAuthority.getPermissionUrl(); method = urlGrantedAuthority.getMethod(); matcher = new AntPathRequestMatcher(url); if (matcher.matches(request)) { //当权限表权限的method为ALL时表示拥有此路径的所有请求方式权利。 if (method.equals(request.getMethod()) || "ALL".equals(method)) { return; } } } else if (ga.getAuthority().equals("ROLE_ANONYMOUS")) {//未登录只允许访问 login 页面 matcher = new AntPathRequestMatcher("/login"); if (matcher.matches(request)) { return; } } } throw new AccessDeniedException("no right"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class clazz) { return true; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/service/MyFilterSecurityInterceptor.java ================================================ package com.us.example.service; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import java.io.IOException; /** * Created by yangyibo on 17/1/19. */ @Service public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { @Autowired private FilterInvocationSecurityMetadataSource securityMetadataSource; @Autowired public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) { super.setAccessDecisionManager(myAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi里面有一个被拦截的url //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); try { //执行下一个拦截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/service/MyGrantedAuthority.java ================================================ package com.us.example.service; import org.springframework.security.core.GrantedAuthority; /** * Created by yangyibo on 17/2/15. */ public class MyGrantedAuthority implements GrantedAuthority { private String url; private String method; public String getPermissionUrl() { return url; } public void setPermissionUrl(String permissionUrl) { this.url = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public MyGrantedAuthority(String url, String method) { this.url = url; this.method = method; } @Override public String getAuthority() { return this.url + ";" + this.method; } } ================================================ FILE: springboot-springSecurity3/src/main/java/com/us/example/service/MyInvocationSecurityMetadataSourceService.java ================================================ package com.us.example.service; import com.us.example.dao.PermissionDao; import com.us.example.domain.Permission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * Created by yangyibo on 17/1/19. */ @Service public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { //此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。 //因为我不想每一次来了请求,都先要匹配一下权限表中的信息是不是包含此url, // 我准备直接拦截,不管请求的url 是什么都直接拦截,然后在MyAccessDecisionManager的decide 方法中做拦截还是放行的决策。 //所以此方法的返回值不能返回 null 此处我就随便返回一下。 @Override public Collection getAttributes(Object object) throws IllegalArgumentException { Collection co=new ArrayList<>(); co.add(new SecurityConfig("null")); return co; } @Override public Collection getAllConfigAttributes() { return null; } @Override public boolean supports(Class clazz) { return true; } } ================================================ FILE: springboot-springSecurity3/src/main/resources/application.properties ================================================ ms.db.driverClassName=com.mysql.jdbc.Driver ms.db.url=jdbc:mysql://localhost:3306/cache?characterEncoding=utf-8&useSSL=false ms.db.username=root ms.db.password=admin ms.db.maxActive=500 logging.level.org.springframework.security= INFO spring.thymeleaf.cache=false ================================================ FILE: springboot-springSecurity3/src/main/resources/mapper/PermissionDaoMapper.xml ================================================ ================================================ FILE: springboot-springSecurity3/src/main/resources/mapper/UserDaoMapper.xml ================================================ ================================================ FILE: springboot-springSecurity3/src/main/resources/templates/home.html ================================================

恭喜您,您有 ROLE_ADMIN 权限

================================================ FILE: springboot-springSecurity3/src/main/resources/templates/login.html ================================================ 登录页面

已成功注销

有错误,请重试

使用账号密码登录

================================================ FILE: springboot-springSecurity4/pom.xml ================================================ 4.0.0 com.example springboot-springSecurity4 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.us.Application 1.8 1.8 3.4.0 1.3.0 org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.thymeleaf.extras thymeleaf-extras-springsecurity4 mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 org.springframework spring-jdbc org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring ${mybatis-spring.version} ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/Application.java ================================================ package com.yy.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.yy.example") @SpringBootApplication public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/bean/Permission.java ================================================ package com.yy.example.bean; public class Permission { private Integer id; private String name; private String permissionUrl; private String method; private String description; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPermissionUrl() { return permissionUrl; } public void setPermissionUrl(String permissionUrl) { this.permissionUrl = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Override public String toString() { return "Permission{" + "id=" + id + ", name=" + name + ", permissionUrl=" + permissionUrl + ", method=" + method + ", description=" + description + '}'; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/bean/Role.java ================================================ package com.yy.example.bean; public class Role implements Comparable{ private Integer id; private String name; private Integer roleLevel; private String description; private String menuItems; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getRoleLevel() { return roleLevel; } public void setRoleLevel(Integer roleLevel) { this.roleLevel = roleLevel; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getMenuItems() { return menuItems; } public void setMenuItems(String menuItems) { this.menuItems = menuItems; } @Override public int compareTo(Role o) { if(id == o.getId()){ return 0; }else if(id > o.getId()){ return 1; }else{ return -1; } } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub if(obj instanceof Role){ if(this.id == ((Role)obj).getId()){ return true; } } return false; } @Override public String toString() { return "Role{" + "id=" + id + ", name=" + name + ", roleLevel=" + roleLevel + ", description=" + description + '}'; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/bean/User.java ================================================ package com.yy.example.bean; import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; public class User implements UserDetails { private Integer id; private String cnname; private String username; @JsonIgnore private String password; private String rePassword; private String historyPassword; private String email; @JsonIgnore private String telephone; private String mobilePhone; private List authorities; private Role role; private Integer roleId; @Override @JsonIgnore public boolean isAccountNonExpired() { return true; } @Override @JsonIgnore public boolean isAccountNonLocked() { return true; } @Override @JsonIgnore public boolean isCredentialsNonExpired() { return true; } @Override @JsonIgnore public boolean isEnabled() { return true; } public void setUsername(String username) { this.username = username; } @JsonIgnore public Collection getAuthorities() { return authorities; } public void setGrantedAuthorities(List authorities) { this.authorities = authorities; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCnname() { return cnname; } public void setCnname(String cnname) { this.cnname = cnname; } public String getUsername() { return username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getMobilePhone() { return mobilePhone; } public void setMobilePhone(String mobilePhone) { this.mobilePhone = mobilePhone; } public String getRePassword() { return rePassword; } public void setRePassword(String rePassword) { this.rePassword = rePassword; } public String getHistoryPassword() { return historyPassword; } public void setHistoryPassword(String historyPassword) { this.historyPassword = historyPassword; } public Role getRole() { return role; } public void setRole(Role role) { this.role = role; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } @Override public String toString() { return "User{" + "id=" + id + ", cnname=" + cnname + ", username=" + username + ", password=" + password + ", email=" + email + ", telephone=" + telephone + ", mobilePhone=" + mobilePhone + '}'; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/DataSourceConfig.java ================================================ package com.yy.example.config; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import java.beans.PropertyVetoException; @Configuration public class DataSourceConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("jdbc.driverClassName")); dataSource.setJdbcUrl(env.getProperty("jdbc.url")); dataSource.setUser(env.getProperty("jdbc.username")); dataSource.setPassword(env.getProperty("jdbc.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/MapperScannerConfig.java ================================================ package com.yy.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MapperScannerConfig { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("**.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/MyBatisConfig.java ================================================ package com.yy.example.config; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration public class MyBatisConfig { @Autowired private DataSource dataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactoryBean sqlSessionFactory( ApplicationContext applicationContext) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration(); configuration.setMapUnderscoreToCamelCase(true); configuration.setJdbcTypeForNull(JdbcType.NULL); configuration.setLogImpl(org.apache.ibatis.logging.log4j.Log4jImpl.class);//use log4j log sessionFactory.setConfiguration(configuration); sessionFactory.setMapperLocations(applicationContext.getResources("classpath:com/yy/example/mapper/*.xml")); // // Properties prop = new Properties(); // prop.setProperty("supportMethodsArguments","true"); // prop.setProperty("rowBoundsWithCount", "true"); // prop.setProperty("params","pageNum=pageNum;pageSize=pageSize;"); // PageInterceptor pi = new PageInterceptor(); // pi.setProperties(prop); // sessionFactory.setPlugins(new Interceptor[]{pi}); return sessionFactory; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/MyBatisScannerConfig.java ================================================ package com.yy.example.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MyBatisScannerConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.us.example.dao"); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); return mapperScannerConfigurer; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/TransactionConfig.java ================================================ package com.yy.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; @Configuration @ComponentScan public class TransactionConfig implements TransactionManagementConfigurer{ @Autowired private DataSource dataSource; @Bean(name = "transactionManager") @Override public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(dataSource); } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/config/WebSecurityConfig.java ================================================ package com.yy.example.config; import com.yy.example.security.UrlUserService; import com.yy.example.utils.MD5Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.crypto.password.PasswordEncoder; /** *
* * @author henley
* @version 1.0
* @taskId
* @CreateDate 2017年1月13日
*/ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UrlUserService urlUserService; @Autowired SessionRegistry sessionRegistry; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/login").permitAll() .antMatchers("/logout").permitAll() .antMatchers("/images/**").permitAll() .antMatchers("/js/**").permitAll() .antMatchers("/css/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/favicon.ico").permitAll() .antMatchers("/").permitAll() .anyRequest().authenticated() .and() .sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry) .and() .and() .logout() .invalidateHttpSession(true) .clearAuthentication(true) .and() .httpBasic(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(urlUserService).passwordEncoder(new PasswordEncoder() { @Override public String encode(CharSequence rawPassword) { return MD5Util.encode((String) rawPassword); } @Override public boolean matches(CharSequence rawPassword, String encodedPassword) { return encodedPassword.equals(MD5Util.encode((String) rawPassword)); } }); } @Bean public SessionRegistry getSessionRegistry(){ SessionRegistry sessionRegistry=new SessionRegistryImpl(); return sessionRegistry; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/controller/LoginController.java ================================================ package com.yy.example.controller; import com.yy.example.bean.User; import com.yy.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class LoginController { @Autowired UserService userService; @RequestMapping(value = "/login") @ResponseBody public Object login(@AuthenticationPrincipal User loginedUser, @RequestParam(name = "logout", required = false) String logout) { if (logout != null) { return null; } if (loginedUser != null) { return userService.getById(loginedUser.getId()); } return null; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/controller/UserController.java ================================================ package com.yy.example.controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; @RequestMapping(value = "/users") @RestController public class UserController { @RequestMapping(method = RequestMethod.GET) @ResponseBody public Object list(HttpServletRequest request) { return "Get all User"; } @RequestMapping(value = "/{id}", method = RequestMethod.GET) @ResponseBody public Object detail(@PathVariable Integer id) { return "Get a user"; } @RequestMapping(method = RequestMethod.POST) @ResponseBody public Object create(HttpServletRequest request) { return "POST a user"; } @RequestMapping(method = RequestMethod.PUT) @ResponseBody public Object update(HttpServletRequest request) { return "PUT a user"; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/dao/PermissionDao.java ================================================ package com.yy.example.dao; import com.yy.example.bean.Permission; import java.util.List; import java.util.Map; public interface PermissionDao { List getByMap(Map map); Permission getById(Integer id); Integer create(Permission permission); int update(Permission permission); List getByUserId(Integer userId); } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/dao/UserDao.java ================================================ package com.yy.example.dao; import com.yy.example.bean.User; import java.util.List; import java.util.Map; public interface UserDao { List getByMap(Map map); List getByRoleId(Map map); User getById(Integer id); Integer create(User user); int update(User user); User getByUserName(String userName); } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlAccessDecisionManager.java ================================================ package com.yy.example.security; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.Collection; /** * Created by yangyibo on 17/1/19. */ @Service public class UrlAccessDecisionManager implements AccessDecisionManager { @Override public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); String url, method; if ("anonymousUser".equals(authentication.getPrincipal()) || matchers("/images/**", request) || matchers("/js/**", request) || matchers("/css/**", request) || matchers("/fonts/**", request) || matchers("/", request) || matchers("/index.html", request) || matchers("/favicon.ico", request) || matchers("/login", request)) { return; } else { for (GrantedAuthority ga : authentication.getAuthorities()) { if (ga instanceof UrlGrantedAuthority) { UrlGrantedAuthority urlGrantedAuthority = (UrlGrantedAuthority) ga; url = urlGrantedAuthority.getPermissionUrl(); method = urlGrantedAuthority.getMethod(); if (matchers(url, request)) { if (method.equals(request.getMethod()) || "ALL".equals(method)) { return; } } } } } throw new AccessDeniedException("no right"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class clazz) { return true; } private boolean matchers(String url, HttpServletRequest request) { AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); if (matcher.matches(request)) { return true; } return false; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlConfigAttribute.java ================================================ package com.yy.example.security; import org.springframework.security.access.ConfigAttribute; import javax.servlet.http.HttpServletRequest; /** * Created by yangyibo on 17/2/15. */ public class UrlConfigAttribute implements ConfigAttribute { private final HttpServletRequest httpServletRequest; public UrlConfigAttribute(HttpServletRequest httpServletRequest) { this.httpServletRequest = httpServletRequest; } @Override public String getAttribute() { return null; } public HttpServletRequest getHttpServletRequest() { return httpServletRequest; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlFilterSecurityInterceptor.java ================================================ package com.yy.example.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import javax.servlet.*; import java.io.IOException; /** * Created by yangyibo on 17/2/7. */ @Service public class UrlFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { @Autowired private FilterInvocationSecurityMetadataSource securityMetadataSource; @Autowired public void setUrlAccessDecisionManager(UrlAccessDecisionManager urlAccessDecisionManager) { super.setAccessDecisionManager(urlAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi里面有一个被拦截的url //里面调用UrlMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 //再调用UrlAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); try { //执行下一个拦截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.securityMetadataSource; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlGrantedAuthority.java ================================================ package com.yy.example.security; import org.springframework.security.core.GrantedAuthority; /** * Created by yangyibo on 17/2/15. */ public class UrlGrantedAuthority implements GrantedAuthority { private String permissionUrl; private String method; public String getPermissionUrl() { return permissionUrl; } public void setPermissionUrl(String permissionUrl) { this.permissionUrl = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public UrlGrantedAuthority (String permissionUrl, String method) { this.permissionUrl = permissionUrl; this.method = method; } @Override public String getAuthority() { return this.permissionUrl + ";"+this.method; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlMetadataSourceService.java ================================================ package com.yy.example.security; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.Collection; import java.util.HashSet; import java.util.Set; /** * Created by yangyibo on 17/1/19. */ @Service public class UrlMetadataSourceService implements FilterInvocationSecurityMetadataSource { @Override public Collection getAttributes(Object object) throws IllegalArgumentException { final HttpServletRequest request = ((FilterInvocation) object).getRequest(); Set allAttributes = new HashSet<>(); ConfigAttribute configAttribute = new UrlConfigAttribute(request); allAttributes.add(configAttribute); return allAttributes; } @Override public Collection getAllConfigAttributes() { return null; } @Override public boolean supports(Class clazz) { return true; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/security/UrlUserService.java ================================================ package com.yy.example.security; import com.yy.example.bean.Permission; import com.yy.example.bean.User; import com.yy.example.dao.PermissionDao; import com.yy.example.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * Created by yangyibo on 17/2/7. */ @Service public class UrlUserService implements UserDetailsService { @Autowired UserDao userDao; @Autowired PermissionDao permissionDao; @Override public UserDetails loadUserByUsername(String userName) { //重写loadUserByUsername 方法获得 userdetails 类型用户 User user = userDao.getByUserName(userName); if (user != null) { List permissions = permissionDao.getByUserId(user.getId()); List grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { if (permission != null && permission.getName()!=null) { GrantedAuthority grantedAuthority = new UrlGrantedAuthority(permission.getPermissionUrl(),permission.getMethod()); grantedAuthorities.add(grantedAuthority); } } user.setGrantedAuthorities(grantedAuthorities); return user; } else { throw new UsernameNotFoundException("admin: " + userName + " do not exist!"); } } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/service/UserService.java ================================================ package com.yy.example.service; import com.yy.example.bean.User; import com.yy.example.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.session.SessionRegistry; import org.springframework.stereotype.Service; @Service public class UserService { @Autowired private SessionRegistry sessionRegistry; @Autowired private UserDao userDao; public User getById(Integer id) { User user = userDao.getById(id); return user; } } ================================================ FILE: springboot-springSecurity4/src/main/java/com/yy/example/utils/MD5Util.java ================================================ package com.yy.example.utils; /** * Created by yangyibo on 17/2/7. */ import java.security.MessageDigest; /** * MD5加密工具 * */ public class MD5Util { private static final String SALT = "yy"; private static final String WECAHT_SALT="yy_aa"; public static String encode(String password) { password = password + SALT; return processEncode(password); } /** * 与微信模块约定的加密模块 * */ public static String wechatEncode(String password){ password = password + WECAHT_SALT; return processEncode(password); } public static boolean wehcatValidation(String str, String token){ boolean flag = false; if(wechatEncode(str).equals(token)){ flag = true; } return flag; } public static String processEncode(String password) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (Exception e) { throw new RuntimeException(e); } char[] charArray = password.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } public static void main(String[] args) { System.out.println(MD5Util.encode("abel")); System.out.println(MD5Util.encode("admin")); } } ================================================ FILE: springboot-springSecurity4/src/main/resources/application.properties ================================================ jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/epp_manager?useSSL=false&useUnicode=true&characterEncoding=UTF-8 #jdbc.url=jdbc:mysql://47.94.17.188:3306/epp_manager?useSSL=false&useUnicode=true&characterEncoding=UTF-8 jdbc.username=root jdbc.password=admin server.port=8088 logging.level.org.springframework.security= INFO spring.thymeleaf.cache=false ================================================ FILE: springboot-springSecurity4/src/main/resources/com/yy/example/mapper/PermissionDaoMapper.xml ================================================ and id = #{id} and name = #{name} and permission_url = #{permissionUrl} and method = #{method} and description = #{description} SELECT LAST_INSERT_ID() INSERT INTO permission( id, name, permission_url, method, description )VALUES( #{id}, #{name}, #{permissionUrl}, #{method}, #{description} ) UPDATE permission SET name = #{name}, permission_url = #{permissionUrl}, method = #{method}, description = #{description} WHERE id = #{id} DELETE FROM permission WHERE id = #{id} ================================================ FILE: springboot-springSecurity4/src/main/resources/com/yy/example/mapper/UserDaoMapper.xml ================================================ and id = #{id} and cnname = #{cnname} and username = #{username} and password = #{password} and email = #{email} and telephone = #{telephone} and mobile_phone = #{mobilePhone} SELECT LAST_INSERT_ID() INSERT INTO user( id, cnname, username, password, email, telephone, mobile_phone, wechat_id, skill, department_id, login_count )VALUES( #{id}, #{cnname}, #{username}, #{password}, #{email}, #{telephone}, #{mobilePhone}, #{wechatId}, #{skill}, #{departmentId}, #{loginCount} ) UPDATE user cnname = #{cnname}, password = #{password}, email = #{email}, telephone = #{telephone}, mobile_phone = #{mobilePhone}, WHERE id = #{id} DELETE FROM user WHERE id = #{id} ================================================ FILE: springboot-swagger-ui/pom.xml ================================================ 4.0.0 com.abel springboot-swagger-ui 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent 1.3.0.RELEASE com.abel.Application 1.8 1.8 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web mysql mysql-connector-java 6.0.5 com.mchange c3p0 0.9.5.4 commons-logging commons-logging org.apache.commons commons-lang3 3.4 io.springfox springfox-swagger2 2.2.2 io.springfox springfox-swagger-ui 2.2.2 ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/Application.java ================================================ package com.abel.example; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ComponentScan; import static org.springframework.boot.SpringApplication.run; /** * Created by yangyibo on 17/1/17. */ @ComponentScan(basePackages ="com.abel.example") @SpringBootApplication @EnableCaching public class Application { public static void main(String[] args) { ConfigurableApplicationContext run = run(Application.class, args); } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/Swagger2.java ================================================ package com.abel.example; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * Created by yangyibo on 2018/9/7. */ @Configuration @EnableSwagger2 public class Swagger2 { /** * 创建API应用 * apiInfo() 增加API相关信息 * 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现, * 本例采用指定扫描的包路径来定义指定要建立API的目录。 * * @return */ @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.abel.example.controller")) .paths(PathSelectors.any()) .build(); } /** * 创建该API的基本信息(这些基本信息会展现在文档页面中) * 访问地址:http://项目实际地址/swagger-ui.html * @return */ private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring Boot中使用Swagger2构建RESTful APIs") .description("更多请关注https://blog.csdn.net/u012373815") .termsOfServiceUrl("https://blog.csdn.net/u012373815") .contact("abel") .version("1.0") .build(); } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/bean/User.java ================================================ package com.abel.example.bean; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity @Table(name = "sec_user") public class User { @Id @GeneratedValue private Long id; @Column(name = "name") private String name; @Column(name = "password") private String password; @Column(name = "username") private String username; @Column(name = "email") private String email; @Column(name = "mobilephone") private String mobilephone; @Column(name = "telephone") private String telephone; @Column(name = "user_type") private Integer userType; @Column(name = "create_by") private String createBy; @Column(name = "create_time") private Date createTime; @Column(name = "update_by") private String updateBy; @Column(name = "update_time") private Date updateTime; @Column(name = "disabled") private Integer disabled; public String getName() { return name; } public void setName(String name) { this.name = name; } @JsonIgnore public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getMobilephone() { return mobilephone; } public void setMobilephone(String mobilephone) { this.mobilephone = mobilephone; } public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public Integer getUserType() { return userType; } public void setUserType(Integer userType) { this.userType = userType; } public String getCreateBy() { return createBy; } public void setCreateBy(String createBy) { this.createBy = createBy; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getUpdateBy() { return updateBy; } public void setUpdateBy(String updateBy) { this.updateBy = updateBy; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public Integer getDisabled() { return disabled; } public void setDisabled(Integer disabled) { this.disabled = disabled; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/config/DBConfig.java ================================================ package com.abel.example.config; import java.beans.PropertyVetoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import com.mchange.v2.c3p0.ComboPooledDataSource; @Configuration public class DBConfig { @Autowired private Environment env; @Bean(name="dataSource") public ComboPooledDataSource dataSource() throws PropertyVetoException { ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass(env.getProperty("ms.db.driverClassName")); dataSource.setJdbcUrl(env.getProperty("ms.db.url")); dataSource.setUser(env.getProperty("ms.db.username")); dataSource.setPassword(env.getProperty("ms.db.password")); dataSource.setMaxPoolSize(20); dataSource.setMinPoolSize(5); dataSource.setInitialPoolSize(10); dataSource.setMaxIdleTime(300); dataSource.setAcquireIncrement(5); dataSource.setIdleConnectionTestPeriod(60); return dataSource; } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/config/JpaConfig.java ================================================ package com.abel.example.config; import java.util.HashMap; import java.util.Map; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableJpaRepositories("com.abel.example.dao") @EnableTransactionManagement @ComponentScan public class JpaConfig { @Autowired private DataSource dataSource; @Bean public EntityManagerFactory entityManagerFactory() { HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); //vendorAdapter.setShowSql(true); //vendorAdapter.setGenerateDdl(true); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setPackagesToScan("com.abel.example.bean"); factory.setDataSource(dataSource); Map jpaProperties = new HashMap(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.jdbc.batch_size",50); //jpaProperties.put("hibernate.show_sql",true); factory.setJpaPropertyMap(jpaProperties); factory.afterPropertiesSet(); return factory.getObject(); } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory()); return txManager; } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/controller/UserController.java ================================================ package com.abel.example.controller; import javax.servlet.http.HttpServletRequest; import java.util.Map; import com.abel.example.bean.User; import io.swagger.annotations.*; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import com.abel.example.service.UserService; import com.abel.example.util.CommonUtil; @Controller @RequestMapping(value = "/users") @Api(value = "用户的增删改查") public class UserController { @Autowired private UserService userService; /** * 查询所有的用户 * api :localhost:8099/users * @return */ @RequestMapping(method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "获取用户列表,目前没有分页") public ResponseEntity findAll() { return new ResponseEntity<>(userService.listUsers(), HttpStatus.OK); } /** * 通过id 查找用户 * api :localhost:8099/users/1 * @param id * @return */ @RequestMapping(value = "/{id}", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "通过id获取用户信息", notes="返回用户信息") public ResponseEntity getUserById(@PathVariable Integer id) { return new ResponseEntity<>(userService.getUserById(Long.valueOf(id)), HttpStatus.OK); } /** * 通过spring data jpa 调用方法 * api :localhost:8099/users/byname?username=xxx * 通过用户名查找用户 * @param request * @return */ @RequestMapping(value = "/byname", method = RequestMethod.GET) @ResponseBody @ApiImplicitParam(paramType = "query",name= "username" ,value = "用户名",dataType = "string") @ApiOperation(value = "通过用户名获取用户信息", notes="返回用户信息") public ResponseEntity getUserByUserName(HttpServletRequest request) { Map map = CommonUtil.getParameterMap(request); String username = (String) map.get("username"); return new ResponseEntity<>(userService.getUserByUserName(username), HttpStatus.OK); } /** * 通过spring data jpa 调用方法 * api :localhost:8099/users/byUserNameContain?username=xxx * 通过用户名模糊查询 * @param request * @return */ @RequestMapping(value = "/byUserNameContain", method = RequestMethod.GET) @ResponseBody @ApiImplicitParam(paramType = "query",name= "username" ,value = "用户名",dataType = "string") @ApiOperation(value = "通过用户名模糊搜索用户信息", notes="返回用户信息") public ResponseEntity getUsers(HttpServletRequest request) { Map map = CommonUtil.getParameterMap(request); String username = (String) map.get("username"); return new ResponseEntity<>(userService.getByUsernameContaining(username), HttpStatus.OK); } /** * 添加用户啊 * api :localhost:8099/users * * @param user * @return */ @RequestMapping(method = RequestMethod.POST) @ResponseBody @ApiModelProperty(value="user",notes = "用户信息的json串") @ApiOperation(value = "新增用户", notes="返回新增的用户信息") public ResponseEntity saveUser(@RequestBody User user) { return new ResponseEntity<>(userService.saveUser(user), HttpStatus.OK); } /** * 修改用户信息 * api :localhost:8099/users * @param user * @return */ @RequestMapping(method = RequestMethod.PUT) @ResponseBody @ApiModelProperty(value="user",notes = "修改后用户信息的json串") @ApiOperation(value = "新增用户", notes="返回新增的用户信息") public ResponseEntity updateUser(@RequestBody User user) { return new ResponseEntity<>(userService.updateUser(user), HttpStatus.OK); } /** * 通过ID删除用户 * api :localhost:8099/users/2 * @param id * @return */ @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) @ResponseBody @ApiOperation(value = "通过id删除用户信息", notes="返回删除状态1 成功 0 失败") public ResponseEntity deleteUser(@PathVariable Integer id) { return new ResponseEntity<>(userService.removeUser(id.longValue()), HttpStatus.OK); } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/dao/UserJpaDao.java ================================================ package com.abel.example.dao; import org.springframework.data.jpa.repository.JpaRepository; import com.abel.example.bean.User; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.util.List; /** * The Interface UserJpaDao. * * @author abel */ public interface UserJpaDao extends JpaRepository { /** * Find by name. * * @param name the name * @return the user */ User findByName(String name); User getOne(Long id); List findByUsernameContaining(String username); User getByUsernameIs(String username); @Query("select s from User s where name like CONCAT('%',:name,'%')") List findByNameLike(@Param("name") String name); } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/service/UserService.java ================================================ package com.abel.example.service; import java.util.List; import com.abel.example.bean.User; /** * The Interface UserService. */ public interface UserService { /** * Gets the user by name. * * @param username the user name * @return the user by name */ public User getUserByUserName(String username); public List getByUsernameContaining(String username); /** * 增加学生 * @param user * @return */ User saveUser(User user); /** * 删除单个学生 * @param id * @return */ int removeUser(Long id); /** * 更新学生信息 * @param user * @return */ User updateUser(User user); /** * 根据id获取学生信息 * @param id * @return */ User getUserById(Long id); /** * 获取学生列表 * @return */ List listUsers(); } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/serviceImpl/UserServiceImpl.java ================================================ package com.abel.example.serviceImpl; import com.abel.example.bean.User; import com.abel.example.dao.UserJpaDao; import com.abel.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * @author abel * @ClassName UserServiceImpl * @date 2016年11月10日 */ @Service public class UserServiceImpl implements UserService { @Autowired private UserJpaDao userJpaDao; /** * @param username * @return */ @Override public User getUserByUserName(String username) { return userJpaDao.getByUsernameIs(username); } @Override public List getByUsernameContaining(String username) { return userJpaDao.findByUsernameContaining(username); } @Override public User saveUser(User user) { return userJpaDao.save(user); } @Override public int removeUser(Long id) { try { userJpaDao.delete(id); }catch (Exception e) { return 0; } return 1; } @Override public User updateUser(User user) { return userJpaDao.save(user); } @Override public User getUserById(Long id) { return userJpaDao.findOne(id); } @Override public List listUsers() { return userJpaDao.findAll(); } } ================================================ FILE: springboot-swagger-ui/src/main/java/com/abel/example/util/CommonUtil.java ================================================ package com.abel.example.util; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; public class CommonUtil { /** * 从request中获得参数Map,并返回可读的Map. * * @param request the request * @return the parameter map */ public static Map getParameterMap(HttpServletRequest request) { // 参数Map Map properties = request.getParameterMap(); //返回值Map Map returnMap = new HashMap(); Set keySet = properties.keySet(); for(String key: keySet){ String[] values = properties.get(key); String value = ""; if(values != null && (values.length==1&&StringUtils.isNotBlank(values[0]))?true:false){ for(int i=0;i