├── README.md ├── car_admin ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── chinawiserv │ │ └── admin │ │ ├── CarAdminApplication.java │ │ ├── config │ │ ├── DruidConfig.java │ │ ├── DruidDBConfig.java │ │ ├── WebMvcConfig.java │ │ └── security │ │ │ ├── CustomerAccessDeniedHandler.java │ │ │ ├── CustomerAuthenticationProvider.java │ │ │ ├── JwtAuthenticationEntryPoint.java │ │ │ ├── JwtAuthenticationRequest.java │ │ │ ├── JwtAuthenticationTokenFilter.java │ │ │ ├── JwtTokenUtil.java │ │ │ ├── JwtUser.java │ │ │ ├── JwtUserFactory.java │ │ │ ├── WebSecurityConfig.java │ │ │ ├── service │ │ │ ├── JwtAuthenticationResponse.java │ │ │ └── JwtUserDetailsServiceImpl.java │ │ │ ├── url │ │ │ ├── UrlAccessDecisionManager.java │ │ │ ├── UrlConfigAttribute.java │ │ │ ├── UrlFilterSecurityInterceptor.java │ │ │ ├── UrlGrantedAuthority.java │ │ │ └── UrlMetadataSourceService.java │ │ │ └── utils │ │ │ └── TimeProvider.java │ │ ├── controller │ │ ├── auth │ │ │ └── AuthenticationController.java │ │ ├── test │ │ │ ├── MethodProtectedRestController.java │ │ │ └── Person.java │ │ └── user │ │ │ └── UserController.java │ │ ├── mapper │ │ ├── PermissionMapper.java │ │ ├── UserMapper.java │ │ └── UserRoleMapper.java │ │ ├── model │ │ ├── Permission.java │ │ ├── User.java │ │ └── UserRole.java │ │ └── service │ │ └── sys │ │ ├── UserService.java │ │ └── UserServiceImpl.java │ └── resources │ ├── application-dev.properties │ ├── application-prod.properties │ ├── application-test.properties │ ├── application.properties │ ├── i18n │ ├── messages.properties │ ├── messages_en_US.properties │ └── messages_zh_CN.properties │ ├── logback-spring.xml │ ├── mapper │ └── UserMapper.xml │ ├── mybatis │ └── mybatis-config.xml │ ├── skcar.sql │ ├── static │ ├── index.html │ └── js │ │ ├── client.js │ │ └── libs │ │ └── jwt-decode.min.js │ └── system.properties ├── car_core ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── chinawiserv │ └── core │ ├── annotation │ └── Auth.java │ ├── constants │ └── Constants.java │ ├── dao │ └── mybatis │ │ ├── BaseMapper.java │ │ ├── SqlProvider.java │ │ └── interceptor │ │ ├── CameHumpInterceptor.java │ │ └── PerformanceInterceptor.java │ ├── enums │ ├── ErrorInfo.java │ ├── ErrorInfoEnum.java │ └── GlobalErrorInfoEnum.java │ ├── exception │ ├── ArtArtistTagException.java │ ├── GlobalErrorInfoException.java │ ├── UserLoginException.java │ └── WxException.java │ ├── handler │ └── GlobalErrorInfoHandler.java │ ├── model │ ├── BaseModel.java │ └── page │ │ └── BasePage.java │ ├── response │ ├── ResultBody.java │ └── ResultGenerator.java │ ├── service │ ├── BaseService.java │ └── IService.java │ ├── utils │ ├── MessageUtils.java │ └── SpringUtils.java │ └── web │ ├── controller │ ├── AbstarctBaseController.java │ ├── BaseCRUDController.java │ └── BaseController.java │ └── interceptor │ └── SetCommonDataInterceptor.java ├── car_utils ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── chinawiserv │ └── utils │ ├── AssertUtil.java │ ├── ConvertPercent.java │ ├── GoodsUpConditionUtils.java │ ├── IPUtils.java │ ├── JsonWebTokenUtility.java │ ├── MD5Util.java │ ├── OrderUtil.java │ ├── PropertyHelper.java │ ├── RamUtils.java │ ├── RandomUtils.java │ ├── ReflectUtils.java │ ├── TenpayUtil.java │ ├── arith │ └── Arith.java │ ├── bean │ └── MapUtils.java │ ├── data │ └── Uuid.java │ ├── date │ ├── DateUtil.java │ └── VeDate.java │ ├── encryption │ ├── Base64Util.java │ ├── EncryptionHelper.java │ └── MD5Utils.java │ ├── excel │ ├── DownloadDatas.java │ └── DownloadExcelUtils.java │ ├── io │ └── FileUtils.java │ ├── kaptcha │ └── KaptchaUtils.java │ ├── sensitive │ ├── SensitiveFilter.java │ ├── SensitiveNode.java │ └── StringPointer.java │ ├── thread │ ├── Sequence.java │ ├── TaskEntity.java │ ├── ThreadPool.java │ ├── ThreadTask.java │ └── ThreadUtil.java │ └── ztree │ └── ZtreeNode.java ├── data ├── ss1.jpeg ├── ss2.jpeg ├── ss3.jpeg ├── ss4.jpeg └── ss5.jpeg └── pom.xml /car_admin/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-security-with-jwt 5 | com.chinawiserv 6 | 0.0.1-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | car_admin 11 | war 12 | 13 | car_admin 14 | http://maven.apache.org 15 | 16 | 17 | 18 | com.chinawiserv 19 | car_core 20 | ${project.version} 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-security 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-mobile 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-validation 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-data-redis 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-cache 46 | 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-tomcat 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-starter-jdbc 59 | 60 | 61 | org.apache.tomcat 62 | tomcat-jdbc 63 | 64 | 65 | 66 | 67 | com.alibaba 68 | druid 69 | ${druid.version} 70 | 71 | 72 | 73 | mysql 74 | mysql-connector-java 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | dev 84 | 85 | true 86 | 87 | 88 | dev 89 | 90 | 91 | 92 | prod 93 | 94 | prod 95 | 96 | 97 | 98 | test 99 | 100 | test 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | src/main/resources 112 | 113 | 114 | src/main/resources 115 | true 116 | 117 | **/*.properties 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | org.springframework.boot 127 | spring-boot-maven-plugin 128 | 129 | true 130 | true 131 | 132 | true 133 | 134 | 135 | 136 | 137 | repackage 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | org.apache.maven.plugins 148 | maven-war-plugin 149 | 150 | false 151 | ${project.build.directory}/boot-mvc 152 | 153 | 154 | ${basedir}/lib 155 | WEB-INF/lib/ 156 | 157 | **/*.jar 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/CarAdminApplication.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin; 2 | 3 | import com.chinawiserv.core.utils.SpringUtils; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.mybatis.spring.annotation.MapperScan; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.builder.SpringApplicationBuilder; 9 | import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; 10 | import org.springframework.boot.web.support.SpringBootServletInitializer; 11 | import org.springframework.cache.annotation.EnableCaching; 12 | import org.springframework.context.ApplicationContext; 13 | import org.springframework.context.annotation.Bean; 14 | import org.springframework.context.annotation.ComponentScan; 15 | import org.springframework.context.annotation.PropertySource; 16 | import org.springframework.context.annotation.PropertySources; 17 | import org.springframework.web.cors.CorsConfiguration; 18 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 19 | import org.springframework.web.filter.CorsFilter; 20 | 21 | import java.util.Locale; 22 | 23 | /** 24 | * Created by sungang on 2017/8/19. 25 | */ 26 | @SpringBootApplication 27 | @PropertySources({ 28 | //默认配置 29 | @PropertySource("classpath:system.properties"), 30 | // tomcat目录下 31 | // @PropertySource(value = "file:${CATALINA_BASE}/system.properties", ignoreResourceNotFound = true), 32 | // @PropertySource(value = "file:${CATALINA_BASE}/wechat.properties", ignoreResourceNotFound = true), 33 | 34 | //${user.dir} 运行在项目同目录下 35 | // @PropertySource(value = "file:${user.dir}/system.properties", ignoreResourceNotFound = true), 36 | // @PropertySource(value = "file:${user.dir}/wechat.properties", ignoreResourceNotFound = true) 37 | }) 38 | @Slf4j 39 | //@EnableAspectJAutoProxy 40 | @MapperScan("com.chinawiserv.admin.mapper") 41 | @ComponentScan("com.chinawiserv") 42 | //开启 缓存 43 | @EnableCaching 44 | public class CarAdminApplication extends SpringBootServletInitializer { 45 | 46 | 47 | @Override 48 | protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { 49 | return builder.sources(CarAdminApplication.class); 50 | } 51 | 52 | /** 53 | * spring boot 服务主入口 54 | * 55 | * @param args 56 | */ 57 | public static void main(String[] args) { 58 | ApplicationContext context = SpringApplication.run(CarAdminApplication.class, args); 59 | if (context instanceof EmbeddedWebApplicationContext) { 60 | int port = ((EmbeddedWebApplicationContext) context).getEmbeddedServletContainer().getPort(); 61 | String contextPath = context.getApplicationName(); 62 | String url = String.format(Locale.SIMPLIFIED_CHINESE, "http://localhost:%d%s", port, contextPath); 63 | 64 | // log.info(" =========== 加载阿里支付数据 =========== "); 65 | // Configs.init("pay-alibaba.properties"); 66 | // log.info(" =========== 加载阿里支付数据 成功!=========== "); 67 | 68 | //提示项目用到的相关配置文件 69 | log.info(" =========== ${user.dir}={} =========== ", System.getProperty("user.dir")); 70 | log.info(" =========== ${java.io.tmpdir}={} =========== ", System.getProperty("java.io.tmpdir")); 71 | 72 | String dashes = "------------------------------------------------------------------------"; 73 | log.info("Access URLs:\n{}\n\tLocal: \t\t{}\n{}", dashes, url, dashes); 74 | 75 | } 76 | } 77 | 78 | 79 | @Bean 80 | public SpringUtils springUtilsBean() { 81 | return new SpringUtils(); 82 | } 83 | 84 | private CorsConfiguration buildConfig() { 85 | CorsConfiguration corsConfiguration = new CorsConfiguration(); 86 | corsConfiguration.addAllowedOrigin("*"); 87 | corsConfiguration.addAllowedHeader("*"); 88 | corsConfiguration.addAllowedMethod("*"); 89 | return corsConfiguration; 90 | } 91 | 92 | /** 93 | * 跨域过滤器 94 | * 95 | * @return 96 | */ 97 | @Bean 98 | public CorsFilter corsFilter() { 99 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 100 | source.registerCorsConfiguration("/**", buildConfig()); // 4 101 | return new CorsFilter(source); 102 | } 103 | } -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/DruidConfig.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config; 2 | 3 | import com.alibaba.druid.support.http.StatViewServlet; 4 | import com.alibaba.druid.support.http.WebStatFilter; 5 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 6 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | /** 11 | * 启动成功 12 | * 访问:http://ip:port/druid/login.html即可 13 | * 14 | * 注: 如果使用Spring Boot Admin 可能导致监控页面数据源加载失败 原因是因为 Druid 所在项目启动后没有连接到Admin Server服务导致 15 | * Created by sungang on 2016/12/15. 16 | */ 17 | @Configuration 18 | public class DruidConfig { 19 | 20 | @Bean 21 | public ServletRegistrationBean druidServlet() { 22 | ServletRegistrationBean reg = new ServletRegistrationBean(); 23 | reg.setServlet(new StatViewServlet()); 24 | reg.addUrlMappings("/druid/*"); 25 | //reg.addInitParameter("allow", "127.0.0.1"); //IP白名单 (没有配置或者为空,则允许所有访问) 26 | //reg.addInitParameter("deny",""); //IP黑名单 (存在共同时,deny优先于allow) 27 | reg.addInitParameter("loginUsername", "admin"); 28 | reg.addInitParameter("loginPassword", "admin"); 29 | reg.addInitParameter("resetEnable", "false");//禁用HTML页面上的“Reset All”功能 30 | return reg; 31 | } 32 | 33 | @Bean 34 | public FilterRegistrationBean filterRegistrationBean() { 35 | FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); 36 | filterRegistrationBean.setFilter(new WebStatFilter()); 37 | filterRegistrationBean.addUrlPatterns("/*"); //拦截地址 38 | filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); //不拦截地址 39 | return filterRegistrationBean; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/DruidDBConfig.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Primary; 10 | 11 | import javax.sql.DataSource; 12 | import java.sql.SQLException; 13 | 14 | /** 15 | * Created by sungang on 2017/4/6. 16 | */ 17 | @Configuration 18 | public class DruidDBConfig { 19 | 20 | private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class); 21 | 22 | @Value("${spring.datasource.url}") 23 | private String dbUrl; 24 | 25 | @Value("${spring.datasource.username}") 26 | private String username; 27 | 28 | @Value("${spring.datasource.password}") 29 | private String password; 30 | 31 | @Value("${spring.datasource.driverClassName}") 32 | private String driverClassName; 33 | 34 | @Value("${spring.datasource.initialSize}") 35 | private int initialSize; 36 | 37 | @Value("${spring.datasource.minIdle}") 38 | private int minIdle; 39 | 40 | @Value("${spring.datasource.maxActive}") 41 | private int maxActive; 42 | 43 | @Value("${spring.datasource.maxWait}") 44 | private int maxWait; 45 | 46 | @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") 47 | private int timeBetweenEvictionRunsMillis; 48 | 49 | @Value("${spring.datasource.minEvictableIdleTimeMillis}") 50 | private int minEvictableIdleTimeMillis; 51 | 52 | @Value("${spring.datasource.validationQuery}") 53 | private String validationQuery; 54 | 55 | @Value("${spring.datasource.testWhileIdle}") 56 | private boolean testWhileIdle; 57 | 58 | @Value("${spring.datasource.testOnBorrow}") 59 | private boolean testOnBorrow; 60 | 61 | @Value("${spring.datasource.testOnReturn}") 62 | private boolean testOnReturn; 63 | 64 | @Value("${spring.datasource.poolPreparedStatements}") 65 | private boolean poolPreparedStatements; 66 | 67 | @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") 68 | private int maxPoolPreparedStatementPerConnectionSize; 69 | 70 | @Value("${spring.datasource.filters}") 71 | private String filters; 72 | 73 | @Value("{spring.datasource.connectionProperties}") 74 | private String connectionProperties; 75 | 76 | @Bean //声明其为Bean实例 77 | // @Primary表示这里定义的DataSource将覆盖其他来源的DataSource 78 | @Primary //在同样的DataSource中,首先使用被标注的DataSource 79 | public DataSource dataSource(){ 80 | DruidDataSource datasource = new DruidDataSource(); 81 | 82 | datasource.setUrl(this.dbUrl); 83 | datasource.setUsername(username); 84 | datasource.setPassword(password); 85 | datasource.setDriverClassName(driverClassName); 86 | 87 | //configuration 88 | datasource.setInitialSize(initialSize); 89 | datasource.setMinIdle(minIdle); 90 | datasource.setMaxActive(maxActive); 91 | datasource.setMaxWait(maxWait); 92 | datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 93 | datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 94 | datasource.setValidationQuery(validationQuery); 95 | datasource.setTestWhileIdle(testWhileIdle); 96 | datasource.setTestOnBorrow(testOnBorrow); 97 | datasource.setTestOnReturn(testOnReturn); 98 | datasource.setPoolPreparedStatements(poolPreparedStatements); 99 | datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); 100 | try { 101 | datasource.setFilters(filters); 102 | } catch (SQLException e) { 103 | logger.error("druid configuration initialization filter", e); 104 | } 105 | datasource.setConnectionProperties(connectionProperties); 106 | 107 | return datasource; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.http.converter.HttpMessageConverter; 7 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 8 | import org.springframework.web.servlet.config.annotation.*; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by sungang on 2016/12/15. 15 | */ 16 | @Configuration 17 | public class WebMvcConfig extends WebMvcConfigurerAdapter { 18 | @Override 19 | public void extendMessageConverters(List> converters) { 20 | converters.add(jackson2HttpMessageConverter()); 21 | } 22 | 23 | @Bean 24 | public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() { 25 | //set HTTP Message converter using a JSON implementation. 26 | MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter(); 27 | // Add supported media type returned by BI API. 28 | List supportedMediaTypes = new ArrayList(); 29 | supportedMediaTypes.add(new MediaType("text", "plain")); 30 | supportedMediaTypes.add(new MediaType("application", "json")); 31 | jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes); 32 | return jsonMessageConverter; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/CustomerAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.security.access.AccessDeniedException; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.security.web.access.AccessDeniedHandler; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * handle 403 page 17 | *

18 | * Created by sungang on 2017/10/24. 19 | */ 20 | @Component 21 | @Slf4j 22 | public class CustomerAccessDeniedHandler implements AccessDeniedHandler { 23 | 24 | @Override 25 | public void handle(HttpServletRequest httpServletRequest, 26 | HttpServletResponse httpServletResponse, 27 | AccessDeniedException e) throws IOException, ServletException { 28 | 29 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 30 | if (auth != null) { 31 | log.info("用户: '" + auth.getName() 32 | + " 无权限访问URL : " 33 | + httpServletRequest.getRequestURI()); 34 | } 35 | httpServletResponse.setStatus(403); 36 | httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/api/login/403?url=" + httpServletRequest.getMethod() + "路径>>" + httpServletRequest.getRequestURI()); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/CustomerAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import com.chinawiserv.admin.config.security.service.JwtUserDetailsServiceImpl; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.authentication.AuthenticationProvider; 7 | import org.springframework.security.authentication.BadCredentialsException; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.core.AuthenticationException; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * Created by sungang on 2017/10/24. 16 | */ 17 | @Component 18 | @Slf4j 19 | public class CustomerAuthenticationProvider implements AuthenticationProvider { 20 | @Autowired 21 | private JwtUserDetailsServiceImpl userDetailsService; 22 | @Override 23 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 24 | log.info("用户输入的用户名是:{}", authentication.getName()); 25 | log.info("用户输入的密码是:{}", authentication.getCredentials()); 26 | // 根据用户输入的用户名获取该用户名已经在服务器上存在的用户详情,如果没有则返回null 27 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(authentication.getName()); 28 | try { 29 | log.info("服务器上已经保存的用户名是:" + userDetails.getUsername()); 30 | log.info("服务器上保存的该用户名对应的密码是: " + userDetails.getPassword()); 31 | log.info("服务器上保存的该用户对应的权限是:" + userDetails.getAuthorities()); 32 | //判断用户输入的密码和服务器上已经保存的密码是否一致 33 | if (authentication.getCredentials().equals(userDetails.getPassword())) { 34 | log.info("认证成功!"); 35 | //如果验证通过,将返回一个UsernamePasswordAuthenticaionToken对象 36 | return new UsernamePasswordAuthenticationToken(userDetails, authentication.getCredentials(), userDetails.getAuthorities()); 37 | }else{ 38 | log.warn("认证失败, 密码输入不正确!"); 39 | new BadCredentialsException("认证失败, 密码输入不正确!"); 40 | } 41 | } catch (Exception e) { 42 | log.error("认证失败, error message is: " , e); 43 | throw e; 44 | } 45 | //如果验证不通过将抛出异常或者返回null 46 | return null; 47 | } 48 | 49 | 50 | 51 | //告诉身份验证的功能只能使用UsernamePasswordAuthenticationToken对象。 52 | @Override 53 | public boolean supports(Class authentication) { 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.AuthenticationEntryPoint; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.Serializable; 11 | 12 | @Component 13 | public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { 14 | 15 | private static final long serialVersionUID = -8970718410437077606L; 16 | 17 | @Override 18 | public void commence(HttpServletRequest request, 19 | HttpServletResponse response, 20 | AuthenticationException authException) throws IOException { 21 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 22 | } 23 | } -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtAuthenticationRequest.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by stephan on 20.03.16. 7 | */ 8 | public class JwtAuthenticationRequest implements Serializable { 9 | 10 | private static final long serialVersionUID = -8445943548965154778L; 11 | 12 | private String username; 13 | private String password; 14 | 15 | public JwtAuthenticationRequest() { 16 | super(); 17 | } 18 | 19 | public JwtAuthenticationRequest(String username, String password) { 20 | this.setUsername(username); 21 | this.setPassword(password); 22 | } 23 | 24 | public String getUsername() { 25 | return this.username; 26 | } 27 | 28 | public void setUsername(String username) { 29 | this.username = username; 30 | } 31 | 32 | public String getPassword() { 33 | return this.password; 34 | } 35 | 36 | public void setPassword(String password) { 37 | this.password = password; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.FilterChain; 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 15 | import org.springframework.security.core.context.SecurityContextHolder; 16 | import org.springframework.security.core.userdetails.UserDetails; 17 | import org.springframework.security.core.userdetails.UserDetailsService; 18 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 19 | import org.springframework.web.filter.OncePerRequestFilter; 20 | 21 | /** 22 | * 首先会去到 OncePerRequestFilter 类的 doFilter 方法,执行doFilterInternal 方法 23 | */ 24 | @Slf4j 25 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 26 | 27 | @Autowired 28 | private UserDetailsService userDetailsService; 29 | 30 | @Autowired 31 | private JwtTokenUtil jwtTokenUtil; 32 | 33 | @Value("${jwt.header}") 34 | private String tokenHeader; 35 | 36 | @Override 37 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { 38 | String authToken = request.getHeader(this.tokenHeader); 39 | String username; 40 | try { 41 | username = jwtTokenUtil.getUsernameFromToken(authToken); 42 | } catch (IllegalArgumentException e) { 43 | username = null; 44 | } 45 | log.info("验证 authentication für user:{} " , username); 46 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 47 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 48 | if (jwtTokenUtil.validateToken(authToken, userDetails)) { 49 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 50 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 51 | log.info("认证用户: " + username + ", 设置 Security Context"); 52 | SecurityContextHolder.getContext().setAuthentication(authentication); 53 | } 54 | } 55 | chain.doFilter(request, response); 56 | } 57 | } -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtTokenUtil.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import com.chinawiserv.admin.config.security.utils.TimeProvider; 4 | import io.jsonwebtoken.Claims; 5 | import io.jsonwebtoken.Jwts; 6 | import io.jsonwebtoken.SignatureAlgorithm; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.mobile.device.Device; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.io.Serializable; 14 | import java.util.Date; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import java.util.function.Function; 18 | 19 | @Component 20 | public class JwtTokenUtil implements Serializable { 21 | 22 | private static final long serialVersionUID = -3301605591108950415L; 23 | 24 | static final String CLAIM_KEY_USERNAME = "sub"; 25 | static final String CLAIM_KEY_AUDIENCE = "aud"; 26 | static final String CLAIM_KEY_CREATED = "iat"; 27 | 28 | static final String AUDIENCE_UNKNOWN = "unknown"; 29 | static final String AUDIENCE_WEB = "web"; 30 | static final String AUDIENCE_MOBILE = "mobile"; 31 | static final String AUDIENCE_TABLET = "tablet"; 32 | 33 | @Autowired 34 | private TimeProvider timeProvider; 35 | 36 | @Value("${jwt.secret}") 37 | private String secret; 38 | 39 | @Value("${jwt.expiration}") 40 | private Long expiration; 41 | 42 | public String getUsernameFromToken(String token) { 43 | return getClaimFromToken(token, Claims::getSubject); 44 | } 45 | 46 | public Date getIssuedAtDateFromToken(String token) { 47 | return getClaimFromToken(token, Claims::getIssuedAt); 48 | } 49 | 50 | public Date getExpirationDateFromToken(String token) { 51 | return getClaimFromToken(token, Claims::getExpiration); 52 | } 53 | 54 | public String getAudienceFromToken(String token) { 55 | return getClaimFromToken(token, Claims::getAudience); 56 | } 57 | 58 | public T getClaimFromToken(String token, Function claimsResolver) { 59 | final Claims claims = getAllClaimsFromToken(token); 60 | return claimsResolver.apply(claims); 61 | } 62 | 63 | private Claims getAllClaimsFromToken(String token) { 64 | return Jwts.parser() 65 | .setSigningKey(secret) 66 | .parseClaimsJws(token) 67 | .getBody(); 68 | } 69 | 70 | private Boolean isTokenExpired(String token) { 71 | final Date expiration = getExpirationDateFromToken(token); 72 | return expiration.before(timeProvider.now()); 73 | } 74 | 75 | private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) { 76 | return (lastPasswordReset != null && created.before(lastPasswordReset)); 77 | } 78 | 79 | private String generateAudience(Device device) { 80 | String audience = AUDIENCE_UNKNOWN; 81 | if (device.isNormal()) { 82 | audience = AUDIENCE_WEB; 83 | } else if (device.isTablet()) { 84 | audience = AUDIENCE_TABLET; 85 | } else if (device.isMobile()) { 86 | audience = AUDIENCE_MOBILE; 87 | } 88 | return audience; 89 | } 90 | 91 | private Boolean ignoreTokenExpiration(String token) { 92 | String audience = getAudienceFromToken(token); 93 | return (AUDIENCE_TABLET.equals(audience) || AUDIENCE_MOBILE.equals(audience)); 94 | } 95 | 96 | public String generateToken(UserDetails userDetails, Device device) { 97 | Map claims = new HashMap<>(); 98 | return doGenerateToken(claims, userDetails.getUsername(), generateAudience(device)); 99 | } 100 | 101 | private String doGenerateToken(Map claims, String subject, String audience) { 102 | final Date createdDate = timeProvider.now(); 103 | final Date expirationDate = new Date(createdDate.getTime() + expiration * 1000); 104 | 105 | System.out.println("doGenerateToken " + createdDate); 106 | 107 | return Jwts.builder() 108 | .setClaims(claims) 109 | .setSubject(subject) 110 | .setAudience(audience) 111 | .setIssuedAt(createdDate) 112 | .setExpiration(expirationDate) 113 | .signWith(SignatureAlgorithm.HS512, secret) 114 | .compact(); 115 | } 116 | 117 | public Boolean canTokenBeRefreshed(String token, Date lastPasswordReset) { 118 | final Date created = getIssuedAtDateFromToken(token); 119 | return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset) 120 | && (!isTokenExpired(token) || ignoreTokenExpiration(token)); 121 | } 122 | 123 | public String refreshToken(String token) { 124 | final Claims claims = getAllClaimsFromToken(token); 125 | claims.setIssuedAt(timeProvider.now()); 126 | return doRefreshToken(claims); 127 | } 128 | 129 | public String doRefreshToken(Claims claims) { 130 | return Jwts.builder() 131 | .setClaims(claims) 132 | .signWith(SignatureAlgorithm.HS512, secret) 133 | .compact(); 134 | } 135 | 136 | public Boolean validateToken(String token, UserDetails userDetails) { 137 | JwtUser user = (JwtUser) userDetails; 138 | final String username = getUsernameFromToken(token); 139 | final Date created = getIssuedAtDateFromToken(token); 140 | //final Date expiration = getExpirationDateFromToken(token); 141 | return ( 142 | username.equals(user.getUsername()) 143 | && !isTokenExpired(token) 144 | && !isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())); 145 | } 146 | } -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtUser.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import java.util.Collection; 4 | import java.util.Date; 5 | 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | 9 | import com.fasterxml.jackson.annotation.JsonIgnore; 10 | 11 | /** 12 | * Created by stephan on 20.03.16. 13 | */ 14 | public class JwtUser implements UserDetails { 15 | 16 | 17 | private final Long id; 18 | private final String username; 19 | private final String password; 20 | private final String email; 21 | private final Collection authorities; 22 | private final boolean enabled; 23 | private final Date lastPasswordResetDate; 24 | 25 | public JwtUser(Long id, String username, String password, String email, boolean enabled, Collection authorities, Date lastPasswordResetDate) { 26 | this.id = id; 27 | this.username = username; 28 | this.email = email; 29 | this.password = password; 30 | this.enabled = enabled; 31 | this.authorities = authorities; 32 | this.lastPasswordResetDate = lastPasswordResetDate; 33 | } 34 | 35 | @JsonIgnore 36 | public Long getId() { 37 | return id; 38 | } 39 | 40 | @Override 41 | public String getUsername() { 42 | return username; 43 | } 44 | 45 | @JsonIgnore 46 | @Override 47 | public boolean isAccountNonExpired() { 48 | return true; 49 | } 50 | 51 | @JsonIgnore 52 | @Override 53 | public boolean isAccountNonLocked() { 54 | return true; 55 | } 56 | 57 | @JsonIgnore 58 | @Override 59 | public boolean isCredentialsNonExpired() { 60 | return true; 61 | } 62 | 63 | public String getEmail() { 64 | return email; 65 | } 66 | 67 | @JsonIgnore 68 | @Override 69 | public String getPassword() { 70 | return password; 71 | } 72 | 73 | @Override 74 | public boolean isEnabled() { 75 | return enabled; 76 | } 77 | 78 | @Override 79 | public Collection getAuthorities() { 80 | return authorities; 81 | } 82 | 83 | @JsonIgnore 84 | public Date getLastPasswordResetDate() { 85 | return lastPasswordResetDate; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/JwtUserFactory.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import com.chinawiserv.admin.config.security.url.UrlGrantedAuthority; 7 | import com.chinawiserv.admin.model.Permission; 8 | import com.chinawiserv.admin.model.User; 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | 12 | public final class JwtUserFactory { 13 | 14 | private JwtUserFactory() { 15 | } 16 | 17 | public static JwtUser create(User user) { 18 | return new JwtUser( 19 | user.getId(), 20 | user.getUsername(), 21 | user.getPassword(), 22 | user.getEmail(), 23 | user.getStatus() == 0 ? false : true, 24 | mapToGrantedAuthorities(user.getAuthorities()), 25 | user.getLastPasswordResetDate() 26 | ); 27 | } 28 | 29 | private static List mapToGrantedAuthorities(List authorities) { 30 | return authorities.stream().map(authority -> new UrlGrantedAuthority(authority.getName(),authority.getPermissionUrl(), authority.getMethod())).collect(Collectors.toList()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security; 2 | 3 | import com.chinawiserv.utils.encryption.EncryptionHelper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.http.HttpMethod; 8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 9 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | import org.springframework.security.config.http.SessionCreationPolicy; 14 | import org.springframework.security.core.userdetails.UserDetailsService; 15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 16 | import org.springframework.security.crypto.password.PasswordEncoder; 17 | import org.springframework.security.web.access.AccessDeniedHandler; 18 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 19 | 20 | /** 21 | * Created by sungang on 2017/8/19. 22 | */ 23 | @SuppressWarnings("SpringJavaAutowiringInspection") 24 | @Configuration 25 | @EnableWebSecurity 26 | @EnableGlobalMethodSecurity(prePostEnabled = true) 27 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 28 | 29 | /** 30 | * 自定义 31 | */ 32 | @Autowired 33 | private CustomerAuthenticationProvider authProvider; 34 | 35 | @Autowired 36 | private JwtAuthenticationEntryPoint unauthorizedHandler; 37 | 38 | @Autowired 39 | private CustomerAccessDeniedHandler customerAccessDeniedHandler; 40 | 41 | // Spring会自动寻找同样类型的具体类注入,这里就是JwtUserDetailsServiceImpl了 42 | @Autowired 43 | private UserDetailsService userDetailsService; 44 | 45 | 46 | // @Autowired 47 | // public void configureAuthentication(AuthenticationManagerBuilder auth) throws Exception { 48 | // auth.authenticationProvider(authProvider) 49 | // // 设置UserDetailsService 50 | // .userDetailsService(this.userDetailsService) 51 | // // 使用BCrypt进行密码的hash 52 | // .passwordEncoder(passwordEncoder()); 53 | // 54 | // } 55 | 56 | @Autowired 57 | public void configureAuthentication(AuthenticationManagerBuilder auth) throws Exception { 58 | auth/*.authenticationProvider(authenticationProvider)*/ 59 | // 设置UserDetailsService 60 | .userDetailsService(this.userDetailsService) 61 | // 使用BCrypt进行密码的hash 62 | .passwordEncoder(passwordEncoder()); 63 | 64 | } 65 | // 装载BCrypt密码编码器 66 | // @Bean 67 | // public PasswordEncoder passwordEncoder() { 68 | // return new BCryptPasswordEncoder(); 69 | // } 70 | 71 | // 装载 密码编码器 72 | @Bean 73 | public PasswordEncoder passwordEncoder() { 74 | return new PasswordEncoder() { 75 | @Override 76 | public String encode(CharSequence rawPassword) { 77 | return EncryptionHelper.encrypt((String) rawPassword); 78 | } 79 | 80 | @Override 81 | public boolean matches(CharSequence rawPassword, String encodedPassword) { 82 | return encodedPassword.equals(EncryptionHelper.encrypt((String) rawPassword)); 83 | } 84 | }; 85 | } 86 | 87 | // @Bean 88 | // public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { 89 | // return new JwtAuthenticationTokenFilter(); 90 | // } 91 | 92 | @Override 93 | protected void configure(HttpSecurity httpSecurity) throws Exception { 94 | httpSecurity 95 | //由于使用的是JWT,我们这里不需要csrf 96 | .csrf().disable() 97 | .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() 98 | // 99 | .exceptionHandling().accessDeniedHandler(customerAccessDeniedHandler).and() 100 | // 基于token,所以不需要session 101 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 102 | .authorizeRequests() 103 | //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 104 | // 允许对于网站静态资源的无授权访问 105 | .antMatchers( 106 | HttpMethod.GET, 107 | "/", 108 | "/*.html", 109 | "/favicon.ico", 110 | "/**/*.html", 111 | "/**/*.css", 112 | "/**/*.js" 113 | ).permitAll() 114 | // 对于获取token的rest api要允许匿名访问 115 | .antMatchers("/api/login/**").permitAll() 116 | // 除上面外的所有请求全部需要鉴权认证 117 | .anyRequest().authenticated(); 118 | 119 | // Custom JWT based security filter 120 | httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); 121 | 122 | // 禁用缓存 123 | httpSecurity.headers().cacheControl(); 124 | } 125 | 126 | 127 | @Bean 128 | public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception { 129 | return new JwtAuthenticationTokenFilter(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/service/JwtAuthenticationResponse.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.service; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by stephan on 20.03.16. 7 | */ 8 | public class JwtAuthenticationResponse implements Serializable { 9 | 10 | private static final long serialVersionUID = 1250166508152483573L; 11 | 12 | private final String token; 13 | 14 | public JwtAuthenticationResponse(String token) { 15 | this.token = token; 16 | } 17 | 18 | public String getToken() { 19 | return this.token; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/service/JwtUserDetailsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.service; 2 | 3 | import com.chinawiserv.admin.config.security.JwtUser; 4 | import com.chinawiserv.admin.config.security.JwtUserFactory; 5 | import com.chinawiserv.admin.mapper.UserMapper; 6 | import com.chinawiserv.admin.model.User; 7 | import com.chinawiserv.core.service.BaseService; 8 | import com.google.common.collect.Maps; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.data.redis.core.RedisTemplate; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.Map; 17 | 18 | /** 19 | * Created by stephan on 20.03.16. 20 | */ 21 | @Service 22 | public class JwtUserDetailsServiceImpl extends BaseService implements UserDetailsService { 23 | 24 | @Autowired 25 | private UserMapper userMapper; 26 | 27 | 28 | @Autowired 29 | private RedisTemplate redisTemplate; 30 | 31 | @Override 32 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 33 | 34 | 35 | Map params = Maps.newHashMap(); 36 | params.put("userName", username); 37 | User user = userMapper.selectUserAndAuthorities(params); 38 | if (user == null) { 39 | throw new UsernameNotFoundException(String.format("No user found with username '%s'.", username)); 40 | } else { 41 | JwtUser userDetail = JwtUserFactory.create(user); 42 | return userDetail; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/url/UrlAccessDecisionManager.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.url; 2 | 3 | import org.springframework.security.access.AccessDecisionManager; 4 | import org.springframework.security.access.AccessDeniedException; 5 | import org.springframework.security.access.ConfigAttribute; 6 | import org.springframework.security.authentication.InsufficientAuthenticationException; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.web.FilterInvocation; 10 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 11 | import org.springframework.stereotype.Service; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.util.Collection; 15 | 16 | /** 17 | * Created by sungang on 2017/10/24. 18 | */ 19 | @Service 20 | public class UrlAccessDecisionManager implements AccessDecisionManager { 21 | 22 | 23 | @Override 24 | public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { 25 | HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); 26 | String url, method; 27 | Object principal = authentication.getPrincipal(); 28 | if ("anonymousUser".equals(principal) 29 | || matchers("/images/**", request) 30 | || matchers("/js/**", request) 31 | || matchers("/css/**", request) 32 | || matchers("/fonts/**", request) 33 | || matchers("/api/", request) 34 | || matchers("/index.html", request) 35 | || matchers("/favicon.ico", request) 36 | || matchers("/api/login/**", request)) { 37 | return; 38 | } else { 39 | for (GrantedAuthority ga : authentication.getAuthorities()) { 40 | if (ga instanceof UrlGrantedAuthority) { 41 | UrlGrantedAuthority urlGrantedAuthority = (UrlGrantedAuthority) ga; 42 | url = urlGrantedAuthority.getPermissionUrl(); 43 | method = urlGrantedAuthority.getMethod(); 44 | if (matchers(url, request)) { 45 | if (method.equals(request.getMethod()) || "ALL".equals(method)) { 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | } 52 | throw new AccessDeniedException("没有权限!"); 53 | } 54 | 55 | 56 | @Override 57 | public boolean supports(ConfigAttribute attribute) { 58 | return true; 59 | } 60 | 61 | @Override 62 | public boolean supports(Class clazz) { 63 | return true; 64 | } 65 | 66 | 67 | private boolean matchers(String url, HttpServletRequest request) { 68 | AntPathRequestMatcher matcher = new AntPathRequestMatcher(url); 69 | if (matcher.matches(request)) { 70 | return true; 71 | } 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/url/UrlConfigAttribute.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.url; 2 | 3 | import org.springframework.security.access.ConfigAttribute; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | /** 8 | * Created by sungang on 2017/10/24. 9 | */ 10 | 11 | public class UrlConfigAttribute implements ConfigAttribute { 12 | 13 | private final HttpServletRequest httpServletRequest; 14 | 15 | public UrlConfigAttribute(HttpServletRequest httpServletRequest) { 16 | this.httpServletRequest = httpServletRequest; 17 | } 18 | 19 | 20 | @Override 21 | public String getAttribute() { 22 | return null; 23 | } 24 | 25 | public HttpServletRequest getHttpServletRequest() { 26 | return httpServletRequest; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/url/UrlFilterSecurityInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.url; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.access.SecurityMetadataSource; 5 | import org.springframework.security.access.intercept.AbstractSecurityInterceptor; 6 | import org.springframework.security.access.intercept.InterceptorStatusToken; 7 | import org.springframework.security.web.FilterInvocation; 8 | import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.servlet.*; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Created by sungang on 2017/10/24. 16 | */ 17 | @Service 18 | public class UrlFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { 19 | @Autowired 20 | private FilterInvocationSecurityMetadataSource securityMetadataSource; 21 | 22 | @Autowired 23 | public void setUrlAccessDecisionManager(UrlAccessDecisionManager urlAccessDecisionManager) { 24 | super.setAccessDecisionManager(urlAccessDecisionManager); 25 | } 26 | 27 | 28 | @Override 29 | public void init(FilterConfig filterConfig) throws ServletException { 30 | 31 | } 32 | 33 | @Override 34 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 35 | 36 | FilterInvocation fi = new FilterInvocation(request, response, chain); 37 | invoke(fi); 38 | } 39 | 40 | 41 | public void invoke(FilterInvocation fi) throws IOException, ServletException { 42 | //fi里面有一个被拦截的url 43 | //里面调用UrlMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 44 | //再调用UrlAccessDecisionManager的decide方法来校验用户的权限是否足够 45 | InterceptorStatusToken token = super.beforeInvocation(fi); 46 | try { 47 | //执行下一个拦截器 48 | fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); 49 | } finally { 50 | super.afterInvocation(token, null); 51 | } 52 | } 53 | 54 | 55 | @Override 56 | public void destroy() { 57 | 58 | } 59 | 60 | @Override 61 | public Class getSecureObjectClass() { 62 | return FilterInvocation.class; 63 | 64 | } 65 | 66 | @Override 67 | public SecurityMetadataSource obtainSecurityMetadataSource() { 68 | return this.securityMetadataSource; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/url/UrlGrantedAuthority.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.url; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import org.springframework.security.core.GrantedAuthority; 6 | 7 | /** 8 | * Created by sungang on 2017/10/24. 9 | */ 10 | @Data 11 | @AllArgsConstructor 12 | public class UrlGrantedAuthority implements GrantedAuthority { 13 | 14 | private String name; 15 | private String permissionUrl; 16 | private String method; 17 | 18 | 19 | @Override 20 | public String getAuthority() { 21 | return this.name + ";" + this.permissionUrl + ";" + this.method; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/url/UrlMetadataSourceService.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.url; 2 | 3 | import org.springframework.security.access.ConfigAttribute; 4 | import org.springframework.security.web.FilterInvocation; 5 | import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import java.util.Collection; 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | 14 | /** 15 | * Created by sungang on 2017/10/24. 16 | */ 17 | @Service 18 | public class UrlMetadataSourceService implements FilterInvocationSecurityMetadataSource { 19 | 20 | 21 | @Override 22 | public Collection getAttributes(Object object) throws IllegalArgumentException { 23 | final HttpServletRequest request = ((FilterInvocation) object).getRequest(); 24 | Set allAttributes = new HashSet<>(); 25 | ConfigAttribute configAttribute = new UrlConfigAttribute(request); 26 | allAttributes.add(configAttribute); 27 | return allAttributes; 28 | } 29 | 30 | @Override 31 | public Collection getAllConfigAttributes() { 32 | return null; 33 | } 34 | 35 | @Override 36 | public boolean supports(Class clazz) { 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/config/security/utils/TimeProvider.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.config.security.utils; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * Created by stephan on 04.07.17. 10 | */ 11 | @Component 12 | public class TimeProvider implements Serializable { 13 | 14 | private static final long serialVersionUID = -3301695478208950415L; 15 | 16 | public Date now() { 17 | return new Date(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/controller/auth/AuthenticationController.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.controller.auth; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.chinawiserv.admin.config.security.JwtAuthenticationRequest; 5 | import com.chinawiserv.admin.config.security.JwtTokenUtil; 6 | import com.chinawiserv.admin.config.security.JwtUser; 7 | import com.chinawiserv.admin.mapper.UserMapper; 8 | import com.chinawiserv.admin.mapper.UserRoleMapper; 9 | import com.chinawiserv.admin.model.User; 10 | import com.chinawiserv.admin.model.UserRole; 11 | import com.chinawiserv.core.enums.GlobalErrorInfoEnum; 12 | import com.chinawiserv.core.exception.GlobalErrorInfoException; 13 | import com.chinawiserv.core.response.ResultBody; 14 | import com.chinawiserv.core.response.ResultGenerator; 15 | import com.google.common.collect.Maps; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.beans.factory.annotation.Value; 18 | import org.springframework.data.redis.core.RedisTemplate; 19 | import org.springframework.mobile.device.Device; 20 | import org.springframework.security.authentication.AuthenticationManager; 21 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 22 | import org.springframework.security.core.Authentication; 23 | import org.springframework.security.core.AuthenticationException; 24 | import org.springframework.security.core.context.SecurityContextHolder; 25 | import org.springframework.security.core.userdetails.UserDetails; 26 | import org.springframework.security.core.userdetails.UserDetailsService; 27 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 28 | import org.springframework.web.bind.annotation.*; 29 | 30 | import javax.servlet.http.HttpServletRequest; 31 | import javax.servlet.http.HttpServletResponse; 32 | import java.util.Date; 33 | import java.util.Map; 34 | 35 | /** 36 | * Created by sungang on 2017/10/24. 37 | */ 38 | @RestController 39 | @RequestMapping("/api/login") 40 | public class AuthenticationController { 41 | 42 | 43 | @Value("${jwt.header}") 44 | private String tokenHeader; 45 | 46 | @Autowired 47 | private JwtTokenUtil jwtTokenUtil; 48 | 49 | @Autowired 50 | private UserDetailsService userDetailsService; 51 | 52 | @Autowired 53 | private UserRoleMapper userRoleMapper; 54 | @Autowired 55 | private UserMapper userMapper; 56 | 57 | @Autowired 58 | private RedisTemplate redisTemplate; 59 | 60 | 61 | /** 62 | * 63 | * @param userToAdd 64 | * @return 65 | * @throws GlobalErrorInfoException 66 | */ 67 | @PostMapping("register") 68 | public ResultBody register(User userToAdd) throws GlobalErrorInfoException { 69 | final String username = userToAdd.getUsername(); 70 | Map params = Maps.newHashMap(); 71 | params.put("userName", username); 72 | if (userMapper.selectUserAndAuthorities(params) != null) { 73 | return ResultGenerator.genFailResult(GlobalErrorInfoEnum.INTERNAL_SERVER_ERROR.getCode(),"改用户名已经存在!"); 74 | } 75 | BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 76 | final String rawPassword = userToAdd.getPassword(); 77 | userToAdd.setPassword(encoder.encode(rawPassword)); 78 | userToAdd.setLastPasswordResetDate(new Date()); 79 | userToAdd.setEmail(""); 80 | userToAdd.setStatus(1); 81 | userMapper.insert(userToAdd); 82 | 83 | 84 | /** 85 | * 用户角色关系 86 | */ 87 | UserRole userRole = new UserRole(); 88 | userRole.setRoleId(userToAdd.getRoleId()); 89 | userRole.setUserId(userToAdd.getId()); 90 | userRoleMapper.insert(userRole); 91 | 92 | 93 | return ResultGenerator.genSuccessResult(); 94 | } 95 | 96 | 97 | 98 | @Autowired 99 | private AuthenticationManager authenticationManager; 100 | @PostMapping 101 | public ResultBody createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException { 102 | UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(authenticationRequest.getUsername(), authenticationRequest.getPassword()); 103 | final Authentication authentication = authenticationManager.authenticate(upToken); 104 | SecurityContextHolder.getContext().setAuthentication(authentication); 105 | final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername()); 106 | final String token = jwtTokenUtil.generateToken(userDetails, device); 107 | 108 | // Return the token 109 | JSONObject res = new JSONObject(); 110 | res.put("access_token",token); 111 | res.put("authorities",userDetails.getAuthorities()); 112 | return ResultGenerator.genSuccessResult(res); 113 | } 114 | 115 | 116 | 117 | @RequestMapping("403") 118 | public ResultBody access403(String url, HttpServletResponse response) throws AuthenticationException { 119 | response.setStatus(403); 120 | return ResultGenerator.genFailResult(GlobalErrorInfoEnum.INTERNAL_SERVER_ERROR.getCode(),"没有权限访问:" + url); 121 | } 122 | 123 | /** 124 | * @param request 125 | * @return 126 | */ 127 | @GetMapping(value = "refresh") 128 | public ResultBody refreshAndGetAuthenticationToken(HttpServletRequest request) { 129 | String token = request.getHeader(tokenHeader); 130 | String username = jwtTokenUtil.getUsernameFromToken(token); 131 | JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username); 132 | 133 | if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())) { 134 | String refreshedToken = jwtTokenUtil.refreshToken(token); 135 | return ResultGenerator.genSuccessResult(refreshedToken); 136 | } else { 137 | return ResultGenerator.genSuccessResult(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/controller/test/MethodProtectedRestController.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.controller.test; 2 | 3 | import org.springframework.http.ResponseEntity; 4 | import org.springframework.security.access.prepost.PreAuthorize; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RequestMethod; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | @RequestMapping("api/protected") 11 | public class MethodProtectedRestController { 12 | 13 | /** 14 | * ADMIN 角色 15 | **/ 16 | @RequestMapping(method = RequestMethod.GET) 17 | public ResponseEntity getProtectedGreeting() { 18 | return ResponseEntity.ok("来自管理员的请求响应成功!"); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/controller/test/Person.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.controller.test; 2 | 3 | /** 4 | * Created by stephan on 11.03.16. 5 | */ 6 | public class Person { 7 | private String name; 8 | private String email; 9 | 10 | public Person() { 11 | } 12 | 13 | public Person(String name, String email) { 14 | this.name = name; 15 | this.email = email; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public void setName(String name) { 23 | this.name = name; 24 | } 25 | 26 | public String getEmail() { 27 | return email; 28 | } 29 | 30 | public void setEmail(String email) { 31 | this.email = email; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/controller/user/UserController.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.controller.user; 2 | 3 | import com.chinawiserv.admin.config.security.JwtTokenUtil; 4 | import com.chinawiserv.admin.config.security.JwtUser; 5 | import com.chinawiserv.admin.controller.test.Person; 6 | import com.chinawiserv.admin.model.User; 7 | import com.chinawiserv.core.response.ResultBody; 8 | import com.chinawiserv.core.response.ResultGenerator; 9 | import com.chinawiserv.core.web.controller.BaseCRUDController; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.security.core.userdetails.UserDetailsService; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Created by sungang on 2017/8/19. 21 | *

22 | * 在 @PreAuthorize 中我们可以利用内建的 SPEL 表达式:比如 'hasRole()' 来决定哪些用户有权访问。 23 | * 需注意的一点是 hasRole 表达式认为每个角色名字前都有一个前缀 'ROLE_'。所以这里的 'ADMIN' 其实在 24 | * 数据库中存储的是 'ROLE_ADMIN' 。这个 @PreAuthorize 可以修饰Controller也可修饰Controller 25 | */ 26 | @RestController 27 | @RequestMapping("/api/user") 28 | public class UserController extends BaseCRUDController { 29 | 30 | @Value("${jwt.header}") 31 | private String tokenHeader; 32 | 33 | @Autowired 34 | private JwtTokenUtil jwtTokenUtil; 35 | 36 | @Autowired 37 | private UserDetailsService userDetailsService; 38 | 39 | @GetMapping 40 | public JwtUser getAuthenticatedUser(HttpServletRequest request) { 41 | String token = request.getHeader(tokenHeader); 42 | String username = jwtTokenUtil.getUsernameFromToken(token); 43 | JwtUser user = (JwtUser) userDetailsService.loadUserByUsername(username); 44 | return user; 45 | } 46 | 47 | 48 | private List persons = new ArrayList<>(); 49 | 50 | private void add() { 51 | persons.add(new Person("Hello", "World")); 52 | persons.add(new Person("Foo", "Bar")); 53 | } 54 | 55 | private void clear() { 56 | persons.clear(); 57 | } 58 | 59 | @RequestMapping(path = "/persons", method = RequestMethod.GET) 60 | public List getPersons() { 61 | return persons; 62 | } 63 | 64 | @RequestMapping(path = "/persons", method = RequestMethod.POST) 65 | public ResultBody addP() { 66 | add(); 67 | return ResultGenerator.genSuccessResult(); 68 | } 69 | @RequestMapping(path = "/persons", method = RequestMethod.DELETE) 70 | public ResultBody delP() { 71 | clear(); 72 | return ResultGenerator.genSuccessResult(); 73 | } 74 | @RequestMapping(path = "/persons/{name}", method = RequestMethod.GET) 75 | public Person getPerson(@PathVariable("name") String name) { 76 | return persons.stream() 77 | .filter(person -> name.equalsIgnoreCase(person.getName())) 78 | .findAny().orElse(null); 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/mapper/PermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.mapper; 2 | 3 | import com.chinawiserv.admin.model.Permission; 4 | import com.chinawiserv.core.dao.mybatis.BaseMapper; 5 | 6 | /** 7 | * Created by sungang on 2017/10/24. 8 | */ 9 | public interface PermissionMapper extends BaseMapper { 10 | } 11 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.mapper; 2 | 3 | import com.chinawiserv.admin.model.User; 4 | import com.chinawiserv.core.dao.mybatis.BaseMapper; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by sungang on 2017/10/24. 10 | */ 11 | public interface UserMapper extends BaseMapper { 12 | 13 | User selectUserAndAuthorities(Map params); 14 | } 15 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.mapper; 2 | 3 | import com.chinawiserv.admin.model.UserRole; 4 | import com.chinawiserv.core.dao.mybatis.BaseMapper; 5 | 6 | /** 7 | * Created by sungang on 2017/10/24. 8 | */ 9 | public interface UserRoleMapper extends BaseMapper { 10 | } 11 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/model/Permission.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.model; 2 | 3 | import com.chinawiserv.core.model.BaseModel; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import javax.persistence.*; 8 | import java.util.Date; 9 | 10 | /** 11 | * Created by sungang on 2017/10/24. 12 | */ 13 | @Table(name = "sys_user") 14 | @Data 15 | @ToString 16 | public class Permission extends BaseModel { 17 | 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | 24 | private String name; 25 | 26 | private Long pid; 27 | 28 | private String method; 29 | 30 | @Column(name = "permission_url") 31 | private String permissionUrl; 32 | 33 | private String description; 34 | 35 | @Column(name = "create_time") 36 | private Date createTime; 37 | } 38 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/model/User.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.model; 2 | 3 | import com.chinawiserv.core.model.BaseModel; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import javax.persistence.*; 8 | import java.util.Date; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by sungang on 2017/10/24. 13 | */ 14 | @Table(name = "sys_user") 15 | @Data 16 | @ToString 17 | public class User extends BaseModel{ 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | private Long id; 22 | 23 | private String username; 24 | 25 | private String password; 26 | 27 | private String name; 28 | 29 | private String email; 30 | 31 | private Integer status; 32 | 33 | private String remark; 34 | 35 | @Column(name = "last_password_reset_date") 36 | private Date lastPasswordResetDate; 37 | 38 | @Transient 39 | private List authorities; 40 | 41 | @Transient 42 | private Long roleId; 43 | } 44 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/model/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.model; 2 | 3 | import com.chinawiserv.core.model.BaseModel; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * Created by sungang on 2017/10/24. 11 | */ 12 | @Table(name = "sys_user") 13 | @Data 14 | @ToString 15 | public class UserRole extends BaseModel { 16 | 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long id; 21 | 22 | 23 | 24 | @Column(name = "user_id") 25 | private Long userId; 26 | 27 | 28 | @Column(name = "role_id") 29 | private Long roleId; 30 | } 31 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/service/sys/UserService.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.service.sys; 2 | 3 | import com.chinawiserv.admin.model.User; 4 | import com.chinawiserv.core.service.IService; 5 | 6 | /** 7 | * Created by sungang on 2017/10/24. 8 | */ 9 | public interface UserService extends IService { 10 | } 11 | -------------------------------------------------------------------------------- /car_admin/src/main/java/com/chinawiserv/admin/service/sys/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.admin.service.sys; 2 | 3 | import com.chinawiserv.admin.model.User; 4 | import com.chinawiserv.core.service.BaseService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Service; 7 | 8 | /** 9 | * Created by sungang on 20 10 | * 17/10/24. 11 | */ 12 | @Service 13 | @Slf4j 14 | public class UserServiceImpl extends BaseService implements UserService { 15 | } 16 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | 2 | #修改启动端口 3 | server.port=8021 4 | #修改访问路径 默认是 / 5 | server.context-path=/ 6 | #用户会话session过期时间 以秒为单位 7 | #server.session-timeout= 8 | #配置Tomcat编码 默认是UTF-8 9 | server.tomcat.uri-encoding = UTF-8 10 | #Tomcat是否开启压缩 默认是关闭 off 11 | server.tomcat.compression = off 12 | server.tomcat.max-threads=800 13 | server.tomcat.basedir = target/tomcat/admin 14 | # session 超时间 此设置将自动与 Redis session超时一致 单位:s 前提 使用spring boot : run 15 | #server.session.timeout = 30 16 | 17 | 18 | 19 | # 是否显示异常信息 20 | show-exception = true 21 | 22 | ########################### JWT And Captcha############################# 23 | jwt.header = Authorization 24 | jwt.secret = mySecret 25 | jwt.expiration = 604800 26 | 27 | jwt.captcha-UUID-mark=Captcha-UUID-Mark 28 | ########################### JWT And Captcha############################# 29 | 30 | 31 | 32 | 33 | # 使用 MD5 作为版本号 34 | # 是否开启内容版本策略,默认为false 35 | #spring.resources.chain.strategy.content.enable=true 36 | #spring.resources.chain.strategy.content.paths=/** 37 | 38 | #日志 39 | #logging.file=log.log 40 | #logging.level.org.springframework.web=INFO 41 | #设置true 可以查看boot运行 已启用的自动配置 42 | #Positive matches:表示已启用的配置 43 | #Negative matches:表示未启用的配置 44 | #debug=true 45 | #日志 46 | log.path=/Users/sungang/Documents/logs/car_admin 47 | log.level=INFO 48 | #日志最多保留天数 49 | log.maxHistory=1 50 | #会检查终端是否支持ANSI,是的话就采用彩色输出 51 | spring.output.ansi.enabled = DETECT 52 | 53 | 54 | ######################################################## 55 | ### i18n setting. 56 | ######################################################## 57 | #指定message的basename,多个以逗号分隔,如果不加包名的话,默认从classpath路径开始,默认: messages 58 | spring.messages.basename=i18n/messages 59 | #设定加载的资源文件缓存失效时间,-1的话为永不过期,默认为-1 60 | spring.messages.cache-seconds= 3600 61 | #设定Message bundles的编码,默认: UTF-8 62 | #spring.messages.encoding=UTF-8 63 | 64 | 65 | ### RabbitMQ Start 66 | #spring.rabbitmq.host= 43.254.3.72 67 | #spring.rabbitmq.port=5672 68 | #spring.rabbitmq.username=admin 69 | #spring.rabbitmq.password=123456 70 | #spring.rabbitmq.virtual-host=/ 71 | ### RabbitMQ End 72 | 73 | 74 | ############################### Redis Start ###################################### 75 | #spring.session.store-type=redis 76 | # Redis数据库索引(默认为0) 77 | spring.redis.database=0 78 | # Redis服务器地址 79 | spring.redis.host=43.254.3.68 80 | #spring.redis.host=43.254.3.72 81 | #spring.redis.cluster.nodes = 43.254.3.68 82 | # Login password of the redis server. 83 | # Redis服务器连接密码(默认为空) 84 | spring.redis.password=Chinawiservqz# 85 | #spring.redis.password=Dehui2017 86 | # Redis服务器连接端口 87 | spring.redis.port=3697 88 | #spring.redis.port=6379 89 | # 连接池中的最大空闲连接 90 | spring.redis.pool.max-idle=8 91 | # 连接池中的最小空闲连接 92 | spring.redis.pool.min-idle=5 93 | # 连接池最大连接数(使用负值表示没有限制) 94 | spring.redis.pool.max-active=8 95 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 96 | spring.redis.pool.max-wait=-1 97 | # Name of Redis server. 98 | #spring.redis.sentinel.master= 99 | # Comma-separated list of host:port pairs. 100 | #spring.redis.sentinel.nodes= 101 | # 连接超时时间(毫秒) 102 | spring.redis.timeout=3600 103 | 104 | ############################### Redis End ###################################### 105 | 106 | 107 | ######################################################## 108 | ### Mybatis Setting 109 | ######################################################## 110 | #mybatis 111 | mybatis.type-aliases-package=com.chinawiserv.admin.model 112 | mybatis.mapper-locations=classpath:mapper/*.xml 113 | mybatis.config-location=classpath:mybatis/mybatis-config.xml 114 | #mapper 115 | #mappers 多个接口时逗号隔开 116 | mapper.mappers=com.chinawiserv.core.dao.mybatis.BaseMapper 117 | mapper.not-empty=false 118 | mapper.identity=MYSQL 119 | #pagehelper 120 | pagehelper.helperDialect=mysql 121 | pagehelper.reasonable=true 122 | pagehelper.supportMethodsArguments=true 123 | pagehelper.params=count=countSql 124 | 125 | 126 | # 数据库访问配置 127 | # 主数据源,默认的 128 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 129 | spring.datasource.driverClassName=com.mysql.jdbc.Driver 130 | spring.datasource.url=jdbc:mysql://localhost:3306/skcar?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 131 | spring.datasource.username=root 132 | spring.datasource.password=123456 133 | 134 | 135 | # 下面为连接池的补充设置,应用到上面所有数据源中 136 | # 初始化大小,最小,最大 137 | spring.datasource.initialSize=5 138 | spring.datasource.minIdle=5 139 | spring.datasource.maxActive=20 140 | # 配置获取连接等待超时的时间 141 | spring.datasource.maxWait=60000 142 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 143 | spring.datasource.timeBetweenEvictionRunsMillis=60000 144 | # 配置一个连接在池中最小生存的时间,单位是毫秒 145 | spring.datasource.minEvictableIdleTimeMillis=300000 146 | # 配置一个连接在池中最小生存的时间,单位是毫秒 147 | spring.datasource.validationQuery=SELECT 'x' 148 | spring.datasource.testWhileIdle=true 149 | spring.datasource.testOnBorrow=false 150 | spring.datasource.testOnReturn=false 151 | # 打开PSCache,并且指定每个连接上PSCache的大小 152 | spring.datasource.poolPreparedStatements=true 153 | spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 154 | # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 155 | spring.datasource.filters=wall,stat 156 | # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 157 | spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 158 | # 合并多个DruidDataSource的监控数据 159 | #spring.datasource.useGlobalDataSourceStat=true 160 | 161 | 162 | #Http Encoding default UTF-8 163 | spring.http.encoding.charset=UTF-8 164 | #设置forceEncoding 默认是true 165 | spring.http.encoding.force=true 166 | #默认支持文件上传. 167 | spring.http.multipart.enabled=true 168 | #支持文件写入磁盘. 169 | spring.http.multipart.file-size-threshold=0 170 | # 上传文件的临时目录 171 | #spring.http.multipart.location= 172 | # 最大支持文件大小 173 | spring.http.multipart.max-file-size=8Mb 174 | # 最大支持请求大小 175 | spring.http.multipart.max-request-size=10Mb 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | 2 | #修改启动端口 3 | server.port=8021 4 | #修改访问路径 默认是 / 5 | server.context-path=/ 6 | #用户会话session过期时间 以秒为单位 7 | #server.session-timeout= 8 | #配置Tomcat编码 默认是UTF-8 9 | server.tomcat.uri-encoding = UTF-8 10 | server.tomcat.max-threads=800 11 | server.tomcat.basedir = target/tomcat/admin 12 | # session 超时间 此设置将自动与 Redis session超时一致 单位:s 前提 使用spring boot : run 13 | #server.session.timeout = 30 14 | 15 | 16 | # 是否显示异常信息 17 | show-exception = true 18 | 19 | ########################### JWT And Captcha############################# 20 | jwt.header = Authorization 21 | jwt.secret = mySecret 22 | jwt.expiration = 604800 23 | 24 | jwt.Captcha-UUID-code=Captcha-UUID-code 25 | ########################### JWT And Captcha############################# 26 | 27 | 28 | # 设置静态资源的存放地址 29 | #spring.resources.static-locations=classpath:/resources 30 | 31 | # 是否开启缓存,默认为: true 32 | spring.resources.chain.cache=true 33 | 34 | #设定资源的缓存时效,以秒为单位. 35 | spring.resources.cache-period = 1 36 | 37 | # 开启 gzip 38 | spring.resources.chain.gzipped=true 39 | 40 | # 指定版本号 41 | # 是否开启固定的版本策略,默认为false 42 | spring.resources.chain.strategy.fixed.enabled=true 43 | # 指定要应用版本策略的路径,多个以逗号分隔 44 | spring.resources.chain.strategy.fixed.paths=/static 45 | # 指定版本策略使用的版本号 46 | spring.resources.chain.strategy.fixed.version=1.0.0 47 | 48 | 49 | # 是否开启h5应用的cache manifest重写,默认为: false 50 | spring.resources.chain.html-application-cache = true 51 | 52 | 53 | 54 | 55 | #日志 56 | #logging.file=log.log 57 | #logging.level.org.springframework.web=INFO 58 | #设置true 可以查看boot运行 已启用的自动配置 59 | #Positive matches:表示已启用的配置 60 | #Negative matches:表示未启用的配置 61 | #debug=true 62 | #日志 63 | log.path=/chinawiserv/application/logs/art_api 64 | log.level=INFO 65 | #日志最多保留天数 66 | log.maxHistory=10 67 | #会检查终端是否支持ANSI,是的话就采用彩色输出 68 | spring.output.ansi.enabled = DETECT 69 | 70 | 71 | ######################################################## 72 | ### i18n setting. 73 | ######################################################## 74 | #指定message的basename,多个以逗号分隔,如果不加包名的话,默认从classpath路径开始,默认: messages 75 | spring.messages.basename=i18n/messages 76 | #设定加载的资源文件缓存失效时间,-1的话为永不过期,默认为-1 77 | spring.messages.cache-seconds= 3600 78 | #设定Message bundles的编码,默认: UTF-8 79 | #spring.messages.encoding=UTF-8 80 | 81 | 82 | ### RabbitMQ Start 83 | #spring.rabbitmq.host= 43.254.3.72 84 | #spring.rabbitmq.port=5672 85 | #spring.rabbitmq.username=admin 86 | #spring.rabbitmq.password=123456 87 | #spring.rabbitmq.virtual-host=/ 88 | ### RabbitMQ End 89 | 90 | ############################### Redis Start ###################################### 91 | #spring.session.store-type=redis 92 | # Redis数据库索引(默认为0) 93 | spring.redis.database=0 94 | # Redis服务器地址 95 | spring.redis.host=localhost 96 | # Login password of the redis server. 97 | # Redis服务器连接密码(默认为空) 98 | spring.redis.password=Dehui2017 99 | # Redis服务器连接端口 100 | spring.redis.port=6379 101 | # 连接池中的最大空闲连接 102 | spring.redis.pool.max-idle=8 103 | # 连接池中的最小空闲连接 104 | spring.redis.pool.min-idle=5 105 | # 连接池最大连接数(使用负值表示没有限制) 106 | spring.redis.pool.max-active=8 107 | # 连接池最大阻塞等待时间(使用负值表示没有限制) 108 | spring.redis.pool.max-wait=-1 109 | # Name of Redis server. 110 | #spring.redis.sentinel.master= 111 | # Comma-separated list of host:port pairs. 112 | #spring.redis.sentinel.nodes= 113 | # 连接超时时间(毫秒) 114 | spring.redis.timeout=3600 115 | 116 | ############################### Redis End ###################################### 117 | 118 | 119 | 120 | ######################################################## 121 | ### Mybatis Setting 122 | ######################################################## 123 | #mybatis 124 | mybatis.type-aliases-package=com.chinawiserv.model 125 | mybatis.mapper-locations=classpath:mapper/*.xml 126 | #mybatis.config-location=classpath:mybatis/mybatis-config.xml 127 | #mapper 128 | #mappers 多个接口时逗号隔开 129 | mapper.mappers=com.chinawiserv.core.dao.mybatis.BaseMapper 130 | mapper.not-empty=false 131 | mapper.identity=MYSQL 132 | #pagehelper 133 | pagehelper.helperDialect=mysql 134 | pagehelper.reasonable=true 135 | pagehelper.supportMethodsArguments=true 136 | pagehelper.params=count=countSql 137 | 138 | 139 | # 数据库访问配置 140 | # 主数据源,默认的 141 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 142 | spring.datasource.driverClassName=com.mysql.jdbc.Driver 143 | spring.datasource.url=jdbc:mysql://localhost:3306/spar?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 144 | spring.datasource.username=root 145 | spring.datasource.password=Dehui2017 146 | 147 | 148 | # 下面为连接池的补充设置,应用到上面所有数据源中 149 | # 初始化大小,最小,最大 150 | spring.datasource.initialSize=5 151 | spring.datasource.minIdle=5 152 | spring.datasource.maxActive=20 153 | # 配置获取连接等待超时的时间 154 | spring.datasource.maxWait=60000 155 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 156 | spring.datasource.timeBetweenEvictionRunsMillis=60000 157 | # 配置一个连接在池中最小生存的时间,单位是毫秒 158 | spring.datasource.minEvictableIdleTimeMillis=300000 159 | # 配置一个连接在池中最小生存的时间,单位是毫秒 160 | spring.datasource.validationQuery=SELECT 'x' 161 | spring.datasource.testWhileIdle=true 162 | spring.datasource.testOnBorrow=false 163 | spring.datasource.testOnReturn=false 164 | # 打开PSCache,并且指定每个连接上PSCache的大小 165 | spring.datasource.poolPreparedStatements=true 166 | spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 167 | # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 168 | spring.datasource.filters=wall,stat 169 | # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 170 | spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 171 | # 合并多个DruidDataSource的监控数据 172 | #spring.datasource.useGlobalDataSourceStat=true 173 | 174 | 175 | #Http Encoding default UTF-8 176 | spring.http.encoding.charset=UTF-8 177 | #设置forceEncoding 默认是true 178 | spring.http.encoding.force=true 179 | #默认支持文件上传. 180 | spring.http.multipart.enabled=true 181 | #支持文件写入磁盘. 182 | spring.http.multipart.file-size-threshold=0 183 | # 上传文件的临时目录 184 | #spring.http.multipart.location= 185 | # 最大支持文件大小 186 | spring.http.multipart.max-file-size=8Mb 187 | # 最大支持请求大小 188 | spring.http.multipart.max-request-size=10Mb 189 | 190 | 191 | 192 | 193 | ############################## Swagger-UI ################################# 194 | #标题 195 | swagger.title=art_api 196 | #描述 197 | swagger.description=art_api 1.x 198 | #版本 199 | swagger.version=0.1 200 | #许可证URL 201 | swagger.license= 202 | #服务条款URL 203 | swagger.licenseUrl= 204 | # 205 | swagger.termsOfServiceUrl= 206 | #维护人 207 | swagger.contact.name=Williamsun 208 | #维护人URL 209 | swagger.contact.url=https://github.com/aillamsun 210 | #维护人邮箱 211 | swagger.contact.email=1120sungang@gmail.com 212 | #扫描的基础包,默认:全扫描 213 | swagger.base-package=com.chinawiserv.api.controller 214 | #需要处理的基础URL规则,默认:/** 215 | swagger.base-path=/** 216 | #需要排除的URL规则,默认:空 217 | swagger.exclude-path=/error, /dashboard/**, /auth/** 218 | ############################## Swagger-UI ################################# -------------------------------------------------------------------------------- /car_admin/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # dev 开发环境 2 | # prod 生产环境 3 | spring.profiles.active=dev 4 | 5 | 6 | #http://localhost:port/info 7 | info.build.artifact=@project.artifactId@ 8 | info.build.name=@project.name@ 9 | info.build.description=@project.description@ 10 | info.build.version=@project.version@ 11 | 12 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/i18n/messages.properties: -------------------------------------------------------------------------------- 1 | # 认证 授权 2 | auth.success=认证注册成功 3 | auth.error=认证注册信息不通过 4 | auth.before=请先注册认证 5 | app_key.error=Token不正确 6 | sign.error=sign或者签名参数不正确 7 | secrity_key.exist=该app_key已经注册 8 | auth.regiter.error=注册{0}认证信{1}息失败 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/i18n/messages_en_US.properties: -------------------------------------------------------------------------------- 1 | welcome = welcome to login to alibaba website(English) -------------------------------------------------------------------------------- /car_admin/src/main/resources/i18n/messages_zh_CN.properties: -------------------------------------------------------------------------------- 1 | welcome = \u6b22\u8fce\u4f60\u767b\u5f55\u5230 \u963f\u91cc\u5df4\u5df4 \u7f51\u7ad9\uff08\u4e2d\u6587\uff09 -------------------------------------------------------------------------------- /car_admin/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 40 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/mybatis/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/skcar.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat Premium Data Transfer 3 | 4 | Source Server : localhost 5 | Source Server Type : MySQL 6 | Source Server Version : 50717 7 | Source Host : localhost 8 | Source Database : skcar 9 | 10 | Target Server Type : MySQL 11 | Target Server Version : 50717 12 | File Encoding : utf-8 13 | 14 | Date: 04/09/2018 10:22:18 AM 15 | */ 16 | 17 | SET NAMES utf8mb4; 18 | SET FOREIGN_KEY_CHECKS = 0; 19 | 20 | -- ---------------------------- 21 | -- Table structure for `sys_permission` 22 | -- ---------------------------- 23 | DROP TABLE IF EXISTS `sys_permission`; 24 | CREATE TABLE `sys_permission` ( 25 | `id` bigint(20) NOT NULL, 26 | `name` varchar(255) DEFAULT NULL, 27 | `pid` bigint(20) DEFAULT NULL, 28 | `method` varchar(50) DEFAULT NULL COMMENT '请求方法', 29 | `permission_url` varchar(255) DEFAULT NULL COMMENT '授权链接', 30 | `description` varchar(255) DEFAULT NULL, 31 | `create_time` datetime DEFAULT NULL, 32 | PRIMARY KEY (`id`) 33 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统权限表'; 34 | 35 | -- ---------------------------- 36 | -- Records of `sys_permission` 37 | -- ---------------------------- 38 | BEGIN; 39 | INSERT INTO `sys_permission` VALUES ('1', 'ADMIN', null, 'ALL', '/api/**', '项目最大权限', '2017-10-24 15:49:04'), ('2', 'USER_ALL', null, 'ALL', '/api/user/**', '用户所有权限', '2017-10-24 15:49:01'), ('3', 'USER_GET', null, 'GET', '/api/user/**', '获取单个用户', '2017-10-24 14:44:24'), ('4', 'USER_PUT', null, 'PUT', '/api/user/**', '修改用户', '2017-10-24 14:45:22'), ('5', 'USER_ADD', null, 'POST', '/api/user/**', '添加用户', '2017-10-24 14:46:03'), ('6', 'USER_ DELETE', null, 'DELETE', '/api/user/**', '删除用户', '2017-10-24 15:49:46'); 40 | COMMIT; 41 | 42 | -- ---------------------------- 43 | -- Table structure for `sys_role` 44 | -- ---------------------------- 45 | DROP TABLE IF EXISTS `sys_role`; 46 | CREATE TABLE `sys_role` ( 47 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 48 | `name` varchar(45) NOT NULL COMMENT '角色名称', 49 | `role` varchar(45) DEFAULT NULL, 50 | `description` varchar(45) DEFAULT NULL, 51 | `is_all` int(11) DEFAULT '0' COMMENT '是否是全选 0 否 1 是', 52 | `create_time` datetime DEFAULT NULL, 53 | `create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人id', 54 | `status` int(45) DEFAULT NULL COMMENT '0 不可用 1 可用', 55 | PRIMARY KEY (`id`) 56 | ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='角色表'; 57 | 58 | -- ---------------------------- 59 | -- Records of `sys_role` 60 | -- ---------------------------- 61 | BEGIN; 62 | INSERT INTO `sys_role` VALUES ('1', 'Admin', 'admin', 'admin', '1', '2017-10-24 11:30:03', '1', '1'), ('2', 'User_All', 'User_All', '用户所有权限', '1', '2017-10-24 11:30:19', '1', '1'), ('3', 'User_A_G', 'User_A_G', '用户添加查询权限', '1', '2017-10-24 16:27:24', '1', '1'), ('4', 'User_A_U_G', 'User_A_U_G', '用户添加修改查询权限', '1', '2017-10-24 17:20:05', '1', '1'); 63 | COMMIT; 64 | 65 | -- ---------------------------- 66 | -- Table structure for `sys_role_permission` 67 | -- ---------------------------- 68 | DROP TABLE IF EXISTS `sys_role_permission`; 69 | CREATE TABLE `sys_role_permission` ( 70 | `id` bigint(20) NOT NULL, 71 | `role_id` bigint(20) NOT NULL, 72 | `permission_id` bigint(20) NOT NULL, 73 | PRIMARY KEY (`id`) 74 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; 75 | 76 | -- ---------------------------- 77 | -- Records of `sys_role_permission` 78 | -- ---------------------------- 79 | BEGIN; 80 | INSERT INTO `sys_role_permission` VALUES ('1', '1', '1'), ('2', '2', '2'), ('3', '3', '3'), ('4', '4', '4'), ('5', '4', '5'), ('6', '3', '5'), ('7', '4', '3'); 81 | COMMIT; 82 | 83 | -- ---------------------------- 84 | -- Table structure for `sys_user` 85 | -- ---------------------------- 86 | DROP TABLE IF EXISTS `sys_user`; 87 | CREATE TABLE `sys_user` ( 88 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 89 | `username` varchar(255) NOT NULL COMMENT '用户名', 90 | `password` varchar(255) NOT NULL COMMENT '用户密码', 91 | `name` varchar(255) DEFAULT NULL COMMENT '用户姓名', 92 | `sex` int(2) DEFAULT NULL COMMENT '性别 1 男 2 女', 93 | `email` varchar(255) DEFAULT NULL COMMENT '邮箱', 94 | `title` varchar(255) DEFAULT NULL COMMENT '职称', 95 | `phone` varchar(11) NOT NULL COMMENT '电话', 96 | `organ_id` bigint(20) NOT NULL COMMENT '公司id', 97 | `dept_id` bigint(20) NOT NULL COMMENT '部门id', 98 | `position` varchar(30) DEFAULT NULL COMMENT '职位', 99 | `job` varchar(30) DEFAULT NULL COMMENT '岗位', 100 | `create_time` datetime DEFAULT NULL COMMENT '创建时间', 101 | `create_user_id` bigint(20) DEFAULT NULL COMMENT '创建人', 102 | `status` int(4) DEFAULT '1' COMMENT '1 正常 2 锁定 3 删除', 103 | `remark` varchar(255) DEFAULT NULL COMMENT '备注', 104 | `last_password_reset_date` datetime DEFAULT NULL, 105 | PRIMARY KEY (`id`) 106 | ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; 107 | 108 | -- ---------------------------- 109 | -- Records of `sys_user` 110 | -- ---------------------------- 111 | BEGIN; 112 | INSERT INTO `sys_user` VALUES ('1', 'admin', '0DPiKuNIrrVmD8IUCuw1hQxNqZc=', null, null, null, null, '13076061657', '1', '1', null, null, '2017-10-24 11:31:12', '1', '1', null, '2017-10-24 12:59:14'), ('2', 'user_all', 'fEqNCco3Yq9h5ZUglD3CZJT4lBs=', null, null, null, null, '307071768', '1', '1', null, null, '2017-10-24 11:32:12', '1', '1', null, '2017-10-24 12:59:17'), ('3', 'disabled', 'fEqNCco3Yq9h5ZUglD3CZJT4lBs=', null, null, null, null, '111', '1', '1', null, null, '2017-10-24 11:32:46', '1', '0', null, '2017-10-24 12:59:21'), ('5', 'user_a_g', 'fEqNCco3Yq9h5ZUglD3CZJT4lBs=', null, null, null, null, '1', '1', '1', null, null, '2017-10-24 16:24:58', null, '1', null, null), ('6', 'user_a_u_g', 'fEqNCco3Yq9h5ZUglD3CZJT4lBs=', null, null, null, null, '1', '1', '1', null, null, '2017-10-24 16:25:27', null, '1', null, null); 113 | COMMIT; 114 | 115 | -- ---------------------------- 116 | -- Table structure for `sys_user_role` 117 | -- ---------------------------- 118 | DROP TABLE IF EXISTS `sys_user_role`; 119 | CREATE TABLE `sys_user_role` ( 120 | `id` bigint(20) NOT NULL, 121 | `user_id` bigint(20) NOT NULL, 122 | `role_id` bigint(20) NOT NULL, 123 | PRIMARY KEY (`id`) 124 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户角色表'; 125 | 126 | -- ---------------------------- 127 | -- Records of `sys_user_role` 128 | -- ---------------------------- 129 | BEGIN; 130 | INSERT INTO `sys_user_role` VALUES ('1', '1', '1'), ('2', '2', '2'), ('3', '3', '2'), ('4', '5', '3'), ('5', '6', '4'); 131 | COMMIT; 132 | 133 | SET FOREIGN_KEY_CHECKS = 1; 134 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JWT Spring Security Demo 6 | 7 | 8 | 10 | 11 | 12 | 14 | 15 | 16 | 17 |

18 |

Spring boot For JWT And Spring Security Example!

19 | 20 |
Not logged in!
21 | 22 |
23 |
24 |
25 |
26 |

登录

27 |
28 |
29 |
30 |
31 | 33 |
34 |
35 | 37 |
38 |
39 | 测试登录账号 40 |
    41 |
  • admin & admin >>[超级权限]
  • 42 |
  • user_all & 123456 >> [用户模块最大权限]
  • 43 |
  • user_a_g & 123456 >> [用户添加查询权限]
  • 44 |
  • user_a_u_g & 123456 >> [用户添加修改查询权限]
  • 45 |
  • disabled & 123456 >> [冻结用户]
  • 46 |
47 |
48 | 49 |
50 |
51 |
52 | 53 |
54 |
55 |
56 |

认证用户信息

57 |
58 |
59 |
60 | 61 |
62 |
63 |
64 |
65 | 66 |
67 |
68 | 69 | 70 | 71 | 72 |
73 |
74 |
75 |

响应:

76 |
77 |
78 |

 79 |             
80 |
81 |
82 |
83 | 84 |
85 |
86 |
87 |
88 |

Token 信息

89 |
90 |
91 |
92 |
93 |
94 |
95 | 96 | 110 | 111 | 113 | 114 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /car_admin/src/main/resources/static/js/libs/jwt-decode.min.js: -------------------------------------------------------------------------------- 1 | !function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g>(-2*g&6)):0)e=f.indexOf(e);return i}var f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";d.prototype=new Error,d.prototype.name="InvalidCharacterError",b.exports="undefined"!=typeof window&&window.atob&&window.atob.bind(window)||e},{}],2:[function(a,b,c){function d(a){return decodeURIComponent(e(a).replace(/(.)/g,function(a,b){var c=b.charCodeAt(0).toString(16).toUpperCase();return c.length<2&&(c="0"+c),"%"+c}))}var e=a("./atob");b.exports=function(a){var b=a.replace(/-/g,"+").replace(/_/g,"/");switch(b.length%4){case 0:break;case 2:b+="==";break;case 3:b+="=";break;default:throw"Illegal base64url string!"}try{return d(b)}catch(c){return e(b)}}},{"./atob":1}],3:[function(a,b,c){"use strict";function d(a){this.message=a}var e=a("./base64_url_decode");d.prototype=new Error,d.prototype.name="InvalidTokenError",b.exports=function(a,b){if("string"!=typeof a)throw new d("Invalid token specified");b=b||{};var c=b.header===!0?0:1;try{return JSON.parse(e(a.split(".")[c]))}catch(f){throw new d("Invalid token specified: "+f.message)}},b.exports.InvalidTokenError=d},{"./base64_url_decode":2}],4:[function(a,b,c){(function(b){var c=a("./lib/index");"function"==typeof b.window.define&&b.window.define.amd?b.window.define("jwt_decode",function(){return c}):b.window&&(b.window.jwt_decode=c)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./lib/index":3}]},{},[4]); -------------------------------------------------------------------------------- /car_admin/src/main/resources/system.properties: -------------------------------------------------------------------------------- 1 | 2 | ######################### 手机短信吗配置####################### 3 | #短信账号 4 | msg.account=LKSDK0005521 5 | #短信密码 6 | msg.password=zh9527@ 7 | #短信接口地址 8 | msg.url=http://mb345.com:999/ws/BatchSend2.aspx 9 | msg.code-UUID-mark=MsgCode-UUID-Mark 10 | ######################### 手机短信吗配置####################### 11 | -------------------------------------------------------------------------------- /car_core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-security-with-jwt 5 | com.chinawiserv 6 | 0.0.1-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | car_core 11 | jar 12 | 13 | car_core 14 | http://maven.apache.org 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | com.chinawiserv 23 | car_utils 24 | ${project.version} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | org.mybatis.spring.boot 34 | mybatis-spring-boot-starter 35 | 1.2.0 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-jdbc 40 | 41 | 42 | 43 | 44 | 45 | tk.mybatis 46 | mapper-spring-boot-starter 47 | 1.1.0 48 | 49 | 50 | 51 | com.github.pagehelper 52 | pagehelper-spring-boot-starter 53 | 1.1.0 54 | 55 | 56 | org.mybatis.spring.boot 57 | mybatis-spring-boot-starter 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/annotation/Auth.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by sungang on 2016/8/31. 10 | */ 11 | 12 | @Target(ElementType.METHOD) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | public @interface Auth { 15 | 16 | boolean verifyLogin() default false; //验证登录 17 | 18 | boolean verifyWxAuth() default false; //验证企业认证 19 | 20 | boolean verifyAppLogin() default false; //验证用户金额 21 | } 22 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/constants/Constants.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.constants; 2 | 3 | /** 4 | * Created with IntelliJ IDEA. 5 | * Date: 2016/6/14 6 | * Time: 14:23 7 | * To change this template use File | Settings | File Templates. 8 | */ 9 | public interface Constants { 10 | 11 | /** 12 | * 操作名称 13 | */ 14 | String OP_NAME = "op"; 15 | 16 | 17 | /** 18 | * 消息key 19 | */ 20 | String MESSAGE = "message"; 21 | 22 | /** 23 | * 错误key 24 | */ 25 | String ERROR = "error"; 26 | 27 | /** 28 | * 上个页面地址 29 | */ 30 | String BACK_URL = "BackURL"; 31 | 32 | String IGNORE_BACK_URL = "ignoreBackURL"; 33 | 34 | /** 35 | * 当前请求的地址 带参数 36 | */ 37 | String CURRENT_URL = "currentURL"; 38 | 39 | /** 40 | * 当前请求的地址 不带参数 41 | */ 42 | String NO_QUERYSTRING_CURRENT_URL = "noQueryStringCurrentURL"; 43 | 44 | 45 | String CONTEXT_PATH = "ctx"; 46 | 47 | /** 48 | * 当前登录的用户 49 | */ 50 | String CURRENT_USER = "user"; 51 | 52 | /** 53 | * 当前登录的CRM用户 54 | */ 55 | String MEMBER_USER = "memberUser"; 56 | 57 | /** 58 | * 当前门店id 59 | */ 60 | String CURRENT_SHOP_ID = "shop_id"; 61 | 62 | /** 63 | * 机器地址 64 | */ 65 | String MAC_IP = "127.0.0.1"; 66 | 67 | /** 68 | * 扣费金额 69 | */ 70 | int CUT_MONEY = 2; 71 | /** 72 | * 当前登录用户名 73 | */ 74 | String CURRENT_USERNAME = "username"; 75 | /** 76 | * 系统编码 77 | */ 78 | String ENCODING = "UTF-8"; 79 | 80 | 81 | String AUTH_TOKEN = "auth_token"; 82 | 83 | /** 84 | * 状态码 85 | */ 86 | //删除状态 87 | final int DELETE = 0; 88 | //未被删除状态,默认状态 89 | final int NORMAL = 1; 90 | 91 | //所有订单查询是查询各个状态的个数 92 | final String EVERY_STATUS_COUNT = "all"; 93 | 94 | /** 95 | * 模拟ajax请求成功返回码 96 | */ 97 | final String REQUEST_SUCCESS = "200"; 98 | 99 | final String SET_TIME_TYPE_PICKUP = "pickUp"; 100 | final String SET_TIME_TYPE_DELIVER = "deliver"; 101 | 102 | /** 103 | * 积分 104 | */ 105 | //基础积分 106 | final int INTEGRAL_BASE = 1; 107 | //赠送积分 108 | final int INTEGRAL_GIVE = 2; 109 | 110 | 111 | final String INTEGRAL_TYPE_ADD = "add"; 112 | 113 | 114 | } 115 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/dao/mybatis/BaseMapper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.dao.mybatis; 2 | 3 | import tk.mybatis.mapper.common.ConditionMapper; 4 | import tk.mybatis.mapper.common.IdsMapper; 5 | import tk.mybatis.mapper.common.Mapper; 6 | import tk.mybatis.mapper.common.MySqlMapper; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * 继承自己的 BaseMapper 12 | */ 13 | public interface BaseMapper extends Mapper,MySqlMapper,ConditionMapper, IdsMapper { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/dao/mybatis/SqlProvider.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.dao.mybatis; 2 | 3 | /** 4 | * Created by sungang on 2017/3/29. 5 | */ 6 | public class SqlProvider { 7 | } 8 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/dao/mybatis/interceptor/CameHumpInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.dao.mybatis.interceptor; 2 | 3 | import org.apache.ibatis.executor.resultset.ResultSetHandler; 4 | import org.apache.ibatis.plugin.*; 5 | 6 | import java.sql.Statement; 7 | import java.util.*; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | /** 12 | * MyBatis Map类型大写下划线Key转小写驼峰形式 13 | * 改为拦截ResultSetHandler,更简单的,而且可以避免一级缓存导致重复转换出错 14 | * Created by sungang on 2016/7/4. 15 | */ 16 | @Intercepts( 17 | @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}) 18 | ) 19 | public class CameHumpInterceptor implements Interceptor { 20 | 21 | @Override 22 | public Object intercept(Invocation invocation) throws Throwable { 23 | //先执行,后处理 24 | List list = (List) invocation.proceed(); 25 | for (Object object : list) { 26 | if (object instanceof Map) { 27 | processMap((Map) object); 28 | } else { 29 | break; 30 | } 31 | } 32 | return list; 33 | } 34 | 35 | /** 36 | * 处理简单对象 37 | * @param map 38 | */ 39 | private void processMap(Map map) { 40 | Map cameHumpMap = new HashMap(); 41 | Iterator iterator = map.entrySet().iterator(); 42 | while (iterator.hasNext()) { 43 | Map.Entry entry = iterator.next(); 44 | String key = (String) entry.getKey(); 45 | String cameHumpKey = underlineToCamelhump(key.toLowerCase()); 46 | if (!key.equals(cameHumpKey)) { 47 | cameHumpMap.put(cameHumpKey, entry.getValue()); 48 | iterator.remove(); 49 | } 50 | } 51 | map.putAll(cameHumpMap); 52 | } 53 | 54 | /** 55 | * 将下划线风格替换为驼峰风格 56 | * @param str 57 | * @return 58 | */ 59 | public static String underlineToCamelhump(String str) { 60 | Matcher matcher = Pattern.compile("_[a-z]").matcher(str); 61 | StringBuilder builder = new StringBuilder(str); 62 | for (int i = 0; matcher.find(); i++) { 63 | builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase()); 64 | } 65 | if (Character.isUpperCase(builder.charAt(0))) { 66 | builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0)))); 67 | } 68 | return builder.toString(); 69 | } 70 | 71 | @Override 72 | public Object plugin(Object target) { 73 | if (target instanceof ResultSetHandler) { 74 | return Plugin.wrap(target, this); 75 | } 76 | return target; 77 | } 78 | 79 | @Override 80 | public void setProperties(Properties properties) { 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/dao/mybatis/interceptor/PerformanceInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.dao.mybatis.interceptor; 2 | 3 | 4 | import org.apache.ibatis.cache.CacheKey; 5 | import org.apache.ibatis.executor.Executor; 6 | import org.apache.ibatis.mapping.BoundSql; 7 | import org.apache.ibatis.mapping.MappedStatement; 8 | import org.apache.ibatis.mapping.ParameterMapping; 9 | import org.apache.ibatis.mapping.ParameterMode; 10 | import org.apache.ibatis.plugin.*; 11 | import org.apache.ibatis.reflection.MetaObject; 12 | import org.apache.ibatis.session.Configuration; 13 | import org.apache.ibatis.session.ResultHandler; 14 | import org.apache.ibatis.session.RowBounds; 15 | import org.apache.ibatis.type.TypeHandlerRegistry; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import java.text.DateFormat; 20 | import java.text.SimpleDateFormat; 21 | import java.util.Date; 22 | import java.util.List; 23 | import java.util.Properties; 24 | 25 | /** 26 | * MyBatis 性能拦截器,用于输出每条 SQL 语句及其执行时间 27 | *

28 | * Created by sungang on 2016/7/4. 29 | */ 30 | @Intercepts({ 31 | @Signature(type = Executor.class, method = "query",args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), 32 | @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) 33 | }) 34 | public class PerformanceInterceptor implements Interceptor { 35 | 36 | private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 37 | 38 | 39 | Logger log = LoggerFactory.getLogger(PerformanceInterceptor.class); 40 | 41 | @Override 42 | public Object intercept(Invocation invocation) throws Throwable { 43 | MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; 44 | Object parameterObject = null; 45 | if (invocation.getArgs().length > 1) { 46 | parameterObject = invocation.getArgs()[1]; 47 | } 48 | 49 | String statementId = mappedStatement.getId(); 50 | BoundSql boundSql = mappedStatement.getBoundSql(parameterObject); 51 | Configuration configuration = mappedStatement.getConfiguration(); 52 | String sql = getSql(boundSql, parameterObject, configuration); 53 | 54 | long start = System.currentTimeMillis(); 55 | 56 | Object result = invocation.proceed(); 57 | 58 | long end = System.currentTimeMillis(); 59 | long timing = end - start; 60 | log.info("耗时:" + timing + " ms" + " - id:" + statementId + " - Sql:" + sql); 61 | return result; 62 | } 63 | 64 | @Override 65 | public Object plugin(Object target) { 66 | if (target instanceof Executor) { 67 | return Plugin.wrap(target, this); 68 | } 69 | return target; 70 | } 71 | 72 | @Override 73 | public void setProperties(Properties properties) { 74 | } 75 | 76 | private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) { 77 | String sql = boundSql.getSql().replaceAll("[\\s]+", " "); 78 | List parameterMappings = boundSql.getParameterMappings(); 79 | TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 80 | if (parameterMappings != null) { 81 | for (int i = 0; i < parameterMappings.size(); i++) { 82 | ParameterMapping parameterMapping = parameterMappings.get(i); 83 | if (parameterMapping.getMode() != ParameterMode.OUT) { 84 | Object value; 85 | String propertyName = parameterMapping.getProperty(); 86 | if (boundSql.hasAdditionalParameter(propertyName)) { 87 | value = boundSql.getAdditionalParameter(propertyName); 88 | } else if (parameterObject == null) { 89 | value = null; 90 | } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { 91 | value = parameterObject; 92 | } else { 93 | MetaObject metaObject = configuration.newMetaObject(parameterObject); 94 | value = metaObject.getValue(propertyName); 95 | } 96 | sql = replacePlaceholder(sql, value); 97 | } 98 | } 99 | } 100 | return sql; 101 | } 102 | 103 | private String replacePlaceholder(String sql, Object propertyValue) { 104 | String result; 105 | if (propertyValue != null) { 106 | if (propertyValue instanceof String) { 107 | result = "'" + propertyValue + "'"; 108 | } else if (propertyValue instanceof Date) { 109 | result = "'" + DATE_FORMAT.format(propertyValue) + "'"; 110 | } else { 111 | result = propertyValue.toString(); 112 | } 113 | } else { 114 | result = "null"; 115 | } 116 | return sql.replaceFirst("\\?", result); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/enums/ErrorInfo.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.enums; 2 | 3 | /** 4 | * 错误码接口 5 | *

6 | * Created by sungang on 2017/5/19. 7 | */ 8 | public interface ErrorInfo { 9 | 10 | String getCode(); 11 | 12 | String getMessage(); 13 | 14 | void setMessage(String message); 15 | } 16 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/enums/ErrorInfoEnum.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.enums; 2 | 3 | /** 4 | * Created by sungang on 2017/5/19. 5 | */ 6 | public enum ErrorInfoEnum implements ErrorInfo { 7 | 8 | USER_OR_PWD_NOT_NUlL("000001", "用户名或密码不能为空!"), 9 | USER_JWT_EXPIRED("000002", "Token不能为空或失效了!"), 10 | USER_JWT_FORMAT("000003", "Token格式不正确!"), 11 | CAPTCHA_ERROR("000004", "验证码不正确!"), 12 | PHONE_CODE_ERROR("000005", "手机短信码不正确!"), 13 | OPEN_ID_IS_NOT_NULL("000006", "!"), 14 | OPEN_ID_EXPIRED("000007", "openId过期重新授权!"), 15 | NOT_MEMBER("000008", "当前不是会员用户!"), 16 | CAPTCHA_MARK_ERROR("000009", "验证码标记不正确或者验证码已过期!"), 17 | PHONE_SEND_CODE_ERROR("000010", "发送手机短信码失败!"); 18 | 19 | 20 | private String code; 21 | 22 | private String message; 23 | 24 | ErrorInfoEnum(String code, String message) { 25 | this.code = code; 26 | this.message = message; 27 | } 28 | 29 | public String getCode() { 30 | return this.code; 31 | } 32 | 33 | public String getMessage() { 34 | return this.message; 35 | } 36 | 37 | @Override 38 | public void setMessage(String message) { 39 | this.message = message; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/enums/GlobalErrorInfoEnum.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.enums; 2 | 3 | /** 4 | * 应用系统级别的错误码 5 | *

6 | * Created by sungang on 2017/5/19. 7 | */ 8 | public enum GlobalErrorInfoEnum implements ErrorInfo { 9 | SUCCESS("200","success"),//成功 10 | FAIL("400","fail"),//失败 11 | UNAUTHORIZED("401","UNAUTHORIZED"),//未认证(签名错误) 12 | NOT_FOUND("404","NOT_FOUND"),//接口不存在 13 | INTERNAL_SERVER_ERROR("500","INTERNAL_SERVER_ERROR");//服务器内部错误 14 | 15 | private String code; 16 | 17 | private String message; 18 | 19 | GlobalErrorInfoEnum(String code, String message) { 20 | this.code = code; 21 | this.message = message; 22 | } 23 | 24 | public String getCode() { 25 | return this.code; 26 | } 27 | 28 | public String getMessage() { 29 | return this.message; 30 | } 31 | 32 | @Override 33 | public void setMessage(String message) { 34 | this.message = message; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/exception/ArtArtistTagException.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.exception; 2 | 3 | import com.chinawiserv.core.enums.ErrorInfo; 4 | 5 | public class ArtArtistTagException extends Exception { 6 | private ErrorInfo errorInfo; 7 | private Object[] args; 8 | 9 | public ArtArtistTagException(ErrorInfo errorInfo, Object... agrs) { 10 | this.errorInfo = errorInfo; 11 | this.args = agrs; 12 | } 13 | 14 | public ErrorInfo getErrorInfo() { 15 | return errorInfo; 16 | } 17 | 18 | public void setErrorInfo(ErrorInfo errorInfo) { 19 | this.errorInfo = errorInfo; 20 | } 21 | 22 | 23 | public Object[] getArgs() { 24 | return args; 25 | } 26 | 27 | public void setArgs(Object[] args) { 28 | this.args = args; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/exception/GlobalErrorInfoException.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.exception; 2 | 3 | 4 | import com.chinawiserv.core.enums.ErrorInfo; 5 | 6 | /** 7 | * Created by sungang on 2017/5/19. 8 | */ 9 | public class GlobalErrorInfoException extends Exception { 10 | 11 | private ErrorInfo errorInfo; 12 | private Object[] args; 13 | 14 | public GlobalErrorInfoException(ErrorInfo errorInfo, Object... agrs) { 15 | this.errorInfo = errorInfo; 16 | this.args = agrs; 17 | } 18 | 19 | public ErrorInfo getErrorInfo() { 20 | return errorInfo; 21 | } 22 | 23 | public void setErrorInfo(ErrorInfo errorInfo) { 24 | this.errorInfo = errorInfo; 25 | } 26 | 27 | 28 | public Object[] getArgs() { 29 | return args; 30 | } 31 | 32 | public void setArgs(Object[] args) { 33 | this.args = args; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/exception/UserLoginException.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.exception; 2 | 3 | import com.chinawiserv.core.enums.ErrorInfo; 4 | 5 | /** 6 | * Created by sungang on 2017/9/18. 7 | */ 8 | public class UserLoginException extends Exception { 9 | 10 | 11 | private ErrorInfo errorInfo; 12 | private Object[] args; 13 | 14 | public UserLoginException(ErrorInfo errorInfo, Object... agrs) { 15 | this.errorInfo = errorInfo; 16 | this.args = agrs; 17 | } 18 | 19 | public ErrorInfo getErrorInfo() { 20 | return errorInfo; 21 | } 22 | 23 | public void setErrorInfo(ErrorInfo errorInfo) { 24 | this.errorInfo = errorInfo; 25 | } 26 | 27 | 28 | public Object[] getArgs() { 29 | return args; 30 | } 31 | 32 | public void setArgs(Object[] args) { 33 | this.args = args; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/exception/WxException.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.exception; 2 | 3 | import com.chinawiserv.core.enums.ErrorInfo; 4 | 5 | /** 6 | * 微信相关异常 7 | * Created by sungang on 2017/9/22. 8 | */ 9 | public class WxException extends Exception { 10 | 11 | 12 | private ErrorInfo errorInfo; 13 | private Object[] args; 14 | 15 | public WxException(ErrorInfo errorInfo, Object... agrs) { 16 | this.errorInfo = errorInfo; 17 | this.args = agrs; 18 | } 19 | 20 | public ErrorInfo getErrorInfo() { 21 | return errorInfo; 22 | } 23 | 24 | public void setErrorInfo(ErrorInfo errorInfo) { 25 | this.errorInfo = errorInfo; 26 | } 27 | 28 | 29 | public Object[] getArgs() { 30 | return args; 31 | } 32 | 33 | public void setArgs(Object[] args) { 34 | this.args = args; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/handler/GlobalErrorInfoHandler.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.handler; 2 | 3 | import com.chinawiserv.core.enums.ErrorInfo; 4 | import com.chinawiserv.core.enums.GlobalErrorInfoEnum; 5 | import com.chinawiserv.core.exception.GlobalErrorInfoException; 6 | import com.chinawiserv.core.response.ResultBody; 7 | import com.chinawiserv.core.utils.MessageUtils; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.util.StringUtils; 13 | import org.springframework.web.bind.annotation.ExceptionHandler; 14 | import org.springframework.web.bind.annotation.RestControllerAdvice; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | 18 | /** 19 | * 统一错误码异常处理 20 | *

21 | * Created by sungang on 2017/5/19. 22 | */ 23 | @Slf4j 24 | @RestControllerAdvice 25 | public class GlobalErrorInfoHandler { 26 | 27 | 28 | @Value("${show-exception}") 29 | private Boolean showException = false; 30 | 31 | private static Logger logger = LoggerFactory.getLogger(GlobalErrorInfoHandler.class); 32 | 33 | /** 34 | * 全局系统异常 35 | * @param request 36 | * @param exception 37 | * @return 38 | */ 39 | @ExceptionHandler(value = RuntimeException.class) 40 | public ResultBody errorHandlerOverJson(HttpServletRequest request, RuntimeException exception) { 41 | logger.error("全局异常:{}", exception.getMessage()); 42 | if (showException){ 43 | exception.printStackTrace(); 44 | } 45 | ResultBody result = new ResultBody(GlobalErrorInfoEnum.INTERNAL_SERVER_ERROR); 46 | return result; 47 | } 48 | 49 | 50 | 51 | 52 | 53 | /** 54 | * GlobalErrorInfoException 系统异常 55 | * @param request 56 | * @param exception 57 | * @return 58 | */ 59 | @ExceptionHandler(value = GlobalErrorInfoException.class) 60 | public ResultBody handleGlobalErrorInfoException(HttpServletRequest request, GlobalErrorInfoException exception) { 61 | logger.error("GlobalErrorInfoException 错误消息:{}", exception.getMessage()); 62 | if (showException){ 63 | exception.printStackTrace(); 64 | } 65 | ErrorInfo errorInfo = exception.getErrorInfo(); 66 | 67 | getMessage(errorInfo, exception.getArgs()); 68 | 69 | ResultBody result = new ResultBody(errorInfo); 70 | return result; 71 | } 72 | 73 | private void getMessage(ErrorInfo errorInfo, Object... agrs) { 74 | String message = null; 75 | if (!StringUtils.isEmpty(errorInfo.getCode())) { 76 | message = MessageUtils.message(errorInfo.getCode(), agrs); 77 | } 78 | if (message == null) { 79 | message = errorInfo.getMessage(); 80 | } 81 | errorInfo.setMessage(message); 82 | } 83 | } -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.model; 2 | 3 | import org.apache.commons.lang3.builder.EqualsBuilder; 4 | import org.apache.commons.lang3.builder.HashCodeBuilder; 5 | import org.apache.commons.lang3.builder.ToStringBuilder; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * Created by sungang on 2017/8/19. 11 | */ 12 | public class BaseModel implements Serializable { 13 | 14 | private static final long serialVersionUID = -3707046914855595598L; 15 | 16 | @Override 17 | public int hashCode() { 18 | return HashCodeBuilder.reflectionHashCode(this); 19 | } 20 | 21 | @Override 22 | public boolean equals(Object obj) { 23 | return EqualsBuilder.reflectionEquals(this, obj); 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return ToStringBuilder.reflectionToString(this); 29 | } 30 | 31 | public final T simpleClone() { 32 | try { 33 | @SuppressWarnings("unchecked") 34 | T ret = (T) clone(); 35 | return ret; 36 | } catch (Exception e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/model/page/BasePage.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.model.page; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by sungang on 2017/4/17. 9 | */ 10 | public class BasePage implements Serializable { 11 | /** 12 | * 13 | */ 14 | private static final long serialVersionUID = 1L; 15 | private int pageNo = 1;// 页码,默认是第一页 16 | private int recordNo = 0; 17 | private int pageSize = 10;// 每页显示的记录数,默认是15 18 | private long totalRecord;// 总记录数 19 | private long totalPage;// 总页数 20 | private String pageUrl;// 请求路径 21 | private short isAjax = 0;//是否是ajax请求 1是ajax,0不是,默认是,因为大部分不需要分页,设为是,就不会在下面显示分页 22 | private String urlParam;//map string 类型的参数 23 | private Map paramsMap;//传递参数,只用于前台请求的参数,不能是实体对象 24 | private T t;//后台传递对象参数,不用于向前太传递 25 | 26 | private List results;// 对应的当前页记录 27 | 28 | 29 | public int getPageNo() { 30 | return pageNo; 31 | } 32 | 33 | 34 | public void setPageNo(int pageNo) { 35 | this.pageNo = pageNo; 36 | } 37 | 38 | 39 | public int getRecordNo() { 40 | return recordNo; 41 | } 42 | 43 | 44 | public void setRecordNo(int recordNo) { 45 | this.recordNo = recordNo; 46 | } 47 | 48 | 49 | public int getPageSize() { 50 | return pageSize; 51 | } 52 | 53 | 54 | public void setPageSize(int pageSize) { 55 | this.pageSize = pageSize; 56 | } 57 | 58 | 59 | public long getTotalRecord() { 60 | return totalRecord; 61 | } 62 | 63 | 64 | public short getIsAjax() { 65 | return isAjax; 66 | } 67 | 68 | 69 | public void setIsAjax(short isAjax) { 70 | this.isAjax = isAjax; 71 | } 72 | 73 | 74 | public long getTotalPage() { 75 | return totalPage; 76 | } 77 | 78 | 79 | public void setTotalPage(long totalPage) { 80 | this.totalPage = totalPage; 81 | } 82 | 83 | public void setTotalRecord(long totalRecord) { 84 | this.totalRecord = totalRecord; 85 | // 在设置总页数的时候计算出对应的总页数,在下面的三目运算中加法拥有更高的优先级,所以最后可以不加括号。 86 | long totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize 87 | : totalRecord / pageSize + 1; 88 | this.setTotalPage(totalPage); 89 | } 90 | 91 | 92 | public List getResults() { 93 | return results; 94 | } 95 | 96 | public void setResults(List results) { 97 | this.results = results; 98 | } 99 | 100 | 101 | public String getPageUrl() { 102 | return pageUrl; 103 | } 104 | 105 | public void setPageUrl(String pageUrl) { 106 | this.pageUrl = pageUrl; 107 | } 108 | 109 | 110 | /** 111 | * 设置请求参数 112 | * 113 | * @param key 114 | * @param value 115 | */ 116 | public void putParam(String key, Object value) { 117 | this.paramsMap.put(key, value); 118 | } 119 | 120 | /** 121 | * 获得请求参数 122 | * 123 | * @param key 124 | * @return 125 | */ 126 | public Object getParam(Object key) { 127 | return this.paramsMap.get(key); 128 | } 129 | 130 | 131 | public String getUrlParam() { 132 | return urlParam; 133 | } 134 | 135 | /** 136 | * url参数 137 | * 138 | * @param urlParam 139 | */ 140 | public void setUrlParam(Map urlParam) { 141 | String urlStr = ""; 142 | for (String key : urlParam.keySet()) { 143 | Object obj = urlParam.get(key); 144 | if (obj != null) 145 | urlStr = urlStr + "&" + key + "=" + obj; 146 | 147 | } 148 | this.urlParam = urlStr.substring(urlStr.indexOf("&") + 1); 149 | System.out.println("#########请求参数" + this.urlParam); 150 | } 151 | 152 | /** 153 | * 只用于页面参数 154 | * 155 | * @return 156 | */ 157 | public Map getParamsMap() { 158 | return paramsMap; 159 | } 160 | 161 | /** 162 | * 只用于页面参数,不能是对象因为要加到url中 163 | * 164 | * @param paramsMap 165 | */ 166 | public void setParamsMap(Map paramsMap) { 167 | this.paramsMap = paramsMap; 168 | this.setUrlParam(paramsMap); 169 | } 170 | 171 | 172 | /** 173 | * 用于后台传递对象参数 174 | * 175 | * @return 176 | */ 177 | public T getT() { 178 | return t; 179 | } 180 | 181 | /** 182 | * 后台传递对象参数 183 | * 184 | * @param t 185 | */ 186 | public void setT(T t) { 187 | this.t = t; 188 | } 189 | 190 | @Override 191 | public String toString() { 192 | StringBuilder builder = new StringBuilder(); 193 | builder.append("Page [pageNo=").append(pageNo).append(", pageSize=") 194 | .append(pageSize).append(", results=").append(results) 195 | .append(", totalPage=").append(totalPage) 196 | .append(", totalRecord=").append(totalRecord).append("]"); 197 | return builder.toString(); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/response/ResultBody.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.response; 2 | 3 | import com.chinawiserv.core.enums.ErrorInfo; 4 | import com.chinawiserv.core.enums.GlobalErrorInfoEnum; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 返回体 10 | * Created by sungang on 2017/5/19. 11 | */ 12 | public class ResultBody implements Serializable { 13 | /** 14 | * 响应代码 15 | */ 16 | private String code = GlobalErrorInfoEnum.SUCCESS.getCode(); 17 | 18 | /** 19 | * 响应消息 20 | */ 21 | private String message; 22 | 23 | /** 24 | * 响应结果 25 | */ 26 | private Object result; 27 | 28 | public ResultBody() { 29 | 30 | } 31 | 32 | public ResultBody(ErrorInfo errorInfo) { 33 | this.code = errorInfo.getCode(); 34 | this.message = errorInfo.getMessage(); 35 | } 36 | 37 | public ResultBody(Object result) { 38 | this.code = GlobalErrorInfoEnum.SUCCESS.getCode(); 39 | this.message = GlobalErrorInfoEnum.SUCCESS.getMessage(); 40 | this.result = result; 41 | } 42 | 43 | public String getCode() { 44 | return code; 45 | } 46 | 47 | public ResultBody setCode(String code) { 48 | this.code = code; 49 | return this; 50 | } 51 | 52 | public String getMessage() { 53 | return message; 54 | } 55 | 56 | public ResultBody setMessage(String message) { 57 | this.message = message; 58 | return this; 59 | } 60 | 61 | public Object getResult() { 62 | return result; 63 | } 64 | 65 | public ResultBody setResult(Object result) { 66 | this.result = result; 67 | return this; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/response/ResultGenerator.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.response; 2 | 3 | 4 | import com.chinawiserv.core.enums.ErrorInfo; 5 | import com.chinawiserv.core.enums.GlobalErrorInfoEnum; 6 | import com.chinawiserv.core.utils.MessageUtils; 7 | import org.apache.commons.lang3.StringUtils; 8 | 9 | /** 10 | * Created by sungang on 2017/8/19. 11 | */ 12 | public class ResultGenerator { 13 | 14 | 15 | private static final String DEFAULT_SUCCESS_MESSAGE = "success"; 16 | 17 | public static ResultBody genSuccessResult() { 18 | return new ResultBody() 19 | .setCode(GlobalErrorInfoEnum.SUCCESS.getCode()) 20 | .setMessage(DEFAULT_SUCCESS_MESSAGE); 21 | } 22 | 23 | public static ResultBody genSuccessResult(Object data) { 24 | return new ResultBody() 25 | .setCode(GlobalErrorInfoEnum.SUCCESS.getCode()) 26 | .setMessage(DEFAULT_SUCCESS_MESSAGE) 27 | .setResult(data); 28 | } 29 | 30 | public static ResultBody genFailResult(ErrorInfo errorInfo, Object... agrs) { 31 | return new ResultBody() 32 | .setCode(errorInfo.getCode()) 33 | .setMessage(getMessage(errorInfo, agrs)); 34 | } 35 | 36 | 37 | public static ResultBody genFailResult(String code, String message) { 38 | return new ResultBody() 39 | .setCode(code) 40 | .setMessage(message); 41 | } 42 | 43 | private static String getMessage(ErrorInfo errorInfo, Object... agrs) { 44 | String msg = errorInfo.getMessage(); 45 | if (!StringUtils.isEmpty(errorInfo.getCode()) && null != agrs) { 46 | msg = MessageUtils.message(errorInfo.getCode(), agrs); 47 | } else { 48 | msg = MessageUtils.message(errorInfo.getCode()); 49 | } 50 | 51 | return msg; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/utils/MessageUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.utils; 2 | 3 | import org.springframework.context.MessageSource; 4 | 5 | /** 6 | * Created by sungang on 2017/9/13. 7 | */ 8 | public class MessageUtils { 9 | 10 | 11 | private static MessageSource messageSource; 12 | 13 | /** 14 | * 根据消息键和参数 获取消息 15 | * 委托给spring messageSource 16 | * 17 | * @param code 消息键 18 | * @param args 参数 19 | * @return 20 | */ 21 | public static String message(String code, Object... args) { 22 | if (messageSource == null) { 23 | messageSource = SpringUtils.getBean(MessageSource.class); 24 | } 25 | return messageSource.getMessage(code, args, null); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/utils/SpringUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.utils; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 5 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 6 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 7 | 8 | /** 9 | * Created by sungang on 2017/9/13. 10 | */ 11 | public class SpringUtils implements BeanFactoryPostProcessor { 12 | 13 | private static ConfigurableListableBeanFactory beanFactory; // Spring应用上下文环境 14 | 15 | // @Override 16 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 17 | SpringUtils.beanFactory = beanFactory; 18 | } 19 | 20 | /** 21 | * 获取对象 22 | * 23 | * @param name 24 | * @return Object 一个以所给名字注册的bean的实例 25 | * @throws BeansException 26 | * 27 | */ 28 | @SuppressWarnings("unchecked") 29 | public static T getBean(String name) throws BeansException { 30 | return (T) beanFactory.getBean(name); 31 | } 32 | 33 | /** 34 | * 获取类型为requiredType的对象 35 | * 36 | * @param clz 37 | * @return 38 | * @throws BeansException 39 | * 40 | */ 41 | public static T getBean(Class clz) throws BeansException { 42 | @SuppressWarnings("unchecked") 43 | T result = (T) beanFactory.getBean(clz); 44 | return result; 45 | } 46 | 47 | /** 48 | * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true 49 | * 50 | * @param name 51 | * @return boolean 52 | */ 53 | public static boolean containsBean(String name) { 54 | return beanFactory.containsBean(name); 55 | } 56 | 57 | /** 58 | * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) 59 | * 60 | * @param name 61 | * @return boolean 62 | * @throws NoSuchBeanDefinitionException 63 | * 64 | */ 65 | public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { 66 | return beanFactory.isSingleton(name); 67 | } 68 | 69 | /** 70 | * @param name 71 | * @return Class 注册对象的类型 72 | * @throws NoSuchBeanDefinitionException 73 | * 74 | */ 75 | public static Class getType(String name) throws NoSuchBeanDefinitionException { 76 | return beanFactory.getType(name); 77 | } 78 | 79 | /** 80 | * 如果给定的bean名字在bean定义中有别名,则返回这些别名 81 | * 82 | * @param name 83 | * @return 84 | * @throws NoSuchBeanDefinitionException 85 | * 86 | */ 87 | public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { 88 | return beanFactory.getAliases(name); 89 | } 90 | 91 | /** 92 | * 93 | * @param name 94 | * @param clz 95 | * @param 96 | * @return 97 | * @throws BeansException 98 | */ 99 | public static T getBean(String name, Class clz) 100 | throws BeansException { 101 | T result = beanFactory.getBean(name, clz); 102 | return result; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/web/controller/AbstarctBaseController.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.web.controller; 2 | 3 | import com.chinawiserv.utils.ReflectUtils; 4 | import com.google.common.collect.Maps; 5 | import org.apache.commons.lang3.StringUtils; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.core.annotation.AnnotationUtils; 9 | import org.springframework.validation.BindingResult; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | 12 | import javax.servlet.ServletRequest; 13 | import javax.servlet.ServletResponse; 14 | import javax.servlet.http.HttpServletRequest; 15 | import java.io.Serializable; 16 | import java.util.Iterator; 17 | import java.util.Map; 18 | 19 | /** 20 | * Created by sungang on 2016/9/26. 21 | */ 22 | public abstract class AbstarctBaseController implements BaseController { 23 | 24 | Logger log = LoggerFactory.getLogger(AbstarctBaseController.class); 25 | 26 | 27 | public static final int DEFAULT_PAGE_SIZE = 15; 28 | public static final int DEFAULT_PAGE_NUM = 1; 29 | 30 | 31 | public static final String SUCESS = "success"; 32 | public static final String ERROR = "error"; 33 | 34 | 35 | //防止重复提交 36 | public static final String POST_TOKEN = "postToken"; 37 | 38 | // protected abstract BaseService getBaseService(); 39 | 40 | /** 41 | * ThreadLocal确保高并发下每个请求的request,response都是独立的 42 | */ 43 | protected static ThreadLocal currentRequest = new ThreadLocal(); 44 | protected static ThreadLocal currentResponse = new ThreadLocal(); 45 | 46 | /** 47 | * 实体类型 48 | */ 49 | protected final Class entityClass; 50 | 51 | private String viewPrefix; 52 | 53 | protected AbstarctBaseController() { 54 | this.entityClass = ReflectUtils.findParameterizedType(getClass(), 0); 55 | setViewPrefix(defaultViewPrefix()); 56 | } 57 | 58 | 59 | /** 60 | * 当前模块 视图的前缀 61 | * 默认 62 | * 1、获取当前类头上的@RequestMapping中的value作为前缀 63 | * 2、如果没有就使用当前模型小写的简单类名 64 | */ 65 | public void setViewPrefix(String viewPrefix) { 66 | if (viewPrefix.startsWith("/")) { 67 | viewPrefix = viewPrefix.substring(1); 68 | } 69 | this.viewPrefix = viewPrefix; 70 | } 71 | 72 | public String getViewPrefix() { 73 | return viewPrefix; 74 | } 75 | 76 | protected T newModel() { 77 | try { 78 | return entityClass.newInstance(); 79 | } catch (Exception e) { 80 | throw new IllegalStateException("can not instantiated model : " + this.entityClass, e); 81 | } 82 | } 83 | 84 | /** 85 | * 获取视图名称:即prefixViewName + "/" + suffixName 86 | * 87 | * @return 88 | */ 89 | public String viewName(String suffixName) { 90 | if (!suffixName.startsWith("/")) { 91 | suffixName = "/" + suffixName; 92 | } 93 | String viewName = getViewPrefix() + suffixName; 94 | log.info("viewName======= " + viewName); 95 | return viewName; 96 | } 97 | 98 | /** 99 | * 共享的验证规则 100 | * 验证失败返回true 101 | * 102 | * @param m 103 | * @param result 104 | * @return 105 | */ 106 | protected boolean hasError(T m, BindingResult result) { 107 | return result.hasErrors(); 108 | } 109 | 110 | /** 111 | * @param backURL null 将重定向到默认getViewPrefix() 112 | * @return 113 | */ 114 | protected String redirectToUrl(String backURL) { 115 | if (StringUtils.isEmpty(backURL)) { 116 | backURL = getViewPrefix(); 117 | } 118 | if (!backURL.startsWith("/") && !backURL.startsWith("http")) { 119 | backURL = "/" + backURL; 120 | } 121 | String redirectUrl = getViewPrefix() + backURL; 122 | log.info("redirectToUrl:======= " + redirectUrl); 123 | return "redirect:" + redirectUrl; 124 | } 125 | 126 | protected String defaultViewPrefix() { 127 | String currentViewPrefix = ""; 128 | RequestMapping requestMapping = AnnotationUtils.findAnnotation(getClass(), RequestMapping.class); 129 | if (requestMapping != null && requestMapping.value().length > 0) { 130 | currentViewPrefix = requestMapping.value()[0]; 131 | } 132 | 133 | if (StringUtils.isEmpty(currentViewPrefix)) { 134 | currentViewPrefix = this.entityClass.getSimpleName(); 135 | } 136 | 137 | return currentViewPrefix; 138 | } 139 | 140 | /** 141 | * 获取Resuest 请求参数 142 | * 143 | * @param request 144 | * @return 145 | */ 146 | protected Map getParameterMap(HttpServletRequest request) { 147 | Map params = Maps.newHashMap(); 148 | Map requestParams = request.getParameterMap(); 149 | for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { 150 | String name = (String) iter.next(); 151 | String[] values = (String[]) requestParams.get(name); 152 | String valueStr = ""; 153 | for (int i = 0; i < values.length; i++) { 154 | valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; 155 | } 156 | //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 157 | //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); 158 | params.put(name, valueStr); 159 | } 160 | return params; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/web/controller/BaseController.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.web.controller; 2 | 3 | /** 4 | * Created by sungang on 2016/8/29. 5 | */ 6 | public interface BaseController { 7 | 8 | 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /car_core/src/main/java/com/chinawiserv/core/web/interceptor/SetCommonDataInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.core.web.interceptor; 2 | 3 | import com.chinawiserv.core.constants.Constants; 4 | import org.springframework.util.AntPathMatcher; 5 | import org.springframework.util.PathMatcher; 6 | import org.springframework.util.StringUtils; 7 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | /** 13 | * 设置通用数据的Interceptor 14 | *

15 | * 使用Filter时 文件上传时 getParameter时为null 所以改成Interceptor 16 | *

17 | * 1、ctx---->request.contextPath 18 | * 2、currentURL---->当前地址 19 | *

20 | * Created with IntelliJ IDEA. 21 | * User: jacks 22 | * Date: 2016/6/14 23 | * Time: 20:23 24 | * To change this template use File | Settings | File Templates. 25 | */ 26 | public class SetCommonDataInterceptor extends HandlerInterceptorAdapter { 27 | 28 | 29 | private final PathMatcher pathMatcher = new AntPathMatcher(); 30 | 31 | private static final String[] DEFAULT_EXCLUDE_PARAMETER_PATTERN = new String[]{ 32 | "\\&\\w*page.pn=\\d+", 33 | "\\?\\w*page.pn=\\d+", 34 | "\\&\\w*page.size=\\d+" 35 | }; 36 | 37 | private String[] excludeParameterPatterns = DEFAULT_EXCLUDE_PARAMETER_PATTERN; 38 | private String[] excludeUrlPatterns = null; 39 | 40 | public void setExcludeParameterPatterns(String[] excludeParameterPatterns) { 41 | this.excludeParameterPatterns = excludeParameterPatterns; 42 | } 43 | 44 | public void setExcludeUrlPatterns(final String[] excludeUrlPatterns) { 45 | this.excludeUrlPatterns = excludeUrlPatterns; 46 | } 47 | 48 | 49 | @Override 50 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 51 | 52 | 53 | if (isExclude(request)) { 54 | return true; 55 | } 56 | 57 | if (request.getAttribute(Constants.CONTEXT_PATH) == null) { 58 | request.setAttribute(Constants.CONTEXT_PATH, request.getContextPath()); 59 | } 60 | if (request.getAttribute(Constants.CURRENT_URL) == null) { 61 | request.setAttribute(Constants.CURRENT_URL, extractCurrentURL(request, true)); 62 | } 63 | if (request.getAttribute(Constants.NO_QUERYSTRING_CURRENT_URL) == null) { 64 | request.setAttribute(Constants.NO_QUERYSTRING_CURRENT_URL, extractCurrentURL(request, false)); 65 | } 66 | if (request.getAttribute(Constants.BACK_URL) == null) { 67 | request.setAttribute(Constants.BACK_URL, extractBackURL(request)); 68 | } 69 | // 70 | // request.setAttribute("SYSNAME", Constants.SYSNAME); 71 | return true; 72 | } 73 | 74 | 75 | private boolean isExclude(final HttpServletRequest request) { 76 | if (excludeUrlPatterns == null) { 77 | return false; 78 | } 79 | for (String pattern : excludeUrlPatterns) { 80 | if (pathMatcher.match(pattern, request.getServletPath())) { 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | 88 | private String extractCurrentURL(HttpServletRequest request, boolean needQueryString) { 89 | String url = request.getRequestURI(); 90 | String queryString = request.getQueryString(); 91 | if (!StringUtils.isEmpty(queryString)) { 92 | queryString = "?" + queryString; 93 | for (String pattern : excludeParameterPatterns) { 94 | queryString = queryString.replaceAll(pattern, ""); 95 | } 96 | if (queryString.startsWith("&")) { 97 | queryString = "?" + queryString.substring(1); 98 | } 99 | } 100 | if (!StringUtils.isEmpty(queryString) && needQueryString) { 101 | url = url + queryString; 102 | } 103 | return getBasePath(request) + url; 104 | } 105 | 106 | 107 | /** 108 | * 上一次请求的地址 109 | * 1、先从request.parameter中查找BackURL 110 | * 2、获取header中的 referer 111 | * 112 | * @param request 113 | * @return 114 | */ 115 | private String extractBackURL(HttpServletRequest request) { 116 | String url = request.getParameter(Constants.BACK_URL); 117 | 118 | //使用Filter时 文件上传时 getParameter时为null 所以改成Interceptor 119 | 120 | if (StringUtils.isEmpty(url)) { 121 | url = request.getHeader("Referer"); 122 | } 123 | 124 | if (!StringUtils.isEmpty(url) && (url.startsWith("http://") || url.startsWith("https://"))) { 125 | return url; 126 | } 127 | 128 | if (!StringUtils.isEmpty(url) && url.startsWith(request.getContextPath())) { 129 | url = getBasePath(request) + url; 130 | } 131 | return url; 132 | } 133 | 134 | private String getBasePath(HttpServletRequest req) { 135 | StringBuffer baseUrl = new StringBuffer(); 136 | String scheme = req.getScheme(); 137 | int port = req.getServerPort(); 138 | baseUrl.append(scheme); // http, https 139 | baseUrl.append("://"); 140 | baseUrl.append(req.getServerName()); 141 | if ((scheme.equals("http") && port != 80) || (scheme.equals("https") && port != 443)) { 142 | baseUrl.append(':'); 143 | baseUrl.append(req.getServerPort()); 144 | } 145 | return baseUrl.toString(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /car_utils/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | spring-boot-security-with-jwt 5 | com.chinawiserv 6 | 0.0.1-SNAPSHOT 7 | 8 | 4.0.0 9 | 10 | car_utils 11 | jar 12 | 13 | car_utils 14 | http://maven.apache.org 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter 24 | 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | log4j-over-slf4j 34 | org.slf4j 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-aop 54 | 55 | 56 | 57 | 58 | 59 | 60 | net.sourceforge.jexcelapi 61 | jxl 62 | 2.6.12 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | com.mzlion 77 | easy-okhttp 78 | 1.0.7-beta 79 | 80 | 81 | javax.servlet 82 | javax.servlet-api 83 | 3.1.0 84 | 85 | 86 | dom4j 87 | dom4j 88 | 1.6.1 89 | 90 | 91 | 92 | 93 | io.jsonwebtoken 94 | jjwt 95 | ${jjwt.version} 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/AssertUtil.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import org.springframework.util.Assert; 4 | 5 | public class AssertUtil extends Assert{ 6 | 7 | } 8 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/ConvertPercent.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | /** 4 | * Created by wangt on 2017/7/12. 5 | */ 6 | public class ConvertPercent { 7 | 8 | //判断是否为16进制数 9 | public static boolean isHex(char c){ 10 | if(((c >= '0') && (c <= '9')) || 11 | ((c >= 'a') && (c <= 'f')) || 12 | ((c >= 'A') && (c <= 'F'))) 13 | return true; 14 | else 15 | return false; 16 | } 17 | 18 | public static String convertPercent(String str){ 19 | StringBuilder sb = new StringBuilder(str); 20 | 21 | for(int i = 0; i < sb.length(); i++){ 22 | char c = sb.charAt(i); 23 | //判断是否为转码符号% 24 | if(c == '%'){ 25 | if(((i + 1) < sb.length() -1) && ((i + 2) < sb.length() - 1)){ 26 | char first = sb.charAt(i + 1); 27 | char second = sb.charAt(i + 2); 28 | //如只是普通的%则转为%25 29 | if(!(isHex(first) && isHex(second))) 30 | sb.insert(i+1, "25"); 31 | } 32 | else{//如只是普通的%则转为%25 33 | sb.insert(i+1, "25"); 34 | } 35 | 36 | } 37 | } 38 | 39 | return sb.toString(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/GoodsUpConditionUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by sungang on 2017/4/26. 9 | */ 10 | public class GoodsUpConditionUtils { 11 | 12 | 13 | 14 | public static List getGoodsUpCondition(){ 15 | List upConditions = Lists.newArrayList(); 16 | upConditions.add(0); 17 | upConditions.add(1); 18 | upConditions.add(2); 19 | upConditions.add(6); 20 | upConditions.add(8); 21 | return upConditions; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/IPUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | /** 6 | * Created by Administrator on 2017/2/15. 7 | */ 8 | public class IPUtils { 9 | 10 | /** 11 | * 获取域名 不包含端口 12 | * 13 | * @return 14 | */ 15 | public static String getDomainNameExitPort(HttpServletRequest request) { 16 | //获取域名 17 | StringBuffer url = request.getRequestURL(); 18 | String domain_name = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString(); 19 | if (domain_name.contains(":")) { 20 | int i = domain_name.length() - domain_name.indexOf(":"); 21 | domain_name = domain_name.substring(0, (i - 2)); 22 | } 23 | String temp_domain_name = domain_name.substring(domain_name.length() - 1); 24 | if (!temp_domain_name.contains("/")) { 25 | domain_name = domain_name + "/"; 26 | } 27 | return domain_name; 28 | } 29 | 30 | public static String getDomainNam(HttpServletRequest request) { 31 | //获取域名 32 | String url = "http://"+request.getLocalAddr()+":"+request.getLocalPort(); 33 | return url; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/JsonWebTokenUtility.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | /** 4 | * Created by sungang on 2017/5/16. 5 | */ 6 | public class JsonWebTokenUtility { 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.security.MessageDigest; 8 | import java.security.NoSuchAlgorithmException; 9 | 10 | public class MD5Util { 11 | /** 12 | * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合 13 | */ 14 | protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 15 | protected static MessageDigest messagedigest = null; 16 | 17 | static { 18 | try { 19 | messagedigest = MessageDigest.getInstance("MD5"); 20 | } catch (NoSuchAlgorithmException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | public static String getFileMD5String(File file) throws IOException { 25 | InputStream fis; 26 | fis = new FileInputStream(file); 27 | byte[] buffer = new byte[1024]; 28 | int numRead = 0; 29 | while ((numRead = fis.read(buffer)) > 0) { 30 | messagedigest.update(buffer, 0, numRead); 31 | } 32 | fis.close(); 33 | return bufferToHex(messagedigest.digest()); 34 | } 35 | 36 | public static String getFileMD5String(InputStream in) throws IOException { 37 | byte[] buffer = new byte[1024]; 38 | int numRead = 0; 39 | while ((numRead = in.read(buffer)) > 0) { 40 | messagedigest.update(buffer, 0, numRead); 41 | } 42 | in.close(); 43 | return bufferToHex(messagedigest.digest()); 44 | } 45 | private static String bufferToHex(byte bytes[]) { 46 | return bufferToHex(bytes, 0, bytes.length); 47 | } 48 | private static String bufferToHex(byte bytes[], int m, int n) { 49 | StringBuffer stringbuffer = new StringBuffer(2 * n); 50 | int k = m + n; 51 | for (int l = m; l < k; l++) { 52 | appendHexPair(bytes[l], stringbuffer); 53 | } 54 | return stringbuffer.toString(); 55 | } 56 | private static void appendHexPair(byte bt, StringBuffer stringbuffer) { 57 | char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换 58 | // 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同 59 | char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换 60 | stringbuffer.append(c0); 61 | stringbuffer.append(c1); 62 | } 63 | 64 | public final static String MD5(String s) { 65 | try { 66 | byte[] btInput = s.getBytes(); 67 | // 使用指定的字节更新摘要 68 | messagedigest.update(btInput); 69 | // 获得密文 70 | byte[] md = messagedigest.digest(); 71 | // 把密文转换成十六进制的字符串形式 72 | int j = md.length; 73 | char str[] = new char[j * 2]; 74 | int k = 0; 75 | for (int i = 0; i < j; i++) { 76 | byte byte0 = md[i]; 77 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 78 | str[k++] = hexDigits[byte0 & 0xf]; 79 | } 80 | return new String(str); 81 | } catch (Exception e) { 82 | e.printStackTrace(); 83 | return null; 84 | } 85 | } 86 | 87 | /** 88 | * 解密 89 | */ 90 | public static String convertMD5(String inStr){ 91 | char[] a = inStr.toCharArray(); 92 | for (int i = 0; i < a.length; i++){ 93 | a[i] = (char) (a[i] ^ 't'); 94 | } 95 | String s = new String(a); 96 | return s; 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/OrderUtil.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | /** 7 | * Created with IntelliJ IDEA. 8 | * User: xuchy 9 | * Date: 16-7-11 10 | * Time: 下午6:05 11 | * To change this template use File | Settings | File Templates. 12 | * 订单工具类 13 | */ 14 | public class OrderUtil { 15 | /** 16 | * 锁对象,可以为任意对象 17 | */ 18 | private static Object lockObj = "lockerOrder"; 19 | 20 | /** 21 | * 订单号生成计数器 22 | */ 23 | private static long orderNumCounter = 0L; 24 | 25 | /** 26 | * 每毫秒生成订单号数量最大值 27 | */ 28 | private int maxPerMSECSize = 1000; 29 | 30 | /** 31 | * 订单根据对象 32 | */ 33 | private static OrderUtil orderUtil; 34 | 35 | /*私有构造方法*/ 36 | private OrderUtil(){} 37 | 38 | /** 39 | * 获取对象 40 | * @return 41 | */ 42 | public static OrderUtil getInstance(){ 43 | if(orderUtil == null){ 44 | orderUtil = new OrderUtil(); 45 | } 46 | return orderUtil; 47 | } 48 | 49 | /** 50 | * 生成非重复订单号 51 | */ 52 | public String makeOrderNo() { 53 | //最终生成的订单号,固定前2位:LF 54 | String orderNo = "LF"; 55 | try { 56 | synchronized (lockObj) { 57 | //取系统当前时间,精确到毫秒 58 | long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())); 59 | //计数器到最大值归零 60 | if (orderNumCounter > maxPerMSECSize) { 61 | orderNumCounter = 0L; 62 | } 63 | //组装订单号 64 | String countStr = maxPerMSECSize + orderNumCounter + ""; 65 | orderNo += nowLong + countStr.substring(1); 66 | orderNumCounter++; 67 | } 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | return orderNo; 72 | } 73 | 74 | /** 75 | * 生成非重复优惠券模板号 76 | */ 77 | public String makeTemplateNo() { 78 | String orderNo = "TP"; 79 | try { 80 | synchronized (lockObj) { 81 | //取系统当前时间,精确到毫秒 82 | long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())); 83 | //计数器到最大值归零 84 | if (orderNumCounter > maxPerMSECSize) { 85 | orderNumCounter = 0L; 86 | } 87 | //组装订单号 88 | String countStr = maxPerMSECSize + orderNumCounter + ""; 89 | orderNo += nowLong + countStr.substring(1); 90 | orderNumCounter++; 91 | } 92 | } catch (Exception e) { 93 | e.printStackTrace(); 94 | } 95 | return orderNo; 96 | } 97 | 98 | /** 99 | * 生成非重复积分换物订单号 100 | */ 101 | public String makeCashGoodsNo() { 102 | //最终生成的订单号,固定前2位:GN 103 | String orderNo = "GN"; 104 | try { 105 | synchronized (lockObj) { 106 | //取系统当前时间,精确到毫秒 107 | long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())); 108 | //计数器到最大值归零 109 | if (orderNumCounter > maxPerMSECSize) { 110 | orderNumCounter = 0L; 111 | } 112 | //组装订单号 113 | String countStr = maxPerMSECSize + orderNumCounter + ""; 114 | orderNo += nowLong + countStr.substring(1); 115 | orderNumCounter++; 116 | } 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } 120 | return orderNo; 121 | } 122 | 123 | /** 124 | * 生成唯一赢商通请求流水号 125 | */ 126 | public String makeRequestSequence(String orderId) { 127 | //最终生成的订单号,固定前2位:LF 128 | try { 129 | synchronized (lockObj) { 130 | //取系统当前时间,精确到毫秒 131 | long nowLong = Long.parseLong(new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date())); 132 | //计数器到最大值归零 133 | if (orderNumCounter > maxPerMSECSize) { 134 | orderNumCounter = 0L; 135 | } 136 | //组装订单号 137 | String countStr = maxPerMSECSize + orderNumCounter + ""; 138 | orderId += nowLong + countStr.substring(1); 139 | orderNumCounter++; 140 | } 141 | } catch (Exception e) { 142 | e.printStackTrace(); 143 | } 144 | return orderId; 145 | } 146 | 147 | public static void main(String[] args) { 148 | // 测试多线程调用订单号生成工具 149 | try { 150 | for (int i = 0; i < 100000; i++) { 151 | Thread t1 = new Thread(new Runnable() { 152 | public void run() { 153 | OrderUtil.getInstance().makeOrderNo(); 154 | } 155 | }, "at" + i); 156 | t1.start(); 157 | 158 | Thread t2 = new Thread(new Runnable() { 159 | public void run() { 160 | OrderUtil.getInstance().makeOrderNo(); 161 | } 162 | }, "bt" + i); 163 | t2.start(); 164 | } 165 | } catch (Exception e) { 166 | e.printStackTrace(); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/PropertyHelper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by sungang on 2017/4/17. 9 | */ 10 | public class PropertyHelper { 11 | 12 | /** 13 | * 不为null的属性 14 | * 15 | * @param o 16 | * @param _class 17 | * @param map 18 | * @return 19 | */ 20 | public static Map recursiveNotNull(Object o, Class _class, 21 | Map map) { 22 | if (_class == null) { 23 | return map; 24 | } else { 25 | Field[] field = _class.getDeclaredFields(); // 获取实体类的所有属性,返回Field数组 26 | // 遍历方法集合 27 | for (int j = 0; j < field.length; j++) { // 遍历所有属性 28 | 29 | String name1 = field[j].getName(); // 获取属性的名字 30 | // System.out.println("attribute name:"+name); 31 | String name2 = name1.substring(0, 1).toUpperCase() 32 | + name1.substring(1); // 将属性的首字符大写,方便构造get,set方法 33 | Object obj = null; 34 | Method m; 35 | try { 36 | m = _class.getMethod("get" + name2); 37 | m.setAccessible(true); 38 | obj = m.invoke(o); 39 | } catch (Exception e) { 40 | // TODO Auto-generated catch block 41 | e.printStackTrace(); 42 | } 43 | if (obj != null) { 44 | map.put(name1, obj); 45 | } 46 | } 47 | return recursiveNotNull(o, _class.getSuperclass(), map); 48 | } 49 | } 50 | 51 | /** 52 | * 所有属性 53 | * 54 | * @param o 55 | * @param _class 56 | * @param map 57 | * @return 58 | */ 59 | public static Map recursiveAll(Object o, Class _class, 60 | Map map) { 61 | if (_class == null) { 62 | return map; 63 | } else { 64 | Field[] field = _class.getDeclaredFields(); // 获取实体类的所有属性,返回Field数组 65 | // 遍历方法集合 66 | for (int j = 0; j < field.length; j++) { // 遍历所有属性 67 | 68 | String name1 = field[j].getName(); // 获取属性的名字 69 | // System.out.println("attribute name:"+name); 70 | String name2 = name1.substring(0, 1).toUpperCase() 71 | + name1.substring(1); // 将属性的首字符大写,方便构造get,set方法 72 | Object obj = null; 73 | Method m; 74 | try { 75 | m = _class.getMethod("get" + name2); 76 | m.setAccessible(true); 77 | obj = m.invoke(o); 78 | } catch (Exception e) { 79 | // TODO Auto-generated catch block 80 | e.printStackTrace(); 81 | } 82 | if (obj != null) { 83 | map.put(name1, obj); 84 | } 85 | } 86 | return recursiveAll(o, _class.getSuperclass(), map); 87 | } 88 | } 89 | 90 | 91 | /** 92 | * 反射后附加对象 93 | * 94 | * @param entityClass 95 | * @param entityMap 96 | * @return 97 | */ 98 | public static Object getFansheObj(Class entityClass, Map entityMap) { 99 | Object t = null; 100 | try { 101 | t = Class.forName(entityClass.getName()).newInstance(); 102 | Field[] field = t.getClass().getDeclaredFields(); // 获取实体类的所有属性,返回Field数组 103 | for (int j = 0; j < field.length; j++) { // 遍历所有属性 104 | String yname = field[j].getName(); // 获取属性的名字 105 | String name = yname.substring(0, 1).toUpperCase() + yname.substring(1); // 将属性的首字符大写,方便构造get,set方法 106 | String type = field[j].getGenericType().toString(); // 获取属性的类型 107 | // if (type.equals("class java.lang.String")) { // 如果type是类类型,则前面包含"class ",后面跟类名 108 | Method m = t.getClass().getMethod("get" + name); 109 | String value = (String) m.invoke(t); // 调用getter方法获取属性值 110 | if (value == null) { 111 | m = t.getClass().getMethod("set" + name, Class.forName(type.split(" ")[1])); 112 | m.invoke(t, entityMap.get(yname)); 113 | //} 114 | } 115 | /*if (type.equals("class java.lang.Integer")) { 116 | Method m = t.getClass().getMethod("get" + name); 117 | Integer value = (Integer) m.invoke(t); 118 | if (value == null) { 119 | m = t.getClass().getMethod("set"+name,Integer.class); 120 | m.invoke(t, 0); 121 | } 122 | } 123 | if (type.equals("class java.lang.Boolean")) { 124 | Method m = t.getClass().getMethod("get" + name); 125 | Boolean value = (Boolean) m.invoke(t); 126 | if (value == null) { 127 | m = t.getClass().getMethod("set"+name,Boolean.class); 128 | m.invoke(t, false); 129 | } 130 | } 131 | if (type.equals("class java.util.Date")) { 132 | Method m = t.getClass().getMethod("get" + name); 133 | Date value = (Date) m.invoke(t); 134 | if (value == null) { 135 | m = t.getClass().getMethod("set"+name,Date.class); 136 | m.invoke(t, new Date()); 137 | } 138 | }*/ 139 | 140 | // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断 141 | } 142 | } catch (Exception e) { 143 | e.printStackTrace(); 144 | } 145 | return t; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/RamUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import com.chinawiserv.utils.ztree.ZtreeNode; 4 | import com.google.common.collect.Maps; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 本地内存工具 11 | * Created by sungang on 2017/5/5. 12 | */ 13 | public class RamUtils { 14 | 15 | 16 | private static RamUtils instance; 17 | 18 | private RamUtils() { 19 | } 20 | 21 | public static RamUtils getInstance() { 22 | if (instance == null) { 23 | instance = new RamUtils(); 24 | } 25 | return instance; 26 | } 27 | 28 | 29 | private Map> erpCategoryMap = Maps.newConcurrentMap(); 30 | 31 | public void setErpCategory(Long key, List ztreeNodes) { 32 | erpCategoryMap.put(key, ztreeNodes); 33 | } 34 | 35 | public List getErpCategory(Long key) { 36 | return erpCategoryMap.get(key); 37 | } 38 | 39 | public void removeErpCategory(Long key){ 40 | erpCategoryMap.remove(key); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/RandomUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | /** 4 | * Created by sungang on 2017/9/23. 5 | */ 6 | public class RandomUtils { 7 | } 8 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/ReflectUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | 6 | /** 7 | * Created by sungang on 2016/6/10. 8 | */ 9 | public class ReflectUtils { 10 | 11 | /** 12 | * 得到指定类型的指定位置的泛型实参 13 | * 14 | * @param clazz 15 | * @param index 16 | * @param 17 | * @return 18 | */ 19 | public static Class findParameterizedType(Class clazz, int index) { 20 | Type parameterizedType = clazz.getGenericSuperclass(); 21 | //CGLUB subclass target object(泛型在父类上) 22 | if (!(parameterizedType instanceof ParameterizedType)) { 23 | parameterizedType = clazz.getSuperclass().getGenericSuperclass(); 24 | } 25 | if (!(parameterizedType instanceof ParameterizedType)) { 26 | return null; 27 | } 28 | Type[] actualTypeArguments = ((ParameterizedType) parameterizedType).getActualTypeArguments(); 29 | if (actualTypeArguments == null || actualTypeArguments.length == 0) { 30 | return null; 31 | } 32 | return (Class) actualTypeArguments[0]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/TenpayUtil.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | 7 | public class TenpayUtil { 8 | 9 | private static Object Server; 10 | private static String QRfromGoogle; 11 | 12 | /** 13 | * 把对象转换成字符串 14 | * @param obj 15 | * @return String 转换成字符串,若对象为null,则返回空字符串. 16 | */ 17 | public static String toString(Object obj) { 18 | if(obj == null) 19 | return ""; 20 | 21 | return obj.toString(); 22 | } 23 | 24 | /** 25 | * 把对象转换为int数值. 26 | * 27 | * @param obj 28 | * 包含数字的对象. 29 | * @return int 转换后的数值,对不能转换的对象返回0。 30 | */ 31 | public static int toInt(Object obj) { 32 | int a = 0; 33 | try { 34 | if (obj != null) 35 | a = Integer.parseInt(obj.toString()); 36 | } catch (Exception e) { 37 | 38 | } 39 | return a; 40 | } 41 | 42 | /** 43 | * 获取当前时间 yyyyMMddHHmmss 44 | * @return String 45 | */ 46 | public static String getCurrTime() { 47 | Date now = new Date(); 48 | SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 49 | String s = outFormat.format(now); 50 | return s; 51 | } 52 | 53 | /** 54 | * 获取当前日期 yyyyMMdd 55 | * @param date 56 | * @return String 57 | */ 58 | public static String formatDate(Date date) { 59 | SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd"); 60 | String strDate = formatter.format(date); 61 | return strDate; 62 | } 63 | 64 | /** 65 | * 取出一个指定长度大小的随机正整数. 66 | * 67 | * @param length 68 | * int 设定所取出随机数的长度。length小于11 69 | * @return int 返回生成的随机数。 70 | */ 71 | public static int buildRandom(int length) { 72 | int num = 1; 73 | double random = Math.random(); 74 | if (random < 0.1) { 75 | random = random + 0.1; 76 | } 77 | for (int i = 0; i < length; i++) { 78 | num = num * 10; 79 | } 80 | return (int) ((random * num)); 81 | } 82 | 83 | public static String URLencode(String content){ 84 | 85 | String URLencode; 86 | 87 | URLencode= replace(Server.equals(content), "+", "%20"); 88 | 89 | return URLencode; 90 | } 91 | private static String replace(boolean equals, String string, String string2) { 92 | 93 | return null; 94 | } 95 | 96 | /** 97 | * 获取unix时间,从1970-01-01 00:00:00开始的秒数 98 | * @param date 99 | * @return long 100 | */ 101 | public static long getUnixTime(Date date) { 102 | if( null == date ) { 103 | return 0; 104 | } 105 | 106 | return date.getTime()/1000; 107 | } 108 | 109 | public static String QRfromGoogle(String chl) 110 | { 111 | int widhtHeight = 300; 112 | String EC_level = "L"; 113 | int margin = 0; 114 | String QRfromGoogle; 115 | chl = URLencode(chl); 116 | 117 | QRfromGoogle = "http://chart.apis.google.com/chart?chs=" + widhtHeight + "x" + widhtHeight + "&cht=qr&chld=" + EC_level + "|" + margin + "&chl=" + chl; 118 | 119 | return QRfromGoogle; 120 | } 121 | 122 | /** 123 | * 时间转换成字符串 124 | * @param date 时间 125 | * @param formatType 格式化类型 126 | * @return String 127 | */ 128 | public static String date2String(Date date, String formatType) { 129 | SimpleDateFormat sdf = new SimpleDateFormat(formatType); 130 | return sdf.format(date); 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/data/Uuid.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.data; 2 | 3 | import java.util.Random; 4 | import java.util.UUID; 5 | 6 | public class Uuid { 7 | public static String uuid() { 8 | return UUID.randomUUID().toString(); 9 | } 10 | 11 | public static long longUuid() { 12 | return UUID.randomUUID().getMostSignificantBits(); 13 | } 14 | 15 | public static String replaceLine(String str) { 16 | return str.replaceAll("-", ""); 17 | } 18 | 19 | public static void main(String[] args) { 20 | 21 | System.out.println(replaceLine(Uuid.uuid())); 22 | } 23 | 24 | /** 25 | * @描述:java产生随机手机验证码 26 | * @参数名: @return 27 | * @返回类型 Integer 28 | * @throws 29 | */ 30 | public static String getPhoneCode() { 31 | int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 32 | Random rand = new Random(); 33 | for (int i = 10; i > 1; i--) { 34 | int index = rand.nextInt(i); 35 | int tmp = array[index]; 36 | array[index] = array[i - 1]; 37 | array[i - 1] = tmp; 38 | } 39 | String result = ""; 40 | for (int i = 0; i < 6; i++) { 41 | result += array[i]+""; 42 | } 43 | return result; 44 | } 45 | 46 | 47 | /** 48 | * 49 | * @Title: getRandomPwd 50 | * @Description: TODO 获取随机的6位数字密码 51 | * @param @return 参数 52 | * @return String 返回类型 53 | * @throws 54 | */ 55 | public static String getRandomPwd() { 56 | int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 57 | Random rand = new Random(); 58 | for (int i = 10; i > 1; i--) { 59 | int index = rand.nextInt(i); 60 | int tmp = array[index]; 61 | array[index] = array[i - 1]; 62 | array[i - 1] = tmp; 63 | } 64 | String result = ""; 65 | for (int i = 0; i < 6; i++) { 66 | result += array[i]+""; 67 | } 68 | return result; 69 | } 70 | 71 | public static String get32UUID() { 72 | String uuid = UUID.randomUUID().toString().trim().replaceAll("-", ""); 73 | return uuid; 74 | } 75 | 76 | 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/encryption/EncryptionHelper.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.encryption; 2 | 3 | import sun.misc.BASE64Encoder; 4 | 5 | import java.security.MessageDigest; 6 | 7 | /** 8 | * Created by sungang on 2017/3/31. 9 | */ 10 | public class EncryptionHelper { 11 | //加密 12 | public static String encrypt(String word) { 13 | String result = ""; 14 | try { 15 | String KEY_SHA = "SHA"; 16 | MessageDigest sha = MessageDigest.getInstance(KEY_SHA); 17 | sha.update(word.getBytes()); 18 | byte[] result1 = sha.digest(); 19 | result = (new BASE64Encoder()).encodeBuffer(result1).replaceAll("\\r\\n","").trim(); 20 | } catch (Exception ex) { 21 | result = word; 22 | } 23 | 24 | return result; 25 | } 26 | 27 | public static void main(String[] args) { 28 | String encrypt_pwd = EncryptionHelper.encrypt("111111"); 29 | System.out.println(encrypt_pwd); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/encryption/MD5Utils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.encryption; 2 | 3 | import java.io.*; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | 8 | public final class MD5Utils { 9 | 10 | /** 11 | * 12 | * 16进制数值 13 | */ 14 | 15 | private static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 16 | 17 | /** 18 | * 19 | * 日志 20 | */ 21 | 22 | 23 | /** 24 | * 25 | * 生成MD5加密校验码 26 | * 27 | * @param string 28 | * 待加密字符串 29 | * 30 | * @return MD5加密校验码 31 | * 32 | * @since 0.2 33 | */ 34 | 35 | public static String md5(String string) { 36 | 37 | return encryptString(getEncrypt("MD5"), string); 38 | 39 | } 40 | 41 | /** 42 | * 43 | * 生成MD5加密校验码 44 | * 45 | * @param file 46 | * 待加密文件 47 | * 48 | * @return MD5加密校验码 49 | * 50 | * @since 0.2 51 | */ 52 | 53 | public static String md5(File file) { 54 | 55 | return encryptFile(getEncrypt("MD5"), file); 56 | 57 | } 58 | 59 | /** 60 | * 获取MD5再次换位的字符串 61 | * 62 | * @param string 63 | * @return 64 | */ 65 | public static String md5Passwd(String string) { 66 | String pass = md5(string); 67 | return pass.substring(11) + pass.substring(0, 11); 68 | } 69 | 70 | /** 71 | * 72 | * 生成SHA1加密校验码 73 | * 74 | * @param string 75 | * 待加密字符串 76 | * 77 | * @return SHA1加密校验码 78 | * 79 | * @since 0.2 80 | */ 81 | 82 | public static String sha1(String string) { 83 | 84 | return encryptString(getEncrypt("SHA1"), string); 85 | 86 | } 87 | 88 | /** 89 | * 90 | * 生成SHA1加密校验码 91 | * 92 | * @param file 93 | * 待加密文件 94 | * 95 | * @return SHA1加密校验码 96 | * 97 | * @since 0.2 98 | */ 99 | 100 | public static String sha1(File file) { 101 | 102 | return encryptFile(getEncrypt("SHA1"), file); 103 | 104 | } 105 | 106 | /** 107 | * 108 | * 获得指定的算法加密器 109 | * 110 | * @param algorithm 111 | * 算法 112 | * 113 | * @throws CatGroupException 114 | * 如果没有参数algorithm指定的加密算法则抛出此异常 115 | * 116 | * @return 加密器 117 | * 118 | * @since 0.2 119 | */ 120 | 121 | private static MessageDigest getEncrypt(String algorithm) { 122 | 123 | try { 124 | 125 | return MessageDigest.getInstance(algorithm); 126 | 127 | } catch (NoSuchAlgorithmException ex) { 128 | 129 | return null; 130 | 131 | } 132 | 133 | } 134 | 135 | /** 136 | * 137 | * 计算结果转为16进制表示 138 | * 139 | * @param bytes 140 | * 待转换Byte数组 141 | * 142 | * @return 转换结果 143 | * 144 | * @since 0.2 145 | */ 146 | 147 | private static String bytesToHex(byte[] bytes) { 148 | 149 | int length = bytes.length; 150 | 151 | StringBuilder sb = new StringBuilder(2 * length); 152 | 153 | for (int i = 0; i < length; i++) { 154 | 155 | sb.append(hexDigits[(bytes[i] & 0xf0) >> 4]); 156 | 157 | sb.append(hexDigits[bytes[i] & 0xf]); 158 | 159 | } 160 | 161 | return sb.toString(); 162 | 163 | } 164 | 165 | /** 166 | * 167 | * 使用加密器对目标字符串进行加密 168 | * 169 | * @param digest 170 | * 加密器 171 | * 172 | * @param string 173 | * 目标字符串 174 | * 175 | * @return 计算结果 176 | * 177 | * @since 0.2 178 | */ 179 | 180 | private static String encryptString(MessageDigest digest, String string) { 181 | 182 | return bytesToHex(digest.digest(string.getBytes())); 183 | 184 | } 185 | 186 | /** 187 | * 188 | * 使用加密器对目标文件进行加密 189 | * 190 | * @param digest 191 | * 加密器 192 | * 193 | * @param file 194 | * 目标文件 195 | * 196 | * @throws CatGroupException 197 | * 当文件未找到或读取错误时抛出此异常 198 | * 199 | * @return 计算结果 200 | * 201 | * @since 0.2 202 | */ 203 | 204 | private static String encryptFile(MessageDigest digest, File file) { 205 | 206 | InputStream fis = null; 207 | 208 | try { 209 | 210 | fis = new FileInputStream(file); 211 | 212 | byte[] buffer = new byte[1024]; 213 | 214 | int numRead = 0; 215 | 216 | while ((numRead = fis.read(buffer)) > 0) { 217 | 218 | digest.update(buffer, 0, numRead); 219 | 220 | } 221 | 222 | } catch (FileNotFoundException ex) { 223 | 224 | 225 | return null; 226 | 227 | } catch (IOException ex) { 228 | 229 | 230 | return null; 231 | 232 | } finally { 233 | 234 | try { 235 | 236 | fis.close(); 237 | 238 | } catch (IOException ex) { 239 | 240 | 241 | return null; 242 | 243 | } 244 | 245 | } 246 | 247 | return bytesToHex(digest.digest()); 248 | 249 | } 250 | public static void main(String[] args) { 251 | System.out.print(md5("123abc")); 252 | } 253 | 254 | } 255 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/excel/DownloadDatas.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.excel; 2 | 3 | import com.google.common.collect.Maps; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: wangt 10 | * Date: 17-4-1 11 | * Time: 上午11:39 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class DownloadDatas { 15 | 16 | public static Map getShopMap(){ 17 | Map map = Maps.newLinkedHashMap(); 18 | map.put("店铺名称","shop_name"); 19 | return map; 20 | } 21 | 22 | public static Map getCommentMap(){ 23 | Map map = Maps.newLinkedHashMap(); 24 | map.put("内容","content"); 25 | return map; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/excel/DownloadExcelUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.excel; 2 | 3 | import jxl.SheetSettings; 4 | import jxl.Workbook; 5 | import jxl.format.UnderlineStyle; 6 | import jxl.write.*; 7 | import jxl.write.Number; 8 | 9 | import java.io.OutputStream; 10 | import java.text.SimpleDateFormat; 11 | import java.util.*; 12 | 13 | /** 14 | * Created with IntelliJ IDEA. 15 | * User: wangt 16 | * Date: 17-3-31 17 | * Time: 下午5:51 18 | * To change this template use File | Settings | File Templates. 19 | */ 20 | public class DownloadExcelUtils { 21 | 22 | public static void download(OutputStream os, List> results, Map titlesMap) throws Exception { 23 | //创建工作簿 24 | WritableWorkbook wwb = null; 25 | try { 26 | wwb = Workbook.createWorkbook(os); 27 | writeExcel(titlesMap,"列表",0,wwb,results); 28 | 29 | //写入工作薄 30 | wwb.write(); 31 | } catch (Exception e) { 32 | e.printStackTrace(); 33 | } finally { 34 | wwb.write(); 35 | if (wwb != null) { 36 | //关闭文件 37 | wwb.close(); 38 | wwb = null; 39 | } 40 | } 41 | } 42 | 43 | public static void writeExcel(Map map, String sheetName, int k, WritableWorkbook wwb, List> results) throws Exception { 44 | //创建工作表 45 | WritableSheet sheet = wwb.createSheet(sheetName, k); 46 | SheetSettings settings = sheet.getSettings(); 47 | settings.setVerticalFreeze(1);//冻结表头 48 | //标题样式 49 | WritableCellFormat wcf_title = setTitleStyle(); 50 | //内容样式 51 | WritableCellFormat wcf_left = setContentStyle(); 52 | //标题 53 | Set fieldTitle = map.keySet(); 54 | Iterator iterator = fieldTitle.iterator(); 55 | int index = 0; 56 | while (iterator.hasNext()) { 57 | Label label = new Label(index, 0, iterator.next().toString(), wcf_title); 58 | sheet.addCell(label); 59 | sheet.setColumnView(index, 20);//设置列宽 60 | index++; 61 | } 62 | int rowIndex = 1;//行索引:第1行是标题,内容从第2行开始 63 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 64 | //写到excel文件中 65 | for( Map row : results ) { 66 | Collection list = map.values(); 67 | Iterator valueIterator = list.iterator(); 68 | int colIndex = 0;//列索引:从第1列开始 69 | while(valueIterator.hasNext()){ 70 | Object val = row.get(valueIterator.next()); 71 | if(val instanceof Double){ 72 | sheet.addCell(new Number(colIndex++, rowIndex, Double.parseDouble(val.toString()), wcf_left)); 73 | }else if(val instanceof Integer){ 74 | sheet.addCell(new Number(colIndex++, rowIndex, Integer.parseInt(val.toString()), wcf_left)); 75 | }else if(val instanceof Date){ 76 | String date = sdf.format((Date)val); 77 | sheet.addCell(new Label(colIndex++, rowIndex, date, wcf_left)); 78 | }else{ 79 | sheet.addCell(new Label(colIndex++, rowIndex, val.toString(), wcf_left)); 80 | } 81 | } 82 | rowIndex++; 83 | } 84 | } 85 | 86 | /** 87 | * 设置标题样式 88 | * @return 89 | */ 90 | private static WritableCellFormat setTitleStyle(){ 91 | WritableCellFormat wcf_center = null; 92 | try { 93 | //设置单元格字体:字体 大小 下划线 斜体 粗体 颜色 94 | WritableFont BoldFont = new WritableFont(WritableFont.ARIAL, 12, WritableFont.BOLD,false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK); 95 | //设置样式:用于标题居中 96 | wcf_center = new WritableCellFormat(BoldFont); 97 | wcf_center.setBorder(Border.ALL, BorderLineStyle.THIN); //边框 98 | wcf_center.setVerticalAlignment(VerticalAlignment.CENTRE); //垂直对齐 99 | wcf_center.setAlignment(Alignment.CENTRE); //水平对齐 100 | wcf_center.setWrap(false); //是否换行 101 | }catch (Exception e){ 102 | e.printStackTrace(); 103 | } 104 | return wcf_center; 105 | } 106 | /** 107 | * 设置内容样式 108 | * @return 109 | */ 110 | private static WritableCellFormat setContentStyle(){ 111 | WritableCellFormat wcf_left = null; 112 | try { 113 | //设置单元格字体:字体 大小 下划线 斜体 粗体 颜色 114 | WritableFont NormalFont = new WritableFont(WritableFont.ARIAL, 10,WritableFont.NO_BOLD,false,UnderlineStyle.NO_UNDERLINE,Colour.BLACK); 115 | //设置样式:用于正文居左 116 | wcf_left = new WritableCellFormat(NormalFont); 117 | wcf_left.setBorder(Border.NONE, BorderLineStyle.THIN); //边框 118 | wcf_left.setVerticalAlignment(VerticalAlignment.CENTRE); //垂直对齐 119 | wcf_left.setAlignment(Alignment.LEFT); //水平对齐 120 | wcf_left.setWrap(false); //是否换行 121 | }catch (Exception e){ 122 | e.printStackTrace(); 123 | } 124 | return wcf_left; 125 | } 126 | 127 | public static String ObjToStrTool(Object obj){ 128 | String str = ""; 129 | if (null==obj){ 130 | return str; 131 | }else { 132 | str = obj.toString(); 133 | } 134 | return str; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/kaptcha/KaptchaUtils.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.kaptcha; 2 | 3 | /** 4 | * Created by sungang on 2017/9/22. 5 | */ 6 | public class KaptchaUtils { 7 | } 8 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/sensitive/SensitiveNode.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.sensitive; 2 | 3 | import java.io.Serializable; 4 | import java.util.TreeSet; 5 | 6 | /** 7 | * 敏感词节点,每个节点包含了以相同的2个字符开头的所有词 8 | *

9 | * Created by sungang on 2017/5/31. 10 | */ 11 | public class SensitiveNode implements Serializable { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | /** 16 | * 头两个字符的mix,mix相同,两个字符相同 17 | */ 18 | protected final int headTwoCharMix; 19 | 20 | /** 21 | * 所有以这两个字符开头的词表 22 | */ 23 | protected final TreeSet words = new TreeSet(); 24 | 25 | /** 26 | * 下一个节点 27 | */ 28 | protected SensitiveNode next; 29 | 30 | public SensitiveNode(int headTwoCharMix) { 31 | this.headTwoCharMix = headTwoCharMix; 32 | } 33 | 34 | public SensitiveNode(int headTwoCharMix, SensitiveNode parent) { 35 | this.headTwoCharMix = headTwoCharMix; 36 | parent.next = this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/sensitive/StringPointer.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.sensitive; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by sungang on 2017/5/31. 7 | *

8 | * 没有注释的方法与{@link String}类似
9 | * 注意:没有(数组越界等的)安全检查
10 | * 可以作为{@link HashMap}和{@link TreeMap}的key 11 | */ 12 | public class StringPointer implements Serializable, CharSequence, Comparable { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | protected final char[] value; 17 | 18 | protected final int offset; 19 | 20 | protected final int length; 21 | 22 | private int hash = 0; 23 | 24 | public StringPointer(String str) { 25 | value = str.toCharArray(); 26 | offset = 0; 27 | length = value.length; 28 | } 29 | 30 | public StringPointer(char[] value, int offset, int length) { 31 | this.value = value; 32 | this.offset = offset; 33 | this.length = length; 34 | } 35 | 36 | /** 37 | * 计算该位置后(包含)2个字符的hash值 38 | * 39 | * @param i 从 0 到 length - 2 40 | * @return hash值 41 | * @author ZhangXiaoye 42 | * @date 2017年1月5日 下午2:23:02 43 | */ 44 | public int nextTwoCharHash(int i) { 45 | return 31 * value[offset + i] + value[offset + i + 1]; 46 | } 47 | 48 | /** 49 | * 计算该位置后(包含)2个字符和为1个int型的值
50 | * int值相同表示2个字符相同 51 | * 52 | * @param i 从 0 到 length - 2 53 | * @return int值 54 | * @author ZhangXiaoye 55 | * @date 2017年1月5日 下午2:46:58 56 | */ 57 | public int nextTwoCharMix(int i) { 58 | return (value[offset + i] << 16) | value[offset + i + 1]; 59 | } 60 | 61 | /** 62 | * 该位置后(包含)的字符串,是否以某个词(word)开头 63 | * 64 | * @param i 从 0 到 length - 2 65 | * @param word 词 66 | * @return 是否? 67 | * @author ZhangXiaoye 68 | * @date 2017年1月5日 下午3:13:49 69 | */ 70 | public boolean nextStartsWith(int i, StringPointer word) { 71 | // 是否长度超出 72 | if (word.length > length - i) { 73 | return false; 74 | } 75 | // 从尾开始判断 76 | for (int c = word.length - 1; c >= 0; c--) { 77 | if (value[offset + i + c] != word.value[word.offset + c]) { 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | /** 85 | * 填充(替换) 86 | * 87 | * @param begin 从此位置开始(含) 88 | * @param end 到此位置结束(不含) 89 | * @param fillWith 以此字符填充(替换) 90 | * @author ZhangXiaoye 91 | * @date 2017年1月5日 下午3:29:21 92 | */ 93 | public void fill(int begin, int end, char fillWith) { 94 | for (int i = begin; i < end; i++) { 95 | value[offset + i] = fillWith; 96 | } 97 | } 98 | 99 | public int length() { 100 | return length; 101 | } 102 | 103 | public char charAt(int i) { 104 | return value[offset + i]; 105 | } 106 | 107 | public StringPointer substring(int begin) { 108 | return new StringPointer(value, offset + begin, length - begin); 109 | } 110 | 111 | public StringPointer substring(int begin, int end) { 112 | return new StringPointer(value, offset + begin, end - begin); 113 | } 114 | 115 | @Override 116 | public CharSequence subSequence(int start, int end) { 117 | return substring(start, end); 118 | } 119 | 120 | public String toString() { 121 | return new String(value, offset, length); 122 | } 123 | 124 | public int hashCode() { 125 | int h = hash; 126 | if (h == 0 && length > 0) { 127 | for (int i = 0; i < length; i++) { 128 | h = 31 * h + value[offset + i]; 129 | } 130 | hash = h; 131 | } 132 | return h; 133 | } 134 | 135 | public boolean equals(Object anObject) { 136 | if (this == anObject) { 137 | return true; 138 | } 139 | if (anObject instanceof StringPointer) { 140 | StringPointer that = (StringPointer) anObject; 141 | if (length == that.length) { 142 | char v1[] = this.value; 143 | char v2[] = that.value; 144 | for (int i = 0; i < this.length; i++) { 145 | if (v1[this.offset + i] != v2[that.offset + i]) { 146 | return false; 147 | } 148 | } 149 | return true; 150 | } 151 | } 152 | return false; 153 | } 154 | 155 | @Override 156 | public int compareTo(StringPointer that) { 157 | int len1 = this.length; 158 | int len2 = that.length; 159 | int lim = Math.min(len1, len2); 160 | char v1[] = this.value; 161 | char v2[] = that.value; 162 | 163 | int k = 0; 164 | while (k < lim) { 165 | char c1 = v1[this.offset + k]; 166 | char c2 = v2[that.offset + k]; 167 | if (c1 != c2) { 168 | return c1 - c2; 169 | } 170 | k++; 171 | } 172 | return len1 - len2; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/thread/Sequence.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.thread; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.Random; 6 | import java.util.UUID; 7 | 8 | /** 9 | * Created by sungang on 2017/8/16. 10 | */ 11 | public class Sequence { 12 | 13 | private static Integer DEFAULT_LENGTH = 10; 14 | 15 | private final static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyMMddHHmmss"); 16 | 17 | private static final String NUMBER_CHAR = "1234567890"; 18 | 19 | private final static int PIX_LEN = NUMBER_CHAR.length(); 20 | 21 | private static volatile int pixOne = 0; 22 | private static volatile int pixTwo = 0; 23 | private static volatile int pixThree = 0; 24 | 25 | 26 | private Sequence(){} 27 | 28 | /** 29 | * 生成一个uuid字符串 30 | *

Function: uuid

31 | *

Description:

32 | * @author zhaoxy@thankjava.com 33 | * @date 2016年1月5日 下午2:11:58 34 | * @version 1.0 35 | * @return 返回String数组, 长度为2 下标为:0是去除中划线后的uuidString 下标:1是原始的uuidString 36 | */ 37 | public static String[] uuid(){ 38 | String uuidStr = UUID.randomUUID().toString(); 39 | String[] uuidStrs = new String[2]; 40 | uuidStrs[0] = uuidStr.replace("-", ""); 41 | uuidStrs[1] = uuidStr; 42 | return uuidStrs; 43 | } 44 | 45 | /** 46 | * 按照时间戳&随机3位数生成唯一seq 47 | *

Function: generateUnique

48 | *

Description: 最大可并发约1000 随机器性能增加而并发数减少

49 | * @author zhaoxy@thankjava.com 50 | * @date 2016年1月5日 下午2:53:18 51 | * @version 1.0 52 | * @return 53 | */ 54 | public synchronized static Long generateUnique() { 55 | String dateStr = SIMPLE_DATE_FORMAT.format(new Date()); 56 | pixThree++; 57 | if (pixThree == PIX_LEN) { 58 | pixThree = 0; 59 | pixTwo++; 60 | if (pixTwo == PIX_LEN) { 61 | pixTwo = 0; 62 | pixOne++; 63 | if (pixOne == PIX_LEN) { 64 | pixOne = 0; 65 | } 66 | } 67 | } 68 | StringBuffer sb = new StringBuffer(); 69 | sb.append(dateStr); 70 | sb.append(NUMBER_CHAR.charAt(pixOne)); 71 | sb.append(NUMBER_CHAR.charAt(pixTwo)); 72 | sb.append(NUMBER_CHAR.charAt(pixThree)); 73 | return Long.valueOf(sb.toString()); 74 | } 75 | 76 | /** 77 | * 随机生成指定位数字符 78 | *

Function: generateNum

79 | *

Description:

80 | * @author zhaoxy@thankjava.com 81 | * @date 2016年1月5日 下午3:05:31 82 | * @version 1.0 83 | * @param length 84 | * @return 85 | */ 86 | public static String generateChar(int length) { 87 | length = length <= 0 ? DEFAULT_LENGTH : length; 88 | StringBuilder sb = new StringBuilder(); 89 | Random rand = new Random();// 随机用以下三个随机生成器 90 | Random randData = new Random(); 91 | int data = 0; 92 | for (int i = 0; i < length; i++) { 93 | int index = rand.nextInt(3); 94 | // 目的是随机选择生成数字,大小写字母 95 | switch (index) { 96 | case 0: 97 | data = randData.nextInt(10);// 仅仅会生成0~9 98 | sb.append(data); 99 | break; 100 | case 1: 101 | data = randData.nextInt(26) + 65;// 保证只会产生65~90之间的整数 102 | sb.append((char) data); 103 | break; 104 | case 2: 105 | data = randData.nextInt(26) + 97;// 保证只会产生97~122之间的整数 106 | sb.append((char) data); 107 | break; 108 | } 109 | } 110 | return sb.toString(); 111 | } 112 | 113 | /** 114 | * 生成指定长度的纯数字 115 | *

Function: generateNum

116 | *

Description:

117 | * @author zhaoxy@thankjava.com 118 | * @date 2016年1月5日 下午3:13:50 119 | * @version 1.0 120 | * @param length 121 | * @return 122 | */ 123 | public static String generateNum(int length) { 124 | length = length <= 0 ? DEFAULT_LENGTH : length; 125 | StringBuilder sb = new StringBuilder(); 126 | Random rand = new Random(); 127 | for (int i = 0; i < length; i++) { 128 | sb.append(rand.nextInt(10)); 129 | } 130 | String data = sb.toString(); 131 | return data; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/thread/TaskEntity.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.thread; 2 | 3 | /** 4 | * Created by sungang on 2017/8/16. 5 | */ 6 | public class TaskEntity { 7 | 8 | 9 | /** 10 | * 任务id 11 | */ 12 | private String taskId; 13 | 14 | /** 15 | * 任务间隔时间 16 | */ 17 | private int timeInterval = 0; 18 | 19 | /** 20 | * 任务启动延迟时间 21 | */ 22 | private int startDelayTime = 0; 23 | 24 | /** 25 | * 任务执行体 26 | */ 27 | private Runnable runnable; 28 | 29 | public String getTaskId() { 30 | return taskId; 31 | } 32 | 33 | public int getTimeInterval() { 34 | return timeInterval; 35 | } 36 | 37 | public int getStartDelayTime() { 38 | return startDelayTime; 39 | } 40 | 41 | public Runnable getRunnable() { 42 | return runnable; 43 | } 44 | 45 | /** 46 | * 初始化对象 47 | * 48 | * @param startDelayTime(s) 49 | * @param timeInterval 任务周期性启动的间隔,时间不能小于0(s) 50 | * @param runnable 执行体 51 | */ 52 | public TaskEntity(int startDelayTime, int timeInterval, Runnable runnable) { 53 | if (startDelayTime < 0) { 54 | throw new IllegalArgumentException("timeInterval must greater than -1"); 55 | } 56 | if (timeInterval <= 0) { 57 | throw new IllegalArgumentException("timeInterval must greater than 0"); 58 | } 59 | 60 | this.taskId = Sequence.generateChar(6); 61 | this.timeInterval = timeInterval; 62 | this.runnable = runnable; 63 | this.startDelayTime = startDelayTime; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/thread/ThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.thread; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.ThreadPoolExecutor; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * Created by sungang on 2017/8/16. 9 | */ 10 | public class ThreadPool { 11 | 12 | /** 13 | * 核心线程保持数量 14 | */ 15 | private static final int INIT_THREAD_NUM = 50; 16 | 17 | /** 18 | * 工作线程最大数量 19 | */ 20 | private static final int MAX_THREAD_NUM = 10000; 21 | 22 | /** 23 | * 空闲线程最大等待时间 24 | */ 25 | private static final int ALIVE_TIME = 1000; 26 | 27 | /** 28 | * 排队任务接受最大数目 29 | */ 30 | private static final int WAIT_RUNABLE_MAX_NUM = 200; 31 | 32 | private static ThreadPoolExecutor threadPoolExecutor; 33 | 34 | public ThreadPool() { 35 | threadPoolExecutor = new ThreadPoolExecutor( 36 | INIT_THREAD_NUM, 37 | MAX_THREAD_NUM, 38 | ALIVE_TIME, 39 | TimeUnit.MILLISECONDS, 40 | new ArrayBlockingQueue(WAIT_RUNABLE_MAX_NUM), 41 | new ThreadPoolExecutor.DiscardOldestPolicy()); 42 | threadPoolExecutor.allowCoreThreadTimeOut(true); 43 | } 44 | 45 | /** 46 | * 指定线程池配置 47 | *

Title:

48 | *

Description:

49 | * 50 | * @param initThreadNum 初始线程数量 51 | * @param maxThreadNum 最大线程数量 52 | * @param aliveTime 等待线程最长时间(ms) 53 | * @param waitRunableMaxNum 接受排队线程最大数量 54 | */ 55 | public ThreadPool(int initThreadNum, int maxThreadNum, int aliveTime, int waitRunableMaxNum) { 56 | threadPoolExecutor = new ThreadPoolExecutor( 57 | initThreadNum, 58 | maxThreadNum, 59 | aliveTime, 60 | TimeUnit.MILLISECONDS, 61 | new ArrayBlockingQueue(waitRunableMaxNum), 62 | new ThreadPoolExecutor.DiscardOldestPolicy()); 63 | threadPoolExecutor.allowCoreThreadTimeOut(true); 64 | } 65 | 66 | /** 67 | * 执行任务 68 | *

Function: execute

69 | *

Description:

70 | * 71 | * @param command 72 | * @author zhaoxy@thankjava.com 73 | * @date 2016年1月5日 下午3:21:05 74 | * @version 1.0 75 | */ 76 | public void execute(Runnable command) { 77 | threadPoolExecutor.execute(command); 78 | } 79 | 80 | public void destroy() { 81 | if (!threadPoolExecutor.isShutdown()) { 82 | threadPoolExecutor.shutdown(); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/thread/ThreadUtil.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.thread; 2 | 3 | /** 4 | * Created by sungang on 2017/8/16. 5 | */ 6 | public class ThreadUtil { 7 | 8 | /** 9 | * JVM退出会触发该动作 10 | *

Function: runWhenJVMExit

11 | *

Description:

12 | * 13 | * @author zhaoxy@thankjava.com 14 | * @date 2016年1月5日 下午2:45:12 15 | * @version 1.0 16 | */ 17 | public static void runWhenJVMExit(Runnable runnable) { 18 | Runtime.getRuntime().addShutdownHook(new Thread(runnable)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /car_utils/src/main/java/com/chinawiserv/utils/ztree/ZtreeNode.java: -------------------------------------------------------------------------------- 1 | package com.chinawiserv.utils.ztree; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by sungang on 2017/4/28. 7 | */ 8 | public class ZtreeNode implements Serializable { 9 | 10 | private Long id; 11 | private Integer state; 12 | private Long pId; 13 | private String icon; 14 | private String iconClose; 15 | private String iconOpen; 16 | private String name; 17 | private boolean open = false; 18 | private boolean isParent = true ; 19 | 20 | private boolean addFLag = true; 21 | private boolean editFlag = true; 22 | private boolean removeFlag = true; 23 | 24 | private boolean isLinked = false; 25 | 26 | //是否选中 默认 false 27 | private boolean checked; 28 | //是否支持可选 29 | private boolean nocheck; 30 | 31 | private String img; 32 | 33 | 34 | public Integer getState() { 35 | return state; 36 | } 37 | 38 | public void setState(Integer state) { 39 | this.state = state; 40 | } 41 | 42 | 43 | public String getIcon() { 44 | return icon; 45 | } 46 | 47 | public void setIcon(String icon) { 48 | this.icon = icon; 49 | } 50 | 51 | public String getIconClose() { 52 | return iconClose; 53 | } 54 | 55 | public void setIconClose(String iconClose) { 56 | this.iconClose = iconClose; 57 | } 58 | 59 | public String getIconOpen() { 60 | return iconOpen; 61 | } 62 | 63 | public void setIconOpen(String iconOpen) { 64 | this.iconOpen = iconOpen; 65 | } 66 | 67 | public String getName() { 68 | return name; 69 | } 70 | 71 | public void setName(String name) { 72 | this.name = name; 73 | } 74 | 75 | public boolean isOpen() { 76 | return open; 77 | } 78 | 79 | public void setOpen(boolean open) { 80 | this.open = open; 81 | } 82 | 83 | public boolean isParent() { 84 | return isParent; 85 | } 86 | 87 | public void setParent(boolean parent) { 88 | isParent = parent; 89 | } 90 | 91 | public Long getId() { 92 | return id; 93 | } 94 | 95 | public void setId(Long id) { 96 | this.id = id; 97 | } 98 | 99 | public Long getpId() { 100 | return pId; 101 | } 102 | 103 | public void setpId(Long pId) { 104 | this.pId = pId; 105 | } 106 | 107 | public boolean isAddFLag() { 108 | return addFLag; 109 | } 110 | 111 | public void setAddFLag(boolean addFLag) { 112 | this.addFLag = addFLag; 113 | } 114 | 115 | public boolean isEditFlag() { 116 | return editFlag; 117 | } 118 | 119 | public void setEditFlag(boolean editFlag) { 120 | this.editFlag = editFlag; 121 | } 122 | 123 | public boolean isRemoveFlag() { 124 | return removeFlag; 125 | } 126 | 127 | public void setRemoveFlag(boolean removeFlag) { 128 | this.removeFlag = removeFlag; 129 | } 130 | 131 | public boolean isChecked() { 132 | return checked; 133 | } 134 | 135 | public void setChecked(boolean checked) { 136 | this.checked = checked; 137 | } 138 | 139 | public boolean isNocheck() { 140 | return nocheck; 141 | } 142 | 143 | public void setNocheck(boolean nocheck) { 144 | this.nocheck = nocheck; 145 | } 146 | 147 | public boolean isLinked() { 148 | return isLinked; 149 | } 150 | 151 | public void setLinked(boolean linked) { 152 | isLinked = linked; 153 | } 154 | 155 | public String getImg() { 156 | return img; 157 | } 158 | 159 | public void setImg(String img) { 160 | this.img = img; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /data/ss1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aillamsun/spring-boot-security-with-jwt/0cc7f1874e1e6daca7bbf63848dec4952d717499/data/ss1.jpeg -------------------------------------------------------------------------------- /data/ss2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aillamsun/spring-boot-security-with-jwt/0cc7f1874e1e6daca7bbf63848dec4952d717499/data/ss2.jpeg -------------------------------------------------------------------------------- /data/ss3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aillamsun/spring-boot-security-with-jwt/0cc7f1874e1e6daca7bbf63848dec4952d717499/data/ss3.jpeg -------------------------------------------------------------------------------- /data/ss4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aillamsun/spring-boot-security-with-jwt/0cc7f1874e1e6daca7bbf63848dec4952d717499/data/ss4.jpeg -------------------------------------------------------------------------------- /data/ss5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aillamsun/spring-boot-security-with-jwt/0cc7f1874e1e6daca7bbf63848dec4952d717499/data/ss5.jpeg -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.chinawiserv 7 | spring-boot-security-with-jwt 8 | 0.0.1-SNAPSHOT 9 | 10 | car_core 11 | car_admin 12 | car_utils 13 | 14 | pom 15 | 16 | spring-boot-security-with-jwt 17 | Demo project for Spring Boot 18 | 19 | 20 | UTF-8 21 | UTF-8 22 | 1.8 23 | 24 | 25 | 1.5.1.RELEASE 26 | 1.4.6 27 | 28 | 29 | 30 | 31 | 32 | 3.3.1 33 | 3.3.9 34 | 4.1.6 35 | 36 | 1.2.4 37 | 5.1.39 38 | 1.0.29 39 | 40 | 1.1.7 41 | 1.7.5 42 | 43 | 44 | 1.3.1 45 | 46 | 18.0 47 | 2.9.4 48 | 3.5 49 | 1.2 50 | 1.3.1 51 | 1.10 52 | 2.5.0 53 | 2.3.1 54 | 2.8.0 55 | 1.16.8 56 | 2.3.2 57 | 58 | 0.7.0 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-dependencies 74 | ${spring.boot.version} 75 | pom 76 | import 77 | 78 | 79 | 80 | 81 | com.google.guava 82 | guava 83 | ${guava.version} 84 | 85 | 86 | joda-time 87 | joda-time 88 | ${joda.version} 89 | 90 | 91 | org.apache.commons 92 | commons-lang3 93 | ${apache.common.lang3.version} 94 | 95 | 96 | 97 | com.alibaba 98 | fastjson 99 | 1.2.12 100 | 101 | 102 | 103 | commons-codec 104 | commons-codec 105 | ${apache.common.codec.version} 106 | 107 | 108 | 109 | com.github.penggle 110 | kaptcha 111 | ${kaptcha.version} 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | org.projectlombok 122 | lombok 123 | true 124 | 125 | 126 | org.springframework.boot 127 | spring-boot-starter-test 128 | test 129 | 130 | 131 | org.springframework.security 132 | spring-security-test 133 | test 134 | 135 | 136 | 137 | 138 | org.apache.commons 139 | commons-lang3 140 | 141 | 142 | com.google.guava 143 | guava 144 | 145 | 146 | com.alibaba 147 | fastjson 148 | 149 | 150 | 151 | commons-codec 152 | commons-codec 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | org.apache.maven.plugins 162 | maven-compiler-plugin 163 | 3.6.1 164 | 165 | ${java.version} 166 | ${java.version} 167 | UTF-8 168 | 169 | 170 | 171 | 172 | org.apache.maven.plugins 173 | maven-surefire-plugin 174 | 175 | true 176 | 177 | 178 | 179 | 180 | 181 | org.apache.maven.plugins 182 | maven-clean-plugin 183 | 2.5 184 | 185 | 186 | 187 | 188 | 189 | org.apache.maven.plugins 190 | maven-resources-plugin 191 | 3.0.2 192 | 193 | 194 | @ 195 | 196 | false 197 | 198 | 199 | 200 | 201 | org.apache.maven.plugins 202 | maven-install-plugin 203 | 2.5.2 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | --------------------------------------------------------------------------------