diff --git a/JeeSpringCloud/jeespring-framework/pom.xml b/JeeSpringCloud/jeespring-framework/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..2727a9e72ca44570ecf1263d0c1f43925f563e94 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + com.jeespring + jeespring-framework + jeespring-framework + jeespring-framework + 1.0.0 + jar + + com.jeespring + jeespring + 1.0.0 + ../pom.xml + + + + + com.ckfinder + apache-ant-zip + 2.3 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/apache-ant-zip-2.3.jar + + + com.ckfinder + ckfinder + 2.3 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/ckfinder-2.3.jar + + + com.ckfinder + ckfinderplugin-fileeditor + 2.3 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/ckfinderplugin-fileeditor-2.3.jar + + + com.ckfinder + ckfinderplugin-imageresize + 2.3 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/ckfinderplugin-imageresize-2.3.jar + + + com.swetake + qrcode + 1.5 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/QRCode-1.5.jar + + + bitwalker + UserAgentUtils + 1.13 + system + ${project.basedir}/../jeespring-web/src/main/webapp/WEB-INF/lib/UserAgentUtils-1.13.jar + + + + + + src/main/resources + + + + \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/annotation/FieldName.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/annotation/FieldName.java new file mode 100644 index 0000000000000000000000000000000000000000..848be154b260d71999905e205f37f0152f93e2f0 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/annotation/FieldName.java @@ -0,0 +1,17 @@ +package com.jeespring.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * bean中文名注解 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldName { + + String value(); + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/AddGroup.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/AddGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..5c66318a1ae28d818bae02a75a04dafa7b01f6c2 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/AddGroup.java @@ -0,0 +1,13 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.beanvalidator; + +/** + * 添加Bean验证组 + * @author 黄炳桂 516821420@qq.com + * + */ +public interface AddGroup { + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/DefaultGroup.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/DefaultGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..6da5fdc080bd2c73a936abce28da72650db406b9 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/DefaultGroup.java @@ -0,0 +1,12 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.beanvalidator; + +/** + * 默认Bean验证组 + * @author 黄炳桂 516821420@qq.com + */ +public interface DefaultGroup { + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/EditGroup.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/EditGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..200e941725919f1147e0dd581c076490a13da278 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/beanvalidator/EditGroup.java @@ -0,0 +1,12 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.beanvalidator; + +/** + * 编辑Bena验证组 + * @author 黄炳桂 516821420@qq.com + */ +public interface EditGroup { + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/Global.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/Global.java new file mode 100644 index 0000000000000000000000000000000000000000..349cefb0bee4f183ee4bb5bba3d44cda371e0e8b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/Global.java @@ -0,0 +1,270 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.config; + +import com.ckfinder.connector.ServletContextFactory; +import com.google.common.collect.Maps; +import com.jeespring.common.utils.PropertiesLoader; +import com.jeespring.common.utils.StringUtils; + +import com.jeespring.modules.sys.entity.SysConfig; +import com.jeespring.modules.sys.service.SysConfigService; +import org.apache.ibatis.io.Resources; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.bind.RelaxedPropertyResolver; +import org.springframework.core.env.Environment; +import org.springframework.core.io.DefaultResourceLoader; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * 全局配置类 + * + * @author 黄炳桂 516821420@qq.com + * @version 2014-06-25 + */ +public class Global { + + private static Logger logger = LoggerFactory.getLogger(Global.class); + + static RelaxedPropertyResolver resolver; + //@Autowired + //private static Environment env; + + /** + * 当前对象实例 + */ + private static Global global = new Global(); + + /** + * 保存全局属性值 + */ + private static Map map = Maps.newHashMap(); + + /** + * 属性文件加载对象 + */ + private static PropertiesLoader loader = new PropertiesLoader("bootstrap.yml"); + + /** + * 显示/隐藏 + */ + public static final String SHOW = "1"; + public static final String HIDE = "0"; + + /** + * 是/否 + */ + public static final String YES = "1"; + public static final String NO = "0"; + + /** + * 对/错 + */ + public static final String TRUE = "true"; + public static final String FALSE = "false"; + + /** + * 上传文件基础虚拟路径 + */ + public static final String USERFILES_BASE_URL = "/userfiles/"; + + /** + * 获取当前对象实例 + */ + public static Global getInstance() { + return global; + } + + /** + * 获取配置 + * ${fns:getConfig('adminPath')} + */ + public static String getConfig(String key) { + String value = map.get(key); + if (value == null) { + try { + value = resolver.getProperty(key); + //value =env.getProperty(key); + if (StringUtils.isBlank(value)) { + throw new RuntimeException("value null"); + } + map.put(key, value); + } catch (Exception e) { + value = loader.getProperty(key); + map.put(key, value != null ? value : StringUtils.EMPTY); + } + } + return value; + } + + public static String getConfig(String key,String value){ + String result=getConfig(key); + if(result==StringUtils.EMPTY){ + return value; + } + return result; + } + /** + * 获取管理端根路径 + */ + public static String getAdminPath() { + return getConfig("adminPath"); + } + + /** + * 获取前端根路径 + */ + public static String getFrontPath() { + return getConfig("frontPath"); + } + + /** + * 获取URL后缀 + */ + public static String getUrlSuffix() { + return getConfig("urlSuffix"); + } + + /** + * 是否是演示模式,演示模式下不能修改用户、角色、密码、菜单、授权 + */ + public static Boolean isDemoMode() { + String dm = getConfig("demoMode"); + return "true".equals(dm) || "1".equals(dm); + } + + public static String isDemoModeDescription() { + String dmd = getConfig("demoModeDescription"); + if(dmd==null){ + return "演示版启用为系统能正常演示,暂时不允许操作!"; + } + return dmd; + } + + public static Boolean isDubbo() { + String dm = getConfig("dubbo.run"); + return "true".equals(dm) || "1".equals(dm); + } + + /** + * 获取上传文件的根目录 + * + * @return + */ + public static String getUserfilesBaseDir() { + String dir = getConfig("userfiles.basedir"); + if (StringUtils.isBlank(dir)) { + try { + dir = ServletContextFactory.getServletContext().getRealPath("/"); + } catch (Exception e) { + return ""; + } + } + if (!dir.endsWith("/")) { + dir += "/"; + } + return dir; + } + + public static String getJdbcType() { + if (map.containsKey("spring.datasource.url")) { + return map.get("spring.datasource.url"); + } + try { + String url = resolver.getProperty("spring.datasource.url"); + //String url = env.getProperty("spring.datasource.url"); + String type = getDbType(url); + map.put("spring.datasource.url", type); + return type; + } catch (Exception e) { + logger.error("get jdbcType error", e); + } + logger.error("return the defaut jdbc type is mysql"); + return "mysql"; + } + + private static String getDbType(String rawUrl) { + return rawUrl == null ? null : (!rawUrl.startsWith("jdbc:derby:") && !rawUrl.startsWith("jdbc:log4jdbc:derby:") ? (!rawUrl.startsWith("jdbc:mysql:") && !rawUrl.startsWith("jdbc:cobar:") && !rawUrl.startsWith("jdbc:log4jdbc:mysql:") ? (rawUrl.startsWith("jdbc:mariadb:") ? "mariadb" : (!rawUrl.startsWith("jdbc:oracle:") && !rawUrl.startsWith("jdbc:log4jdbc:oracle:") ? (rawUrl.startsWith("jdbc:alibaba:oracle:") ? "AliOracle" : (!rawUrl.startsWith("jdbc:microsoft:") && !rawUrl.startsWith("jdbc:log4jdbc:microsoft:") ? (!rawUrl.startsWith("jdbc:sqlserver:") && !rawUrl.startsWith("jdbc:log4jdbc:sqlserver:") ? (!rawUrl.startsWith("jdbc:sybase:Tds:") && !rawUrl.startsWith("jdbc:log4jdbc:sybase:") ? (!rawUrl.startsWith("jdbc:jtds:") && !rawUrl.startsWith("jdbc:log4jdbc:jtds:") ? (!rawUrl.startsWith("jdbc:fake:") && !rawUrl.startsWith("jdbc:mock:") ? (!rawUrl.startsWith("jdbc:postgresql:") && !rawUrl.startsWith("jdbc:log4jdbc:postgresql:") ? (rawUrl.startsWith("jdbc:edb:") ? "edb" : (!rawUrl.startsWith("jdbc:hsqldb:") && !rawUrl.startsWith("jdbc:log4jdbc:hsqldb:") ? (rawUrl.startsWith("jdbc:odps:") ? "odps" : (rawUrl.startsWith("jdbc:db2:") ? "db2" : (rawUrl.startsWith("jdbc:sqlite:") ? "sqlite" : (rawUrl.startsWith("jdbc:ingres:") ? "ingres" : (!rawUrl.startsWith("jdbc:h2:") && !rawUrl.startsWith("jdbc:log4jdbc:h2:") ? (rawUrl.startsWith("jdbc:mckoi:") ? "mckoi" : (rawUrl.startsWith("jdbc:cloudscape:") ? "cloudscape" : (!rawUrl.startsWith("jdbc:informix-sqli:") && !rawUrl.startsWith("jdbc:log4jdbc:informix-sqli:") ? (rawUrl.startsWith("jdbc:timesten:") ? "timesten" : (rawUrl.startsWith("jdbc:as400:") ? "as400" : (rawUrl.startsWith("jdbc:sapdb:") ? "sapdb" : (rawUrl.startsWith("jdbc:JSQLConnect:") ? "JSQLConnect" : (rawUrl.startsWith("jdbc:JTurbo:") ? "JTurbo" : (rawUrl.startsWith("jdbc:firebirdsql:") ? "firebirdsql" : (rawUrl.startsWith("jdbc:interbase:") ? "interbase" : (rawUrl.startsWith("jdbc:pointbase:") ? "pointbase" : (rawUrl.startsWith("jdbc:edbc:") ? "edbc" : (rawUrl.startsWith("jdbc:mimer:multi1:") ? "mimer" : (rawUrl.startsWith("jdbc:dm:") ? "dm" : (rawUrl.startsWith("jdbc:kingbase:") ? "kingbase" : (rawUrl.startsWith("jdbc:log4jdbc:") ? "log4jdbc" : (rawUrl.startsWith("jdbc:hive:") ? "hive" : (rawUrl.startsWith("jdbc:hive2:") ? "hive" : (rawUrl.startsWith("jdbc:phoenix:") ? "phoenix" : null)))))))))))))))) : "informix"))) : "h2"))))) : "hsql")) : "postgresql") : "mock") : "jtds") : "sybase") : "sqlserver") : "sqlserver")) : "oracle")) : "mysql") : "derby"); + } + + /** + * 获取工程路径 + * @return + */ + public static String getProjectPath(){ + // 如果配置了工程路径,则直接返回,否则自动获取。 + String projectPath = Global.getConfig("projectPath"); + if (StringUtils.isNotBlank(projectPath)){ + return projectPath; + } + try { + File file = new DefaultResourceLoader().getResource("").getFile(); + if (file != null){ + while(true){ + File f = new File(file.getPath() + File.separator + "src" + File.separator + "main"); + if (f == null || f.exists()){ + break; + } + if (file.getParentFile() != null){ + file = file.getParentFile(); + }else{ + break; + } + } + projectPath = file.toString(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return projectPath; + } + + /** + * 写入properties信息 + * + * @param key + * 名称 + * @param value + * 值 + */ + public static void modifyConfig(String key, String value) { + try { + // 从输入流中读取属性列表(键和元素对) + Properties prop = getProperties(); + prop.setProperty(key, value); + String path = Global.class.getResource("/jeespring.properties").getPath(); + FileOutputStream outputFile = new FileOutputStream(path); + prop.store(outputFile, "modify"); + outputFile.close(); + outputFile.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * (注意:加载的是src下的文件,如果在某个包下.请把包名加上) + * 返回 Properties + * @return + */ + public static Properties getProperties(){ + Properties prop = new Properties(); + try { + Reader reader = Resources.getResourceAsReader("/jeespring.properties"); + prop.load(reader); + } catch (Exception e) { + return null; + } + return prop; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ScheduleConfig.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ScheduleConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..94ad9f63c3da8021d821eeb1054a59d8c373538e --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ScheduleConfig.java @@ -0,0 +1,58 @@ +package com.jeespring.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + +import javax.sql.DataSource; +import java.util.Properties; + +/** + * 定时任务配置 + * + * @author JeeSpring + * + */ +@Configuration +public class ScheduleConfig +{ + + @Bean + public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) + { + SchedulerFactoryBean factory = new SchedulerFactoryBean(); + factory.setDataSource(dataSource); + + // quartz参数 + Properties prop = new Properties(); + prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); + prop.put("org.quartz.scheduler.instanceId", "AUTO"); + // 线程池配置 + prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); + prop.put("org.quartz.threadPool.threadCount", "20"); + prop.put("org.quartz.threadPool.threadPriority", "5"); + // JobStore配置 + prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX"); + // 集群配置 + prop.put("org.quartz.jobStore.isClustered", "true"); + prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); + prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); + prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); + + prop.put("org.quartz.jobStore.misfireThreshold", "12000"); + prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); + factory.setQuartzProperties(prop); + + factory.setSchedulerName("RuoyiScheduler"); + // 延时启动 + factory.setStartupDelay(1); + factory.setApplicationContextSchedulerContextKey("applicationContextKey"); + // 可选,QuartzScheduler + // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 + factory.setOverwriteExistingJobs(true); + // 设置自动启动,默认为true + factory.setAutoStartup(true); + + return factory; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ShiroConfig.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ShiroConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..b30e5e777bec863ba13fe3e67a201c171ca7f890 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/config/ShiroConfig.java @@ -0,0 +1,304 @@ +package com.jeespring.common.config; + +import com.jeespring.common.filter.LogoutFilter; +import com.jeespring.common.filter.OnlineSessionFilter; +import com.jeespring.common.redis.RedisUtils; +import com.jeespring.common.security.shiro.session.CacheSessionDAO; +import com.jeespring.common.security.shiro.session.SessionManager; +import com.jeespring.modules.sys.dao.OnlineSessionDAO; +import com.jeespring.modules.sys.dao.OnlineSessionFactory; +import com.jeespring.modules.sys.security.FormAuthenticationFilter; +import com.jeespring.modules.sys.security.SystemAuthorizingRealm; +import net.sf.ehcache.CacheManager; +import org.apache.shiro.cache.ehcache.EhCacheManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.crazycake.shiro.RedisCacheManager; +import org.crazycake.shiro.RedisManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.bind.RelaxedPropertyResolver; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.DelegatingFilterProxy; +import com.jeespring.common.filter.SyncOnlineSessionFilter; + +import javax.servlet.Filter; +import java.util.HashMap; +import java.util.Map; + +/** + * shiro的控制类 + * 下面方法的顺序不能乱 + * Created by zhao.weiwei + * create on 2017/1/11 10:59 + * the email is zhao.weiwei@jyall.com. + */ +@Component +public class ShiroConfig { + /** + * 日志对象 + */ + private static Logger logger = LoggerFactory.getLogger(RedisUtils.class); + + @Autowired + public OnlineSessionDAO sessionDAO; + @Autowired + public OnlineSessionFactory sessionFactory; + + // Session超时时间,单位为毫秒(默认30分钟) + @Value("${shiro.session.expireTime}") + private int expireTime; + + //启动shiro redis缓存,单点登录 + //@Value("${shiro.redis}") + //private String shiroRedis; + + // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟 + @Value("${shiro.session.validationInterval}") + private int validationInterval; + + // 验证码开关 + @Value("${shiro.user.captchaEbabled}") + private boolean captchaEbabled; + + // 验证码类型 + @Value("${shiro.user.captchaType}") + private String captchaType; + + // 设置Cookie的域名 + @Value("${shiro.cookie.domain}") + private String domain; + + // 设置cookie的有效访问路径 + @Value("${shiro.cookie.path}") + private String path; + + // 设置HttpOnly属性 + @Value("${shiro.cookie.httpOnly}") + private boolean httpOnly; + + // 设置Cookie的过期时间,秒为单位 + @Value("${shiro.cookie.maxAge}") + private int maxAge; + + // 登录地址 + @Value("${shiro.user.loginUrl}") + private String loginUrl="/admin/login"; + + // 权限认证失败地址 + @Value("${shiro.user.unauthorizedUrl}") + private String unauthorizedUrl; + + /** + * 全局的环境变量的设置 + * shiro的拦截 + * + * @param environment + * @param adminPath + * @return + */ + @Bean(name = "shiroFilterChainDefinitions") + public String shiroFilterChainDefinitions(Environment environment + , @Value("${adminPath}") String adminPath + , @Value("${frontPath}") String frontPath) { + Global.resolver = new RelaxedPropertyResolver(environment); + StringBuilder string=new StringBuilder(); + string.append("/static/** = anon\n"); + string.append("/staticViews/** = anon\n"); + string.append("/jeeSpringStatic/** = anon\n"); + string.append("/userfiles/** = anon\n"); + string.append("/rest/** = anon\n"); + string.append(frontPath+"/** = anon\n"); + string.append( adminPath + "/basic = basic\n"); + string.append( adminPath + "/login = authc\n"); + string.append( adminPath + "/loginBase = anon\n"); + string.append( adminPath + "/logout = logout\n"); + string.append( adminPath + "/register = anon\n"); + string.append( adminPath + "/sys/register/registerUser = anon\n"); + string.append( adminPath + "/sys/user/validateLoginName = anon\n"); + string.append( adminPath + "/sys/user/validateMobile = anon\n"); + string.append( adminPath + "/** = user\n"); + string.append( "/ReportServer/** = user"); + return string.toString(); + } + + @Bean(name = "basicHttpAuthenticationFilter") + public BasicHttpAuthenticationFilter casFilter(@Value("${adminPath:/a}") String adminPath) { + BasicHttpAuthenticationFilter basicHttpAuthenticationFilter = new BasicHttpAuthenticationFilter(); + basicHttpAuthenticationFilter.setLoginUrl(adminPath + "/login"); + return basicHttpAuthenticationFilter; + } + + @Bean(name = "shiroFilter") + public ShiroFilterFactoryBean shiroFilterFactoryBean( + @Value("${adminPath:/a}") String adminPath, + BasicHttpAuthenticationFilter basicHttpAuthenticationFilter, + FormAuthenticationFilter formAuthenticationFilter, + DefaultWebSecurityManager securityManager, + @Qualifier("shiroFilterChainDefinitions") String shiroFilterChainDefinitions) { + Map filters = new HashMap<>(); + filters.put("basic", basicHttpAuthenticationFilter); + filters.put("authc", formAuthenticationFilter); + filters.put("syncOnlineSession", syncOnlineSessionFilter()); + //filters.put("onlineSession", onlineSessionFilter()); + filters.put("logout", logoutFilter()); + ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); + bean.setFilters(filters); + bean.setSecurityManager(securityManager); + bean.setLoginUrl(adminPath + "/login"); + bean.setSuccessUrl(adminPath + "?login"); + // Shiro过滤器配置 + bean.setFilterChainDefinitions(shiroFilterChainDefinitions); + return bean; + } + + @Bean(name = "shiroCacheManager") + public EhCacheManager shiroCacheManager(CacheManager manager) { + EhCacheManager ehCacheManager = new EhCacheManager(); + ehCacheManager.setCacheManager(manager); + return ehCacheManager; + } + + + //@Bean(name = "redisCacheManager") + public RedisCacheManager redisCacheManager(String redisHostName,String reidsPassword,int reidsPort,int expireTimeShiro) { + RedisCacheManager redisCacheManager= new RedisCacheManager(); + RedisManager redisManager= new RedisManager(); + redisManager.setHost(redisHostName); + redisManager.setPassword(reidsPassword); + redisManager.setPort(reidsPort); + redisManager.setExpire(expireTimeShiro); + redisCacheManager.setRedisManager(redisManager); + return redisCacheManager; + } + + + + @Bean(name = "sessionManager") + public SessionManager sessionManager(CacheSessionDAO dao) { + SessionManager sessionManager = new SessionManager(); + sessionManager.setSessionDAO(dao); + // 设置全局session超时时间 + sessionManager.setGlobalSessionTimeout(86400000); + // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟 + sessionManager.setSessionValidationInterval(1800000); + sessionManager.setSessionValidationSchedulerEnabled(true); + sessionManager.setSessionIdCookie(new SimpleCookie("com.jeespring.session.id")); + sessionManager.setSessionIdCookieEnabled(true); + // 删除过期的session + sessionManager.setDeleteInvalidSessions(true); + // 去掉 JSESSIONID + sessionManager.setSessionIdUrlRewritingEnabled(false); + // 是否定时检查session + sessionManager.setSessionValidationSchedulerEnabled(true); + // 自定义SessionDao + //sessionManager.setSessionDAO(sessionDAO()); + // 自定义sessionFactory + //sessionManager.setSessionFactory(sessionFactory()); + return sessionManager; + } + + @Bean(name = "securityManager") + public DefaultWebSecurityManager defaultWebSecurityManager( + SystemAuthorizingRealm systemAuthorizingRealm, + SessionManager sessionManager, + EhCacheManager ehCacheManager, + @Value("${spring.redis.run}") String redisRun, + @Value("${spring.redis.hostName}") String redisHostName, + @Value("${spring.redis.password}") String reidsPassword, + @Value("${spring.redis.port}") int redisPort, + @Value("${spring.redis.expireTimeShiro}") int expireTimeShiro, + @Value("${shiro.redis}") String shiroRedis + ) { + DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); + defaultWebSecurityManager.setSessionManager(sessionManager); + if("true".equals(redisRun) && "true".equals(shiroRedis)){ + try{ + // 加入缓存管理器 + defaultWebSecurityManager.setCacheManager(redisCacheManager(redisHostName,reidsPassword,redisPort,expireTimeShiro)); + } catch (Exception e) { + logger.error("RedisUtils run:"+RedisUtils.RUN_MESSAGE+e.getMessage(), RedisUtils.RUN_MESSAGE+e.getMessage()); + defaultWebSecurityManager.setCacheManager(ehCacheManager); + } + }else{ + // 加入缓存管理器 + defaultWebSecurityManager.setCacheManager(ehCacheManager); + } + defaultWebSecurityManager.setRealm(systemAuthorizingRealm); + return defaultWebSecurityManager; + } + + + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor( + DefaultWebSecurityManager defaultWebSecurityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager); + return authorizationAttributeSourceAdvisor; + } + + @Bean + public FilterRegistrationBean filterRegistrationBean() { + FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); + filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter")); + filterRegistration.addInitParameter("targetFilterLifecycle", "true"); + filterRegistration.setEnabled(true); + filterRegistration.addUrlPatterns("/*"); + return filterRegistration; + } + + @Bean(name = "lifecycleBeanPostProcessor") + public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + @Bean + @DependsOn("lifecycleBeanPostProcessor") + public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { + DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); + defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); + return defaultAdvisorAutoProxyCreator; + } + + /** + * 自定义在线用户处理过滤器 + */ + + public OnlineSessionFilter onlineSessionFilter() + { + OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter(); + //onlineSessionFilter.setLoginUrl(loginUrl); + return onlineSessionFilter; + } + + /** + * 自定义在线用户同步过滤器 + */ + @Bean + public SyncOnlineSessionFilter syncOnlineSessionFilter() + { + SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter(); + return syncOnlineSessionFilter; + } + + + public LogoutFilter logoutFilter() + { + LogoutFilter logoutFilter = new LogoutFilter(); + logoutFilter.setLoginUrl(loginUrl); + return logoutFilter; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/Constants.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..e4d9044c9bedf508b2b3f0236712d1e28f2fcef1 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/Constants.java @@ -0,0 +1,65 @@ +package com.jeespring.common.constant; + +/** + * 通用常量信息 + * + * @author JeeSpring + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 自动去除表前缀 + */ + public static String AUTO_REOMVE_PRE = "true"; + + /** + * 当前记录起始索引 + */ + public static String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static String IS_ASC = "isAsc"; + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ScheduleConstants.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ScheduleConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..87d6310d534c48a4fd017d1a06ce3f80f72814e4 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ScheduleConstants.java @@ -0,0 +1,51 @@ +package com.jeespring.common.constant; + +/** + * 任务调度通用常量 + * + * @author JeeSpring + */ +public interface ScheduleConstants +{ + + public static final String TASK_CLASS_NAME = "__TASK_CLASS_NAME__"; + + public static final String TASK_PROPERTIES = "__TASK_PROPERTIES__"; + + /** 默认 */ + public static final String MISFIRE_DEFAULT = "0"; + + /** 立即触发执行 */ + public static final String MISFIRE_IGNORE_MISFIRES = "1"; + + /** 触发一次执行 */ + public static final String MISFIRE_FIRE_AND_PROCEED = "2"; + + /** 不触发立即执行 */ + public static final String MISFIRE_DO_NOTHING = "3"; + + public enum Status + { + /** + * 正常 + */ + NORMAL("0"), + /** + * 暂停 + */ + PAUSE("1"); + + private String value; + + private Status(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ShiroConstants.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ShiroConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..60c5fcb834b1d8320f6d113da2369d5597889f30 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/constant/ShiroConstants.java @@ -0,0 +1,65 @@ +package com.jeespring.common.constant; + +/** + * Shiro通用常量 + * + * @author JeeSpring + */ +public interface ShiroConstants +{ + /** + * 当前登录的用户 + */ + public static final String CURRENT_USER = "currentUser"; + + /** + * 用户名 + */ + public static final String CURRENT_USERNAME = "username"; + + /** + * 消息key + */ + public static String MESSAGE = "message"; + + /** + * 错误key + */ + public static String ERROR = "errorMsg"; + + /** + * 编码格式 + */ + public static String ENCODING = "UTF-8"; + + /** + * 当前在线会话 + */ + public String ONLINE_SESSION = "online_session"; + + /** + * 验证码key + */ + public static final String CURRENT_CAPTCHA = "captcha"; + + /** + * 验证码开关 + */ + public static final String CURRENT_EBABLED = "captchaEbabled"; + + /** + * 验证码开关 + */ + public static final String CURRENT_TYPE = "captchaType"; + + /** + * 验证码 + */ + public static final String CURRENT_VALIDATECODE = "validateCode"; + + /** + * 验证码错误 + */ + public static final String CAPTCHA_ERROR = "captchaError"; + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidConfiguration.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..af784124ce160ea056d3bb88e61d50663ba3663b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidConfiguration.java @@ -0,0 +1,93 @@ +package com.jeespring.common.druid; + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import com.alibaba.druid.pool.DruidDataSource; + +/** + * + * 描述:如果不使用代码手动初始化DataSource的话,监控界面的SQL监控会没有数据("是spring boot的bug???") + * @author chhliu + * 创建时间:2017年2月9日 下午10:33:08 + * @version 1.2.0 + */ +@Configuration +public class DruidConfiguration { + @Value("${spring.datasource.url}") + private String dbUrl; + @Value("${spring.datasource.username}") + private String username; + @Value("${spring.datasource.password}") + private String password; + @Value("${spring.datasource.driverClassName}") + private String driverClassName; + @Value("${spring.datasource.initialSize}") + private int initialSize; + @Value("${spring.datasource.minIdle}") + private int minIdle; + @Value("${spring.datasource.maxActive}") + private int maxActive; + @Value("${spring.datasource.maxWait}") + private int maxWait; + @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") + private int timeBetweenEvictionRunsMillis; + @Value("${spring.datasource.minEvictableIdleTimeMillis}") + private int minEvictableIdleTimeMillis; + @Value("${spring.datasource.validationQuery}") + private String validationQuery; + @Value("${spring.datasource.testWhileIdle}") + private boolean testWhileIdle; + @Value("${spring.datasource.testOnBorrow}") + private boolean testOnBorrow; + @Value("${spring.datasource.testOnReturn}") + private boolean testOnReturn; + @Value("${spring.datasource.poolPreparedStatements}") + private boolean poolPreparedStatements; + @Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}") + private int maxPoolPreparedStatementPerConnectionSize; + @Value("${spring.datasource.filters}") + private String filters; + @Value("${spring.datasource.connectionProperties}") + private String connectionProperties; + @Value("${spring.datasource.useGlobalDataSourceStat}") + private boolean useGlobalDataSourceStat; + + @Bean //声明其为Bean实例 + @Primary //在同样的DataSource中,首先使用被标注的DataSource + public DataSource dataSource(){ + DruidDataSource datasource = new DruidDataSource(); + datasource.setUrl(this.dbUrl); + datasource.setUsername(username); + datasource.setPassword(password); + datasource.setDriverClassName(driverClassName); + + //configuration + datasource.setInitialSize(initialSize); + datasource.setMinIdle(minIdle); + datasource.setMaxActive(maxActive); + datasource.setMaxWait(maxWait); + datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + datasource.setValidationQuery(validationQuery); + datasource.setTestWhileIdle(testWhileIdle); + datasource.setTestOnBorrow(testOnBorrow); + datasource.setTestOnReturn(testOnReturn); + datasource.setPoolPreparedStatements(poolPreparedStatements); + datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); + datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat); + try { + datasource.setFilters(filters); + } catch (SQLException e) { + System.err.println("druid configuration initialization filter: "+ e); + } + datasource.setConnectionProperties(connectionProperties); + return datasource; + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..85e0b6f96c4e08b056331f5a9a27922fb8f14a8d --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatFilter.java @@ -0,0 +1,21 @@ +package com.jeespring.common.druid; + +import javax.servlet.annotation.WebFilter; +import javax.servlet.annotation.WebInitParam; + +import com.alibaba.druid.support.http.WebStatFilter; + +/** + * Druid的StatFilter + * + * @author 单红宇(365384722) + * @myblog http://blog.csdn.net/catoop/ + * @create 2016年3月17日 + */ +@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", + initParams={ + @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 +}) +public class DruidStatFilter extends WebStatFilter { + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatViewServlet.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatViewServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..85c4cfad185b0ac1fae4b2c2d77a90231ef7be61 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/druid/DruidStatViewServlet.java @@ -0,0 +1,26 @@ +package com.jeespring.common.druid; + +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; + +import com.alibaba.druid.support.http.StatViewServlet; + +/** + * StatViewServlet + * + * @author 单红宇(365384722) + * @myblog http://blog.csdn.net/catoop/ + * @create 2016年3月17日 + */ +@SuppressWarnings("serial") +@WebServlet(urlPatterns = "/druid/*", + initParams={ + @WebInitParam(name="allow",value="192.168.16.110,127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) + @WebInitParam(name="deny",value="192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow) + //WebInitParam(name="loginUsername",value="shanhy"),// 用户名 + //WebInitParam(name="loginPassword",value="shanhypwd"),// 密码 + @WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能 + }) +public class DruidStatViewServlet extends StatViewServlet { + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/exception/job/TaskException.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/exception/job/TaskException.java new file mode 100644 index 0000000000000000000000000000000000000000..9e6f595313a2a2d9b47c4a824ef99fa1ca71fa4a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/exception/job/TaskException.java @@ -0,0 +1,35 @@ +package com.jeespring.common.exception.job; + +/** + * 计划策略异常 + * + * @author JeeSpring + */ +public class TaskException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Code code; + + public TaskException(String msg, Code code) + { + this(msg, code, null); + } + + public TaskException(String msg, Code code, Exception nestedEx) + { + super(msg, nestedEx); + this.code = code; + } + + public Code getCode() + { + return code; + } + + public enum Code + { + TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE + } + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/JeesiteFileUploadFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/JeesiteFileUploadFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..fb1bbab15f6bee8c258e6aaf3892f5b338cf9f5c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/JeesiteFileUploadFilter.java @@ -0,0 +1,18 @@ +package com.jeespring.common.filter; + +import com.ckfinder.connector.FileUploadFilter; + +import javax.servlet.annotation.WebFilter; +import javax.servlet.annotation.WebInitParam; + +/** + * Created by zhao.weiwei + * create on 2017/1/10 12:23 + * the email is zhao.weiwei@jyall.com. + */ +@WebFilter(urlPatterns = "/static/ckfinder/core/connector/java/connector.java", initParams = { + @WebInitParam(name = "sessionCookieName", value = "JSESSIONID"), + @WebInitParam(name = "sessionParameterName", value = "jsessionid") +}) +public class JeesiteFileUploadFilter extends FileUploadFilter { +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/LogoutFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/LogoutFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..6ff959960483e927ec881db2903d5f84bd426525 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/LogoutFilter.java @@ -0,0 +1,111 @@ +package com.jeespring.common.filter; + +import com.jeespring.common.security.ShiroUtils; +import com.jeespring.common.utils.StringUtils; +import com.jeespring.modules.monitor.entity.OnlineSession; +import com.jeespring.modules.sys.dao.OnlineSessionDAO; +import com.jeespring.modules.sys.entity.SysUserOnline; +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.service.SysUserOnlineService; +import org.apache.shiro.session.SessionException; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.servlet.ServletContext; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +/** + * 退出过滤器 + * + * @author JeeSpring + */ + +public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter +{ + private SysUserOnlineService sysUserOnlineService; + + private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class); + + /** + * 退出后重定向的地址 + */ + private String loginUrl="/admin/login"; + + public String getLoginUrl() + { + return loginUrl; + } + + public void setLoginUrl(String loginUrl) + { + this.loginUrl = loginUrl; + } + + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception + { + try + { + Subject subject = getSubject(request, response); + String redirectUrl = getRedirectUrl(request, response, subject); + try + { + User user = ShiroUtils.getUser(); + if (StringUtils.isNotNull(user)) + { + String loginName = user.getLoginName(); + SysUserOnline sysUserOnline=new SysUserOnline(); + sysUserOnline.setLoginName(user.getName()); + if(sysUserOnlineService==null){ + ServletContext context = request.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context); + sysUserOnlineService = ctx.getBean(SysUserOnlineService.class); + } + if(sysUserOnlineService!=null){ + sysUserOnline= sysUserOnlineService.get(subject.getSession().getId().toString()); + if(sysUserOnline!=null){ + sysUserOnline.setStatus(OnlineSession.OnlineStatus.off_line.toString()); + sysUserOnlineService.save(sysUserOnline); + } + } + // 记录用户退出日志 + //SystemLogUtils.log(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success")); + } + // 退出登录 + subject.logout(); + } + catch (SessionException ise) + { + log.error("logout fail.", ise); + } + issueRedirect(request, response, redirectUrl); + } + catch (Exception e) + { + log.error("Encountered session exception during logout. This can generally safely be ignored.", e); + } + return false; + } + + /** + * 退出跳转URL + */ + @Override + protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) + { + String url = getLoginUrl(); + if (StringUtils.isNotEmpty(url)) + { + return url; + } + return super.getRedirectUrl(request, response, subject); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/OnlineSessionFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/OnlineSessionFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..e40ecc75f3e0ae296c88c790ab01d4d4c8a01b71 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/OnlineSessionFilter.java @@ -0,0 +1,121 @@ +package com.jeespring.common.filter; + +import com.jeespring.common.constant.ShiroConstants; +import com.jeespring.common.security.ShiroUtils; +import com.jeespring.common.utils.IpUtils; +import com.jeespring.common.utils.ServletUtils; +import com.jeespring.modules.sys.dao.OnlineSessionDAO; +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.service.SysUserOnlineService; +import eu.bitwalker.useragentutils.UserAgent; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.AccessControlFilter; +import org.apache.shiro.web.util.WebUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import com.jeespring.modules.monitor.entity.OnlineSession; + +/** + * 自定义访问控制 + * + * @author JeeSpring + */ +public class OnlineSessionFilter //extends AccessControlFilter +{ + + /** + * 强制退出后重定向的地址 + */ + @Value("${shiro.user.loginUrl}") + private String loginUrl="/admin/login"; + + /** + * 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false; + */ + //@Override + protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) + throws Exception + { + Subject subject = getSubject(request, response); + if (subject == null || subject.getSession() == null) + { + return true; + } + //Session session = onlineSessionDAO.readSession(subject.getSession().getId()); + Session session =subject.getSession(); + //&& session instanceof OnlineSession + if (session != null) + { + //OnlineSession onlineSession = (OnlineSession) session; + OnlineSession onlineSession = new OnlineSession(); + onlineSession.setId(subject.getSession().getId().toString()); + request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession); + // 把user对象设置进去 + boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == ""; + if (isGuest == true) + { + User user = ShiroUtils.getUser(); + if (user != null) + { + onlineSession.setUserId(user.getId()); + onlineSession.setLoginName(user.getLoginName()); + if(user.getOffice()!=null) { + onlineSession.setDeptName(user.getOffice().getName()); + } + onlineSession.markAttributeChanged(); + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + // 获取客户端操作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + onlineSession.setHost(IpUtils.getIpAddr((HttpServletRequest)request)); + onlineSession.setBrowser(browser); + onlineSession.setOs(os); + } + } + + if (onlineSession.getStatus() == OnlineSession.OnlineStatus.off_line) + { + return false; + } + } + return true; + } + + /** + * 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。 + */ + //@Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception + { + Subject subject = getSubject(request, response); + if (subject != null) + { + subject.logout(); + } + //saveRequestAndRedirectToLogin(request, response); + return true; + } + + // 跳转到登录页 + //@Override + protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException + { + WebUtils.issueRedirect(request, response, loginUrl); + } + + /** + * 表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false; + */ + + protected Subject getSubject(ServletRequest request, ServletResponse response) { + return SecurityUtils.getSubject(); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/PageCachingFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/PageCachingFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..c0a53ec088dd357253cd2b9fc9ba0b825ac1d77b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/PageCachingFilter.java @@ -0,0 +1,26 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.filter; + +import com.jeespring.common.utils.SpringContextHolder; + +import net.sf.ehcache.CacheManager; +import net.sf.ehcache.constructs.web.filter.SimplePageCachingFilter; + +/** + * 页面高速缓存过滤器 + * @author 黄炳桂 516821420@qq.com + * @version 2013-8-5 + */ +public class PageCachingFilter extends SimplePageCachingFilter { + + private CacheManager cacheManager = SpringContextHolder.getBean(CacheManager.class); + + @Override + protected CacheManager getCacheManager() { + this.cacheName = "pageCachingFilter"; + return cacheManager; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/SyncOnlineSessionFilter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/SyncOnlineSessionFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..dc7524334f4490560f66ffddc59d77358a7f4a1a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/filter/SyncOnlineSessionFilter.java @@ -0,0 +1,80 @@ +package com.jeespring.common.filter; + +import com.jeespring.common.constant.ShiroConstants; +import com.jeespring.common.redis.RedisUtils; +import com.jeespring.common.security.ShiroUtils; +import com.jeespring.common.utils.IpUtils; +import com.jeespring.common.utils.ServletUtils; +import com.jeespring.modules.monitor.entity.OnlineSession; +import com.jeespring.modules.sys.dao.OnlineSessionDAO; +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.service.SysUserOnlineService; +import eu.bitwalker.useragentutils.UserAgent; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.filter.PathMatchingFilter; +import org.apache.shiro.web.util.WebUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 同步Session数据到Db + * + * @author JeeSpring + */ +public class SyncOnlineSessionFilter extends PathMatchingFilter +{ + /** + * 日志对象 + */ + private static Logger logger = LoggerFactory.getLogger(SyncOnlineSessionFilter.class); + + @Autowired + private SysUserOnlineService sysUserOnlineService; + /** + * 强制退出后重定向的地址 + */ + @Value("${shiro.user.loginUrl}") + private String loginUrl; + + /** + * 同步会话数据到DB 一次请求最多同步一次 防止过多处理 需要放到Shiro过滤器之前 + * + * @param request + * @param response + * @return + * @throws Exception + */ + @Override + protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception + { + try { + OnlineSessionFilter onlineSessionFilter=new OnlineSessionFilter(); + onlineSessionFilter.isAccessAllowed(request,response,null); + //isAccessAllowed(request, response); + OnlineSession session = (OnlineSession) request.getAttribute(ShiroConstants.ONLINE_SESSION); + // 如果session stop了 也不同步 + // session停止时间,如果stopTimestamp不为null,则代表已停止 + if (session != null && session.getUserId() != null && session.getStopTimestamp() == null) + { + sysUserOnlineService.syncToDb(session); + } + return true; + }catch (Exception e){ + logger.error("SyncOnlineSessionFilter preHandle error:", e.getMessage()); + return true; + } + + } + + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/AjaxJson.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/AjaxJson.java new file mode 100644 index 0000000000000000000000000000000000000000..048a232edca552a784d5d19d67c767772d70ea4e --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/AjaxJson.java @@ -0,0 +1,73 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.json; + +import java.util.LinkedHashMap; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.jeespring.common.mapper.JsonMapper; + + +/** + * $.ajax后需要接受的JSON + * + * @author + * + */ +public class AjaxJson { + + private boolean success = true;// 是否成功 + private String errorCode = "-1";//错误代码 + private String msg = "操作成功";// 提示信息 + private LinkedHashMap body = new LinkedHashMap();//封装json的map + + public LinkedHashMap getBody() { + return body; + } + + public void setBody(LinkedHashMap body) { + this.body = body; + } + + public void put(String key, Object value){//向json中添加属性,在js中访问,请调用data.map.key + body.put(key, value); + } + + public void remove(String key){ + body.remove(key); + } + + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) {//向json中添加属性,在js中访问,请调用data.msg + this.msg = msg; + } + + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + @JsonIgnore//返回对象时忽略此属性 + public String getJsonStr() {//返回json字符串数组,将访问msg和key的方式统一化,都使用data.key的方式直接访问。 + + String json = JsonMapper.getInstance().toJson(this); + return json; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorCode() { + return errorCode; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/PrintJSON.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/PrintJSON.java new file mode 100644 index 0000000000000000000000000000000000000000..1770d5ba2457ba00428e5c35f139f2ca62880941 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/json/PrintJSON.java @@ -0,0 +1,28 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.json; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletResponse; + +public class PrintJSON { + + + public static void write(HttpServletResponse response,String content) { + response.reset(); + response.setContentType("application/json"); + response.setHeader("Cache-Control", "no-store"); + response.setCharacterEncoding("UTF-8"); + try { + PrintWriter pw=response.getWriter(); + pw.write(content); + pw.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailAuthenticator.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailAuthenticator.java new file mode 100644 index 0000000000000000000000000000000000000000..8daa50132e543262ea5e40e8c4a27d27301a0c2b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailAuthenticator.java @@ -0,0 +1,21 @@ +package com.jeespring.common.mail; +/** + * + */ +import javax.mail.*; + +public class MailAuthenticator extends Authenticator{ + String userName=null; + String password=null; + + public MailAuthenticator(){ + } + public MailAuthenticator(String username, String password) { + this.userName = username; + this.password = password; + } + @Override + protected PasswordAuthentication getPasswordAuthentication(){ + return new PasswordAuthentication(userName, password); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailBody.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailBody.java new file mode 100644 index 0000000000000000000000000000000000000000..c53b4026242ec10a1e7ad0c0b92b51068bb3d781 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailBody.java @@ -0,0 +1,96 @@ +package com.jeespring.common.mail; +/** + *发送邮件需要使用的基本信息 + * + */ +import java.util.Properties; +public class MailBody { + // 发送邮件的服务器的IP和端口 + private String mailServerHost; + private String mailServerPort = "25"; + // 邮件发送者的地址 + private String fromAddress; + // 邮件接收者的地址 + private String toAddress; + // 登陆邮件发送服务器的用户名和密码 + private String userName; + private String password; + // 是否需要身份验证 + private boolean validate = false; + // 邮件主题 + private String subject; + // 邮件的文本内容 + private String content; + // 邮件附件的文件名 + private String[] attachFileNames; + /** + * 获得邮件会话属性 + */ + public Properties getProperties(){ + Properties p = new Properties(); + p.put("mail.smtp.host", this.mailServerHost); + p.put("mail.smtp.port", this.mailServerPort); + p.put("mail.smtp.auth", validate ? "true" : "false"); + return p; + } + public String getMailServerHost() { + return mailServerHost; + } + public void setMailServerHost(String mailServerHost) { + this.mailServerHost = mailServerHost; + } + public String getMailServerPort() { + return mailServerPort; + } + public void setMailServerPort(String mailServerPort) { + this.mailServerPort = mailServerPort; + } + public boolean isValidate() { + return validate; + } + public void setValidate(boolean validate) { + this.validate = validate; + } + public String[] getAttachFileNames() { + return attachFileNames; + } + public void setAttachFileNames(String[] fileNames) { + this.attachFileNames = fileNames; + } + public String getFromAddress() { + return fromAddress; + } + public void setFromAddress(String fromAddress) { + this.fromAddress = fromAddress; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + public String getToAddress() { + return toAddress; + } + public void setToAddress(String toAddress) { + this.toAddress = toAddress; + } + public String getUserName() { + return userName; + } + public void setUserName(String userName) { + this.userName = userName; + } + public String getSubject() { + return subject; + } + public void setSubject(String subject) { + this.subject = subject; + } + public String getContent() { + return content; + } + public void setContent(String textContent) { + this.content = textContent; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailSendUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailSendUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..80cbf313321b32c150cc87d3546693af1aae076c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mail/MailSendUtils.java @@ -0,0 +1,154 @@ +package com.jeespring.common.mail; +/** + * 简单邮件(不带附件的邮件)发送器 + */ +import java.util.Date; +import java.util.Properties; + +import javax.mail.Address; +import javax.mail.BodyPart; +import javax.mail.Message; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + + +public class MailSendUtils { +/** + * 以文本格式发送邮件 + * @param mailInfo 待发送的邮件的信息 + */ + public boolean sendTextMail(MailBody mailInfo) throws Exception{ + // 判断是否需要身份认证 + MailAuthenticator authenticator = null; + Properties pro = mailInfo.getProperties(); + if (mailInfo.isValidate()) { + // 如果需要身份认证,则创建一个密码验证器 + authenticator = new MailAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); + } + // 根据邮件会话属性和密码验证器构造一个发送邮件的session + Session sendMailSession = Session.getDefaultInstance(pro,authenticator); + // logBefore(logger, "构造一个发送邮件的session"); + + // 根据session创建一个邮件消息 + Message mailMessage = new MimeMessage(sendMailSession); + // 创建邮件发送者地址 + Address from = new InternetAddress(mailInfo.getFromAddress()); + // 设置邮件消息的发送者 + mailMessage.setFrom(from); + // 创建邮件的接收者地址,并设置到邮件消息中 + Address to = new InternetAddress(mailInfo.getToAddress()); + mailMessage.setRecipient(Message.RecipientType.TO,to); + // 设置邮件消息的主题 + mailMessage.setSubject(mailInfo.getSubject()); + // 设置邮件消息发送的时间 + mailMessage.setSentDate(new Date()); + // 设置邮件消息的主要内容 + String mailContent = mailInfo.getContent(); + mailMessage.setText(mailContent); + // 发送邮件 + Transport.send(mailMessage); + System.out.println("发送成功!"); + return true; + } + + /** + * 以HTML格式发送邮件 + * @param mailInfo 待发送的邮件信息 + */ + public boolean sendHtmlMail(MailBody mailInfo) throws Exception{ + // 判断是否需要身份认证 + MailAuthenticator authenticator = null; + Properties pro = mailInfo.getProperties(); + //如果需要身份认证,则创建一个密码验证器 + if (mailInfo.isValidate()) { + authenticator = new MailAuthenticator(mailInfo.getUserName(), mailInfo.getPassword()); + } + // 根据邮件会话属性和密码验证器构造一个发送邮件的session + Session sendMailSession = Session.getDefaultInstance(pro,authenticator); + + // 根据session创建一个邮件消息 + Message mailMessage = new MimeMessage(sendMailSession); + // 创建邮件发送者地址 + Address from = new InternetAddress(mailInfo.getFromAddress()); + // 设置邮件消息的发送者 + mailMessage.setFrom(from); + // 创建邮件的接收者地址,并设置到邮件消息中 + Address to = new InternetAddress(mailInfo.getToAddress()); + // Message.RecipientType.TO属性表示接收者的类型为TO + mailMessage.setRecipient(Message.RecipientType.TO,to); + // 设置邮件消息的主题 + mailMessage.setSubject(mailInfo.getSubject()); + // 设置邮件消息发送的时间 + mailMessage.setSentDate(new Date()); + // MiniMultipart类是一个容器类,包含MimeBodyPart类型的对象 + Multipart mainPart = new MimeMultipart(); + // 创建一个包含HTML内容的MimeBodyPart + BodyPart html = new MimeBodyPart(); + // 设置HTML内容 + html.setContent(mailInfo.getContent(), "text/html; charset=utf-8"); + mainPart.addBodyPart(html); + // 将MiniMultipart对象设置为邮件内容 + mailMessage.setContent(mainPart); + // 发送邮件 + Transport.send(mailMessage); + return true; + } + + /** + * @param SMTP + * 邮件服务器 + * @param PORT + * 端口 + * @param EMAIL + * 本邮箱账号 + * @param PAW + * 本邮箱密码 + * @param toEMAIL + * 对方箱账号 + * @param TITLE + * 标题 + * @param CONTENT + * 内容 + * @param TYPE + * 1:文本格式;2:HTML格式 + */ + public static boolean sendEmail(String SMTP, String PORT, String EMAIL, + String PAW, String toEMAIL, String TITLE, String CONTENT, + String TYPE) { + + // 这个类主要是设置邮件 + MailBody mailInfo = new MailBody(); + + mailInfo.setMailServerHost(SMTP); + mailInfo.setMailServerPort(PORT); + mailInfo.setValidate(true); + mailInfo.setUserName(EMAIL); + mailInfo.setPassword(PAW); + mailInfo.setFromAddress(EMAIL); + mailInfo.setToAddress(toEMAIL); + mailInfo.setSubject(TITLE); + mailInfo.setContent(CONTENT); + // 这个类主要来发送邮件 + + MailSendUtils sms = new MailSendUtils(); + try { + if ("1".equals(TYPE)) { + return sms.sendTextMail(mailInfo); + } else { + return sms.sendHtmlMail(mailInfo); + } + } catch (Exception e) { + return false; + } + + } + + + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/BeanMapper.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/BeanMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..c0f740398d4d30c823b1256c8e4e818189341400 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/BeanMapper.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.mapper; + +import java.util.Collection; +import java.util.List; + +import org.dozer.DozerBeanMapper; + +import com.google.common.collect.Lists; + +/** + * 简单封装Dozer, 实现深度转换Bean<->Bean的Mapper.实现: + * + * 1. 持有Mapper的单例. + * 2. 返回值类型转换. + * 3. 批量转换Collection中的所有对象. + * 4. 区分创建新的B对象与将对象A值复制到已存在的B对象两种函数. + * + * @author calvin + * @version 2013-01-15 + */ +public class BeanMapper { + + /** + * 持有Dozer单例, 避免重复创建DozerMapper消耗资源. + */ + private static DozerBeanMapper dozer = new DozerBeanMapper(); + + /** + * 基于Dozer转换对象的类型. + */ + public static T map(Object source, Class destinationClass) { + return dozer.map(source, destinationClass); + } + + /** + * 基于Dozer转换Collection中对象的类型. + */ + @SuppressWarnings("rawtypes") + public static List mapList(Collection sourceList, Class destinationClass) { + List destinationList = Lists.newArrayList(); + for (Object sourceObject : sourceList) { + T destinationObject = dozer.map(sourceObject, destinationClass); + destinationList.add(destinationObject); + } + return destinationList; + } + + /** + * 基于Dozer将对象A的值拷贝到对象B中. + */ + public static void copy(Object source, Object destinationObject) { + dozer.map(source, destinationObject); + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JaxbMapper.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JaxbMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..284426cd844c61577703c1f41898dd361620dd3f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JaxbMapper.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.mapper; + +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAnyElement; +import javax.xml.namespace.QName; + +import org.springframework.http.converter.HttpMessageConversionException; +import org.springframework.util.Assert; + +import com.jeespring.common.utils.Exceptions; +import com.jeespring.common.utils.Reflections; +import com.jeespring.common.utils.StringUtils; + +/** + * 使用Jaxb2.0实现XML<->Java Object的Mapper. + * + * 在创建时需要设定所有需要序列化的Root对象的Class. + * 特别支持Root对象是Collection的情形. + * + * @author calvin + * @version 2013-01-15 + */ +@SuppressWarnings("rawtypes") +public class JaxbMapper { + + private static ConcurrentMap jaxbContexts = new ConcurrentHashMap(); + + /** + * Java Object->Xml without encoding. + */ + public static String toXml(Object root) { + Class clazz = Reflections.getUserClass(root); + return toXml(root, clazz, null); + } + + /** + * Java Object->Xml with encoding. + */ + public static String toXml(Object root, String encoding) { + Class clazz = Reflections.getUserClass(root); + return toXml(root, clazz, encoding); + } + + /** + * Java Object->Xml with encoding. + */ + public static String toXml(Object root, Class clazz, String encoding) { + try { + StringWriter writer = new StringWriter(); + createMarshaller(clazz, encoding).marshal(root, writer); + return writer.toString(); + } catch (JAXBException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * Java Collection->Xml without encoding, 特别支持Root Element是Collection的情形. + */ + public static String toXml(Collection> root, String rootName, Class clazz) { + return toXml(root, rootName, clazz, null); + } + + /** + * Java Collection->Xml with encoding, 特别支持Root Element是Collection的情形. + */ + public static String toXml(Collection> root, String rootName, Class clazz, String encoding) { + try { + CollectionWrapper wrapper = new CollectionWrapper(); + wrapper.collection = root; + + JAXBElement wrapperElement = new JAXBElement(new QName(rootName), + CollectionWrapper.class, wrapper); + + StringWriter writer = new StringWriter(); + createMarshaller(clazz, encoding).marshal(wrapperElement, writer); + + return writer.toString(); + } catch (JAXBException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * Xml->Java Object. + */ + @SuppressWarnings("unchecked") + public static T fromXml(String xml, Class clazz) { + try { + StringReader reader = new StringReader(xml); + return (T) createUnmarshaller(clazz).unmarshal(reader); + } catch (JAXBException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 创建Marshaller并设定encoding(可为null). + * 线程不安全,需要每次创建或pooling。 + */ + public static Marshaller createMarshaller(Class clazz, String encoding) { + try { + JAXBContext jaxbContext = getJaxbContext(clazz); + + Marshaller marshaller = jaxbContext.createMarshaller(); + + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + if (StringUtils.isNotBlank(encoding)) { + marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding); + } + + return marshaller; + } catch (JAXBException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 创建UnMarshaller. + * 线程不安全,需要每次创建或pooling。 + */ + public static Unmarshaller createUnmarshaller(Class clazz) { + try { + JAXBContext jaxbContext = getJaxbContext(clazz); + return jaxbContext.createUnmarshaller(); + } catch (JAXBException e) { + throw Exceptions.unchecked(e); + } + } + + protected static JAXBContext getJaxbContext(Class clazz) { + Assert.notNull(clazz, "'clazz' must not be null"); + JAXBContext jaxbContext = jaxbContexts.get(clazz); + if (jaxbContext == null) { + try { + jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class); + jaxbContexts.putIfAbsent(clazz, jaxbContext); + } catch (JAXBException ex) { + throw new HttpMessageConversionException("Could not instantiate JAXBContext for class [" + clazz + + "]: " + ex.getMessage(), ex); + } + } + return jaxbContext; + } + + /** + * 封装Root Element 是 Collection的情况. + */ + public static class CollectionWrapper { + + @XmlAnyElement + protected Collection> collection; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JsonMapper.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JsonMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..050c97dfe5cf986a13bfc4f2f02112a18d432f25 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/JsonMapper.java @@ -0,0 +1,257 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.mapper; + +import java.io.IOException; +import java.util.TimeZone; + +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser.Feature; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.util.JSONPObject; +import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; + +/** + * 简单封装Jackson,实现JSON String<->Java Object的Mapper. + * 封装不同的输出风格, 使用不同的builder函数创建实例. + * @author 黄炳桂 516821420@qq.com + * @version 2013-11-15 + */ +public class JsonMapper extends ObjectMapper { + + private static final long serialVersionUID = 1L; + + private static Logger logger = LoggerFactory.getLogger(JsonMapper.class); + + private static JsonMapper mapper; + + public JsonMapper() { + this(Include.NON_EMPTY); + } + + public JsonMapper(Include include) { + // 设置输出时包含属性的风格 + if (include != null) { + this.setSerializationInclusion(include); + } + // 允许单引号、允许不带引号的字段名称 + this.enableSimple(); + // 设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性 + this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + // 空值处理为空串 + this.getSerializerProvider().setNullValueSerializer(new JsonSerializer(){ + @Override + public void serialize(Object value, JsonGenerator jgen, + SerializerProvider provider) throws IOException, + JsonProcessingException { + jgen.writeString(""); + } + }); + // 进行HTML解码。 + this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer(){ + @Override + public void serialize(String value, JsonGenerator jgen, + SerializerProvider provider) throws IOException, + JsonProcessingException { + jgen.writeString(StringEscapeUtils.unescapeHtml4(value)); + } + })); + // 设置时区 + this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00") + } + + /** + * 创建只输出非Null且非Empty(如List.isEmpty)的属性到Json字符串的Mapper,建议在外部接口中使用. + */ + public static JsonMapper getInstance() { + if (mapper == null){ + mapper = new JsonMapper().enableSimple(); + } + return mapper; + } + + /** + * 创建只输出初始值被改变的属性到Json字符串的Mapper, 最节约的存储方式,建议在内部接口中使用。 + */ + public static JsonMapper nonDefaultMapper() { + if (mapper == null){ + mapper = new JsonMapper(Include.NON_DEFAULT); + } + return mapper; + } + + /** + * Object可以是POJO,也可以是Collection或数组。 + * 如果对象为Null, 返回"null". + * 如果集合为空集合, 返回"[]". + */ + public String toJson(Object object) { + try { + return this.writeValueAsString(object); + } catch (IOException e) { + logger.warn("write to json string error:" + object, e); + return null; + } + } + + /** + * 反序列化POJO或简单Collection如List. + * + * 如果JSON字符串为Null或"null"字符串, 返回Null. + * 如果JSON字符串为"[]", 返回空集合. + * + * 如需反序列化复杂Collection如List, 请使用fromJson(String,JavaType) + * @see #fromJson(String, JavaType) + */ + public T fromJson(String jsonString, Class clazz) { + if (StringUtils.isEmpty(jsonString)) { + return null; + } + try { + return this.readValue(jsonString, clazz); + } catch (IOException e) { + logger.warn("parse json string error:" + jsonString, e); + return null; + } + } + + /** + * 反序列化复杂Collection如List, 先使用函數createCollectionType构造类型,然后调用本函数. + * @see #createCollectionType(Class, Class...) + */ + @SuppressWarnings("unchecked") + public T fromJson(String jsonString, JavaType javaType) { + if (StringUtils.isEmpty(jsonString)) { + return null; + } + try { + return (T) this.readValue(jsonString, javaType); + } catch (IOException e) { + logger.warn("parse json string error:" + jsonString, e); + return null; + } + } + + /** + * 構造泛型的Collection Type如: + * ArrayList, 则调用constructCollectionType(ArrayList.class,MyBean.class) + * HashMap, 则调用(HashMap.class,String.class, MyBean.class) + */ + public JavaType createCollectionType(Class> collectionClass, Class>... elementClasses) { + return this.getTypeFactory().constructParametricType(collectionClass, elementClasses); + } + + /** + * 當JSON裡只含有Bean的部分屬性時,更新一個已存在Bean,只覆蓋該部分的屬性. + */ + @SuppressWarnings("unchecked") + public T update(String jsonString, T object) { + try { + return (T) this.readerForUpdating(object).readValue(jsonString); + } catch (JsonProcessingException e) { + logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e); + } catch (IOException e) { + logger.warn("update json string:" + jsonString + " to object:" + object + " error.", e); + } + return null; + } + + /** + * 輸出JSONP格式數據. + */ + public String toJsonP(String functionName, Object object) { + return toJson(new JSONPObject(functionName, object)); + } + + /** + * 設定是否使用Enum的toString函數來讀寫Enum, + * 為False時時使用Enum的name()函數來讀寫Enum, 默認為False. + * 注意本函數一定要在Mapper創建後, 所有的讀寫動作之前調用. + */ + public JsonMapper enableEnumUseToString() { + this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + return this; + } + + /** + * 支持使用Jaxb的Annotation,使得POJO上的annotation不用与Jackson耦合。 + * 默认会先查找jaxb的annotation,如果找不到再找jackson的。 + */ + public JsonMapper enableJaxbAnnotation() { + JaxbAnnotationModule module = new JaxbAnnotationModule(); + this.registerModule(module); + return this; + } + + /** + * 允许单引号 + * 允许不带引号的字段名称 + */ + public JsonMapper enableSimple() { + this.configure(Feature.ALLOW_SINGLE_QUOTES, true); + this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + return this; + } + + /** + * 取出Mapper做进一步的设置或使用其他序列化API. + */ + public ObjectMapper getMapper() { + return this; + } + + /** + * 对象转换为JSON字符串 + * @param object + * @return + */ + public static String toJsonString(Object object){ + return JsonMapper.getInstance().toJson(object); + } + + /** + * JSON字符串转换为对象 + * @param jsonString + * @param clazz + * @return + */ + public static Object fromJsonString(String jsonString, Class> clazz){ + return JsonMapper.getInstance().fromJson(jsonString, clazz); + } + + /** + * 测试 + */ +// public static void main(String[] args) { +// List> list = Lists.newArrayList(); +// Map map = Maps.newHashMap(); +// map.put("id", 1); +// map.put("pId", -1); +// map.put("name", "根节点"); +// list.add(map); +// map = Maps.newHashMap(); +// map.put("id", 2); +// map.put("pId", 1); +// map.put("name", "你好"); +// map.put("open", true); +// list.add(map); +// String json = JsonMapper.getInstance().toJson(list); +// System.out.println(json); +// } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapAdapter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..78edf3f2dec5630ce2efdeb5119a8aeb2a358b26 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapAdapter.java @@ -0,0 +1,30 @@ +package com.jeespring.common.mapper.adapters; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +public class MapAdapter extends XmlAdapter> { + + @Override + public MapConvertor marshal(Map map) throws Exception { + MapConvertor convertor = new MapConvertor(); + for (Map.Entry entry : map.entrySet()) { + MapConvertor.MapEntry e = new MapConvertor.MapEntry(entry); + convertor.addEntry(e); + } + return convertor; + } + + @Override + public Map unmarshal(MapConvertor map) throws Exception { + Map result = new HashMap(); + for (MapConvertor.MapEntry e : map.getEntries()) { + result.put(e.getKey(), e.getValue()); + } + return result; + } + +} + diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapConvertor.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapConvertor.java new file mode 100644 index 0000000000000000000000000000000000000000..197860f3a7f424aaa654169adf17083125c47e88 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/mapper/adapters/MapConvertor.java @@ -0,0 +1,63 @@ +package com.jeespring.common.mapper.adapters; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +@XmlType(name = "MapConvertor") +@XmlAccessorType(XmlAccessType.FIELD) +public class MapConvertor { + + private List entries = new ArrayList(); + + public void addEntry(MapEntry entry) { + entries.add(entry); + } + + public List getEntries() { + return entries; + } + + public static class MapEntry { + + private String key; + + private Object value; + + public MapEntry() { + super(); + } + + public MapEntry(Map.Entry entry) { + super(); + this.key = entry.getKey(); + this.value = entry.getValue(); + } + + public MapEntry(String key, Object value) { + super(); + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractBaseEntity.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractBaseEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..a8cbff12e407a95af73dabda04d7bdfd488c1f27 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractBaseEntity.java @@ -0,0 +1,184 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import java.util.Date; +import java.util.HashMap; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONField; +import com.jeespring.common.utils.IdGen; +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.utils.UserUtils; +import org.apache.commons.lang3.StringUtils; +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * 数据Entity类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +public abstract class AbstractBaseEntity extends AbstractEntity { + + private static final long serialVersionUID = 1L; + + protected String remarks; // 备注 + protected User createBy; // 创建者 + protected Date createDate; // 创建日期 + protected User updateBy; // 更新者 + protected Date updateDate; // 更新日期 + protected String delFlag; // 删除标记(0:正常;1:删除;2:审核) + protected HashMap extendMap;//HashMap对象的拓展属性 + protected JSONObject jsonObject;//JSONObject对象的拓展属性 + protected Integer totalCount; + protected String totalDate; + protected String totalType; + + public void setExtendMap(String item,Object object) { + if(extendMap==null) { + extendMap = new HashMap(); + } + extendMap.put(item,object); + } + + public HashMap getExtendMap() { + return extendMap; + } + + public JSONObject setExtendObject(String item,Object object){ + if(jsonObject==null) { + jsonObject = JSON.parseObject(JSON.toJSONString(this)); + } + jsonObject.put(item,object); + return jsonObject; + } + + public AbstractBaseEntity() { + super(); + this.delFlag = DEL_FLAG_NORMAL; + } + + public AbstractBaseEntity(String id) { + super(id); + } + + /** + * 插入之前执行方法,需要手动调用 + */ + @Override + public void preInsert(){ + // 不限制ID为UUID,调用setIsNewRecord()使用自定义ID + if (!this.isNewRecord){ + setId(IdGen.uuid()); + } + User user = UserUtils.getUser(); + if (StringUtils.isNotBlank(user.getId())){ + this.updateBy = user; + this.createBy = user; + } + this.updateDate = new Date(); + this.createDate = this.updateDate; + } + + /** + * 更新之前执行方法,需要手动调用 + */ + @Override + public void preUpdate(){ + User user = UserUtils.getUser(); + if (StringUtils.isNotBlank(user.getId())){ + this.updateBy = user; + } + this.updateDate = new Date(); + } + + @Length(min=0, max=255) + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + @JsonIgnore + @JSONField(serialize=false) + public User getCreateBy() { + return createBy; + } + + public void setCreateBy(User createBy) { + this.createBy = createBy; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + @JsonIgnore + @JSONField(serialize=false) + public User getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(User updateBy) { + this.updateBy = updateBy; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + public Date getUpdateDate() { + return updateDate; + } + + public void setUpdateDate(Date updateDate) { + this.updateDate = updateDate; + } + + @JsonIgnore + @JSONField(serialize=false) + @Length(min=1, max=1) + public String getDelFlag() { + if(delFlag==null) { + delFlag = "0"; + } + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public Integer getTotalCount() { + return totalCount; + } + + public void setTotalCount(Integer totalCount) { + this.totalCount = totalCount; + } + + public String getTotalDate() { + return totalDate; + } + + public void setTotalDate(String totalDate) { + this.totalDate = totalDate; + } + + public String getTotalType() { + return totalType; + } + + public void setTotalType(String totalType) { + this.totalType = totalType; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractEntity.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..6428bb37f89e58110e0f35cff7ae149861a2593f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/AbstractEntity.java @@ -0,0 +1,237 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.google.common.collect.Maps; +import com.jeespring.common.config.Global; +import com.jeespring.common.utils.StringUtils; +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.utils.UserUtils; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +import javax.xml.bind.annotation.XmlTransient; +import java.io.Serializable; +import java.util.Map; + +/** + * Entity支持类 + * + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +//@SupTreeList +public abstract class AbstractEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 实体编号(唯一标识) + */ + protected String id; + + /** + * 当前用户 + */ + protected User currentUser; + + /** + * 当前实体分页对象 + */ + protected Page page; + private String orderBy = ""; // 标准查询有效, 实例: updatedate desc, name asc + private String groupBy = ""; // 标准查询有效, 实例: updatedate desc, name asc + private String where = ""; // 标准查询条件 + protected int pageNo = 1; // 当前页码 + protected int pageSize = Integer.valueOf(Global.getConfig("page.pageSize")); // 页面大小,设置为“-1”表示不进行分页(分页无效) + + /** + * 自定义SQL(SQL标识,SQL内容) + */ + protected Map sqlMap; + + /** + * 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。 + * 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。 + */ + protected boolean isNewRecord = false; + + public AbstractEntity() { + + } + + public AbstractEntity(String id) { + this(); + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @JsonIgnore + @XmlTransient + @JSONField(serialize=false) + public User getCurrentUser() { + if (currentUser == null) { + currentUser = UserUtils.getUser(); + } + return currentUser; + } + + public void setCurrentUser(User currentUser) { + this.currentUser = currentUser; + } + + @JsonIgnore + @XmlTransient + @JSONField(serialize=false) + public Page getPage() { + if (page == null) { + page = new Page(); + } + return page; + } + + public Page setPage(Page page) { + this.page = page; + return page; + } + + @JsonIgnore + @XmlTransient + @JSONField(serialize=false) + public String getWhere() { + return where; + } + + public void setWhere(String where) { + this.where = where; + } + + public String getOrderBy() { + return orderBy; + } + + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + public String getGroupBy() { + return groupBy; + } + + public void setGroupBy(String groupBy) { + this.groupBy = groupBy; + } + + public int getPageNo() { + return pageNo; + } + + public void setPageNo(int pageNo) { + this.pageNo = pageNo; + } + + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + @JsonIgnore + @XmlTransient + @JSONField(serialize=false) + public Map getSqlMap() { + if (sqlMap == null) { + sqlMap = Maps.newHashMap(); + } + return sqlMap; + } + + public void setSqlMap(Map sqlMap) { + this.sqlMap = sqlMap; + } + + /** + * 插入之前执行方法,子类实现 + */ + public abstract void preInsert(); + + /** + * 更新之前执行方法,子类实现 + */ + public abstract void preUpdate(); + + /** + * 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。 + * 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。 + * + * @return + */ + public boolean getIsNewRecord() { + return isNewRecord || StringUtils.isBlank(getId()); + } + + /** + * 是否是新记录(默认:false),调用setIsNewRecord()设置新记录,使用自定义ID。 + * 设置为true后强制执行插入语句,ID不会自动生成,需从手动传入。 + */ + public void setIsNewRecord(boolean isNewRecord) { + this.isNewRecord = isNewRecord; + } + + /** + * 全局变量对象 + */ + @JsonIgnore + @JSONField(serialize=false) + public Global getGlobal() { + return new Global(); + } + /** + * 获取数据库名称,该方法至关重要,在所有的mapper里面都是用 + */ + @JsonIgnore + @JSONField(serialize=false) + public String getDbName() { + return Global.getJdbcType(); + } + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + if (this == obj) { + return true; + } + if (!getClass().equals(obj.getClass())) { + return false; + } + AbstractEntity> that = (AbstractEntity>) obj; + return null == this.getId() ? false : this.getId().equals(that.getId()); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + + /** + * 删除标记(0:正常;1:删除;2:审核;) + */ + public static final String DEL_FLAG_NORMAL = "0"; + public static final String DEL_FLAG_DELETE = "1"; + public static final String DEL_FLAG_AUDIT = "2"; + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/ActEntity.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/ActEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..950a4ebc2a6e551cc0c87cf64f35b01dd619c5c6 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/ActEntity.java @@ -0,0 +1,57 @@ +/** + * Copyright © 2012-2016 JeeSpring All rights reserved. + */ +package com.jeespring.common.persistence; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.jeespring.modules.act.entity.Act; + +/** + * Activiti Entity类 + * @author JeeSpring + * @version 2013-05-28 + */ +public abstract class ActEntity extends AbstractBaseEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + protected Act act; // 流程任务对象 + + public ActEntity() { + super(); + } + + public ActEntity(String id) { + super(id); + } + + @JsonIgnore + public Act getAct() { + if (act == null){ + act = new Act(); + } + return act; + } + + public void setAct(Act act) { + this.act = act; + } + + /** + * 获取流程实例ID + * @return + */ + public String getProcInsId() { + return this.getAct().getProcInsId(); + } + + /** + * 设置流程实例ID + * @param procInsId + */ + public void setProcInsId(String procInsId) { + this.getAct().setProcInsId(procInsId); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseDao.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseDao.java new file mode 100644 index 0000000000000000000000000000000000000000..9dc406eb26706eb64c0b3b3cecd40eeeffe91232 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseDao.java @@ -0,0 +1,129 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +/** + * DAO支持类实现 + * + * @param + * * * * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +public interface InterfaceBaseDao extends InterfaceDao { + + /** + * 获取单条数据 + * + * @param id + * @return + */ + T get(String id); + + /** + * 获取单条数据 + * + * @param entity + * @return + */ + T get(T entity); + + /** + * 根据实体名称和字段名称和字段值获取唯一记录 + * + * @param + * @param entityClass + * @param propertyName + * @param value + * @return + */ + T findUniqueByProperty(@Param(value = "propertyName") String propertyName, @Param(value = "value") Object value); + + /** + * 查询统计列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page()); + * + * @param entity + * @return + */ + List total(T entity); + + /** + * 查询数据列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page()); + * + * @param entity + * @return + */ + List findList(T entity); + + /** + * 查询所有数据列表 + * + * @param entity + * @return + */ + List findAllList(T entity); + + /** + * 查询所有数据列表 + * + * @return + * @see public List findAllList(T entity) + */ + @Deprecated + List findAllList(); + + /** + * 插入数据 + * + * @param entity + * @return + */ + int insert(T entity); + + /** + * 更新数据 + * + * @param entity + * @return + */ + int update(T entity); + + /** + * 删除数据(一般为逻辑删除,更新del_flag字段为1) + * + * @param id + * @return + * @see public int delete(T entity) + */ + @Deprecated + int delete(String id); + + /** + * 删除数据(逻辑删除,更新del_flag字段为1,在表包含字段del_flag时,可以调用此方法,将数据隐藏) + * @param id + * @see public int delete(T entity) + * @return + */ + @Deprecated + int deleteByLogic(String id); + + /** + * 删除数据(一般为逻辑删除,更新del_flag字段为1) + * + * @param entity + * @return + */ + int delete(T entity); + + /** + * 删除数据(逻辑删除,更新del_flag字段为1,在表包含字段del_flag时,可以调用此方法,将数据隐藏) + * @param entity + * @return + */ + int deleteByLogic(T entity); + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseService.java new file mode 100644 index 0000000000000000000000000000000000000000..bc3647626fee9c3c3d62bef78a9a4517f7b5be9e --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceBaseService.java @@ -0,0 +1,91 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import com.jeespring.modules.server.entity.SysServer; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * DAO支持类实现 + * + * @param + * * * * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +public interface InterfaceBaseService { + + /** + * 获取单条数据 + * + * @param id + * @return + */ + T get(String id); + + /** + * 获取单条数据 + * + * @param entity + * @return + */ + T get(T entity); + + T getCache(String id); + + List totalCache(T entity); + /** + * 查询统计列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page()); + * + * @param entity + * @return + */ + List total(T entity); + + /** + * 查询数据列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page()); + * + * @param entity + * @return + */ + List findList(T entity); + + List findAllList(T entity); + + List findListCache(T entity); + + Page findPage(Page page, T entity); + + Page findPageCache(Page page, T entity); + + /** + * 插入数据 + * + * @param entity + * @return + */ + void save(T entity); + + /** + * 删除数据(一般为逻辑删除,更新del_flag字段为1) + * + * @param entity + * @return + * @see public int delete(T entity) + * @Deprecated + */ + void delete(T entity); + + /** + * 删除数据(逻辑删除,更新del_flag字段为1,在表包含字段del_flag时,可以调用此方法,将数据隐藏) + * @param entity + * @see public int delete(T entity) + * @return + * @Deprecated + */ + void deleteByLogic(T entity); + + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceDao.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceDao.java new file mode 100644 index 0000000000000000000000000000000000000000..3ecc6610ff38e2503abf918d7abb6950ae50973b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/InterfaceDao.java @@ -0,0 +1,13 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +/** + * DAO支持类实现 + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +public interface InterfaceDao { + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/Page.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/Page.java new file mode 100644 index 0000000000000000000000000000000000000000..08bd053eabe84c71a4bdd3ca896f7781b2cfc891 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/Page.java @@ -0,0 +1,711 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.jeespring.common.config.Global; +import org.apache.commons.lang3.StringUtils; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.jeespring.common.utils.CookieUtils; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; + +/** + * 分页类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-7-2 + * @param + */ +public class Page implements Serializable { + + protected int pageNo = 1; // 当前页码 + protected int pageSize = Integer.valueOf(Global.getConfig("page.pageSize")); // 页面大小,设置为“-1”表示不进行分页(分页无效) + + protected long count;// 总记录数,设置为“-1”表示不查询总数 + + protected int first;// 首页索引 + protected int last;// 尾页索引 + protected int prev;// 上一页索引 + protected int next;// 下一页索引 + + private boolean firstPage;//是否是第一页 + private boolean lastPage;//是否是最后一页 + + protected int length = 8;// 显示页面长度 + protected int slider = 1;// 前后显示页面长度 + + private List list = new ArrayList(); + + private String orderBy = ""; // 标准查询有效, 实例: updatedate desc, name asc + + protected String funcName = "page"; // 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。 + + protected String funcParam = ""; // 函数的附加参数,第三个参数值。 + + private String message = ""; // 设置提示消息,显示在“共n条”之后 + + public Page() { + this.pageSize = -1; + } + + /** + * 构造方法 + * @param request 传递 repage 参数,来记住页码 + * @param response 用于设置 Cookie,记住页码 + */ + public Page(HttpServletRequest request, HttpServletResponse response){ + this(request, response, -2); + } + + public Page(int pageNo, int pageSize,String orderBy){ + this(pageNo, pageSize,0); + this.orderBy=orderBy; + } + + + /** + * 构造方法 + * @param request 传递 repage 参数,来记住页码 + * @param response 用于设置 Cookie,记住页码 + * @param defaultPageSize 默认分页大小,如果传递 -1 则为不分页,返回所有数据 + */ + public Page(HttpServletRequest request, HttpServletResponse response, int defaultPageSize){ + // 设置页码参数(传递repage参数,来记住页码) + String no = request.getParameter("pageNo"); + if (StringUtils.isNumeric(no)){ + CookieUtils.setCookie(response, "pageNo", no); + this.setPageNo(Integer.parseInt(no)); + }else if (request.getParameter("repage")!=null){ + no = CookieUtils.getCookie(request, "pageNo"); + if (StringUtils.isNumeric(no)){ + this.setPageNo(Integer.parseInt(no)); + } + } + // 设置页面大小参数(传递repage参数,来记住页码大小) + String size = request.getParameter("pageSize"); + if (StringUtils.isNumeric(size)){ + CookieUtils.setCookie(response, "pageSize", size); + this.setPageSize(Integer.parseInt(size)); + }else if (request.getParameter("repage")!=null){ + no = CookieUtils.getCookie(request, "pageSize"); + if (StringUtils.isNumeric(size)){ + this.setPageSize(Integer.parseInt(size)); + } + }else if (defaultPageSize != -2){ + this.pageSize = defaultPageSize; + } + // 设置排序参数 + String orderBy = request.getParameter("orderBy"); + if (StringUtils.isNotBlank(orderBy)){ + this.setOrderBy(orderBy); + } + } + + /** + * 构造方法 + * @param pageNo 当前页码 + * @param pageSize 分页大小 + */ + public Page(int pageNo, int pageSize) { + this(pageNo, pageSize, 0); + } + + /** + * 构造方法 + * @param pageNo 当前页码 + * @param pageSize 分页大小 + * @param count 数据条数 + */ + public Page(int pageNo, int pageSize, long count) { + this(pageNo, pageSize, count, new ArrayList()); + } + + /** + * 构造方法 + * @param pageNo 当前页码 + * @param pageSize 分页大小 + * @param count 数据条数 + * @param list 本页数据对象列表 + */ + public Page(int pageNo, int pageSize, long count, List list) { + this.setCount(count); + this.setPageNo(pageNo); + this.pageSize = pageSize; + this.list = list; + } + + /** + * 初始化参数 + */ + public void initialize(){ + + //1 + this.first = 1; + + this.last = (int)(count / (this.pageSize < 1 ? 20 : this.pageSize) + first - 1); + + if (this.count % this.pageSize != 0 || this.last == 0) { + this.last++; + } + + if (this.last < this.first) { + this.last = this.first; + } + + if (this.pageNo <= 1) { + this.pageNo = this.first; + this.firstPage=true; + } + + if (this.pageNo >= this.last) { + this.pageNo = this.last; + this.lastPage=true; + } + + if (this.pageNo < this.last - 1) { + this.next = this.pageNo + 1; + } else { + this.next = this.last; + } + + if (this.pageNo > 1) { + this.prev = this.pageNo - 1; + } else { + this.prev = this.first; + } + + //2 + if (this.pageNo < this.first) {// 如果当前页小于首页 + this.pageNo = this.first; + } + + if (this.pageNo > this.last) {// 如果当前页大于尾页 + this.pageNo = this.last; + } + + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this); + } + /** + * 默认输出当前分页标签 + * ${page} + */ + public String toStringPage() { + + StringBuilder sb = new StringBuilder(); + sb.append(""); +// sb.append(""); +// sb.append("当前 "); +// sb.append(" / "); +// sb.append(" 条,"); +// sb.append("共 " + count + " 条"+(message!=null?message:"")+"\n"); +// sb.append(""); + long startIndex = (pageNo-1)*pageSize + 1; + long endIndex = pageNo*pageSize <=count? pageNo*pageSize:count; + + sb.append(""); + sb.append("显示第 "+startIndex+" 到第 "+ endIndex +" 条记录,总共 "+count+" 条记录"); + sb.append("每页显示 "); + sb.append(""); + sb.append(""+pageSize+" "); + sb.append(""); + sb.append(""); + sb.append("10"); + sb.append("25"); + sb.append("50"); + sb.append("100"); + sb.append("1000"); + sb.append("全部"); + sb.append(""); + sb.append(" 条记录"); + sb.append(""); +// sb.append("每页 " + +// "10" + +// "25" + +// "50" + +// "100" + +// " 条记录,显示 " +startIndex+ " 到 "+ endIndex +" 条,共 "+count+" 条"); +// sb.append(""); +// sb.append(""); + + + + + sb.append(""); + sb.append(""); + if (pageNo == first) {// 如果是首页 + sb.append("\n"); + sb.append("\n"); + } else { + sb.append("\n"); + sb.append("\n"); + } + + int begin = pageNo - (length / 2); + + if (begin < first) { + begin = first; + } + + int end = begin + length - 1; + + if (end >= last) { + end = last; + begin = end - length + 1; + if (begin < first) { + begin = first; + } + } + + if (begin > first) { + int i = 0; + for (i = first; i < first + slider && i < begin; i++) { + sb.append("" + + (i + 1 - first) + "\n"); + } + if (i < begin) { + sb.append("...\n"); + } + } + + for (int i = begin; i <= end; i++) { + if (i == pageNo) { + sb.append("" + (i + 1 - first) + + "\n"); + } else { + sb.append("" + + (i + 1 - first) + "\n"); + } + } + + if (last - end > slider) { + sb.append("...\n"); + end = last - slider; + } + + for (int i = end + 1; i <= last; i++) { + sb.append("" + + (i + 1 - first) + "\n"); + } + + if (pageNo == last) { + sb.append("\n"); + sb.append("\n"); + } else { + sb.append("" + + "\n"); + sb.append("" + + "\n"); + } + + + sb.append(""); + sb.append(""); + sb.append(""); +// sb.insert(0,"\n").append("\n"); + +// sb.append(""); + +// sb.insert(0,"\n").append("\n"); + + return sb.toString(); + } + + /** + * 默认输出当前分页标签 + * ${page} + */ + public String getPageHtml() { + + StringBuilder sb = new StringBuilder(); + + if (pageNo == first) {// 如果是首页 + sb.append("« 上一页\n"); + } else { + sb.append("« 上一页\n"); + } + + int begin = pageNo - (length / 2); + + if (begin < first) { + begin = first; + } + + int end = begin + length - 1; + + if (end >= last) { + end = last; + begin = end - length + 1; + if (begin < first) { + begin = first; + } + } + + if (begin > first) { + int i = 0; + for (i = first; i < first + slider && i < begin; i++) { + sb.append("" + + (i + 1 - first) + "\n"); + } + if (i < begin) { + sb.append("...\n"); + } + } + + for (int i = begin; i <= end; i++) { + if (i == pageNo) { + sb.append("" + (i + 1 - first) + + "\n"); + } else { + sb.append("" + + (i + 1 - first) + "\n"); + } + } + + if (last - end > slider) { + sb.append("...\n"); + end = last - slider; + } + + for (int i = end + 1; i <= last; i++) { + sb.append("" + + (i + 1 - first) + "\n"); + } + + if (pageNo == last) { + sb.append("下一页 »\n"); + } else { + sb.append("" + + "下一页 »\n"); + } + + sb.append("当前 "); + sb.append(" / "); + sb.append(" 条,"); + sb.append("共 " + count + " 条"+(message!=null?message:"")+"\n"); + + sb.insert(0,"\n").append("\n"); + + sb.append(""); + +// sb.insert(0,"\n").append("\n"); + + return sb.toString(); + } + protected String getSelected(int pageNo, int selectedPageNo){ + if(pageNo == selectedPageNo){ + //return "selected"; + return "active"; + }else{ + return ""; + } + + } + /** + * 获取分页HTML代码 + * @return + */ + //@JsonIgnore + public String getHtml(){ + return toStringPage(); + } + +// public static void main(String[] args) { +// Page p = new Page(3, 3); +// System.out.println(p); +// System.out.println("首页:"+p.getFirst()); +// System.out.println("尾页:"+p.getLast()); +// System.out.println("上页:"+p.getPrev()); +// System.out.println("下页:"+p.getNext()); +// } + + /** + * 获取设置总数 + * @return + */ + public long getCount() { + return count; + } + + /** + * 设置数据总数 + * @param count + */ + public void setCount(long count) { + this.count = count; + if (pageSize >= count){ + pageNo = 1; + } + } + + /** + * 获取当前页码 + * @return + */ + public int getPageNo() { + return pageNo; + } + + /** + * 设置当前页码 + * @param pageNo + */ + public void setPageNo(int pageNo) { + this.pageNo = pageNo; + } + + /** + * 获取页面大小 + * @return + */ + public int getPageSize() { + return pageSize; + } + + /** + * 设置页面大小(最大500) + * @param pageSize + */ + public void setPageSize(int pageSize) { + this.pageSize = pageSize <= 0 ? 10 : pageSize;// > 500 ? 500 : pageSize; + } + + /** + * 首页索引 + * @return + */ + @JsonIgnore + public int getFirst() { + return first; + } + + /** + * 尾页索引 + * @return + */ + @JsonIgnore + public int getLast() { + return last; + } + + /** + * 获取页面总数 + * @return getLast(); + */ + @JsonIgnore + public int getTotalPage() { + return getLast(); + } + + /** + * 是否为第一页 + * @return + */ + @JsonIgnore + public boolean isFirstPage() { + return firstPage; + } + + /** + * 是否为最后一页 + * @return + */ + @JsonIgnore + public boolean isLastPage() { + return lastPage; + } + + /** + * 上一页索引值 + * @return + */ + @JsonIgnore + public int getPrev() { + if (isFirstPage()) { + return pageNo; + } else { + return pageNo - 1; + } + } + + /** + * 下一页索引值 + * @return + */ + @JsonIgnore + public int getNext() { + if (isLastPage()) { + return pageNo; + } else { + return pageNo + 1; + } + } + + /** + * 获取本页数据对象列表 + * @return List + */ + public List getList() { + return list; + } + + /** + * 设置本页数据对象列表 + * @param list + */ + public Page setList(List list) { + this.list = list; + initialize(); + return this; + } + + /** + * 获取查询排序字符串 + * @return + */ + @JsonIgnore + public String getOrderBy() { + // SQL过滤,防止注入 + String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|" + + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)"; + Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE); + if (sqlPattern.matcher(orderBy).find()) { + return ""; + } + return orderBy; + } + + /** + * 设置查询排序,标准查询有效, 实例: updatedate desc, name asc + */ + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; + } + + /** + * 获取点击页码调用的js函数名称 + * function ${page.funcName}(pageNo){location="${ctx}/list-${category.id}${urlSuffix}?pageNo="+i;} + * @return + */ + @JsonIgnore + public String getFuncName() { + return funcName; + } + + /** + * 设置点击页码调用的js函数名称,默认为page,在一页有多个分页对象时使用。 + * @param funcName 默认为page + */ + public void setFuncName(String funcName) { + this.funcName = funcName; + } + + /** + * 获取分页函数的附加参数 + * @return + */ + @JsonIgnore + public String getFuncParam() { + return funcParam; + } + + /** + * 设置分页函数的附加参数 + * @return + */ + public void setFuncParam(String funcParam) { + this.funcParam = funcParam; + } + + /** + * 设置提示消息,显示在“共n条”之后 + * @param message + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * 分页是否有效 + * @return this.pageSize==-1 + */ + @JsonIgnore + public boolean isDisabled() { + return this.pageSize==-1; + } + + /** + * 是否进行总数统计 + * @return this.count==-1 + */ + @JsonIgnore + public boolean isNotCount() { + return this.count==-1; + } + + /** + * 获取 Hibernate FirstResult + */ + public int getFirstResult(){ + int firstResult = (getPageNo() - 1) * getPageSize(); + if (firstResult >= getCount()) { + firstResult = 0; + } + return firstResult; + } + /** + * 获取 Hibernate MaxResults + */ + public int getMaxResults(){ + return getPageSize(); + } + +// /** +// * 获取 Spring data JPA 分页对象 +// */ +// public Pageable getSpringPage(){ +// List orders = new ArrayList(); +// if (orderBy!=null){ +// for (String order : StringUtils.split(orderBy, ",")){ +// String[] o = StringUtils.split(order, " "); +// if (o.length==1){ +// orders.add(new Order(Direction.ASC, o[0])); +// }else if (o.length==2){ +// if ("DESC".equals(o[1].toUpperCase())){ +// orders.add(new Order(Direction.DESC, o[0])); +// }else{ +// orders.add(new Order(Direction.ASC, o[0])); +// } +// } +// } +// } +// return new PageRequest(this.pageNo - 1, this.pageSize, new Sort(orders)); +// } +// +// /** +// * 设置 Spring data JPA 分页对象,转换为本系统分页对象 +// */ +// public void setSpringPage(org.springframework.data.domain.Page page){ +// this.pageNo = page.getNumber(); +// this.pageSize = page.getSize(); +// this.count = page.getTotalElements(); +// this.list = page.getContent(); +// } + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeDao.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeDao.java new file mode 100644 index 0000000000000000000000000000000000000000..497101f63a41ecdbcfd8c175ec7ebd00e604a2e4 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeDao.java @@ -0,0 +1,30 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import java.util.List; + +/** + * DAO支持类实现 + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + * @param + */ +public interface TreeDao> extends InterfaceBaseDao { + + /** + * 找到所有子节点 + * @param entity + * @return + */ + List findByParentIdsLike(T entity); + + /** + * 更新所有父节点字段 + * @param entity + * @return + */ + int updateParentIds(T entity); + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeEntity.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..c06042c1f106d2fb899cef57cb5d2031b60cfdbf --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/TreeEntity.java @@ -0,0 +1,85 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence; + +import javax.validation.constraints.NotNull; + +import org.hibernate.validator.constraints.Length; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.jeespring.common.utils.Reflections; +import com.jeespring.common.utils.StringUtils; + +/** + * 数据Entity类 + * * * * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +public abstract class TreeEntity extends AbstractBaseEntity { + + private static final long serialVersionUID = 1L; + + protected T parent; // 父级编号 + protected String parentIds; // 所有父级编号 + protected String name; // 机构名称 + protected Integer sort; // 排序 + + public TreeEntity() { + super(); + this.sort = 30; + } + + public TreeEntity(String id) { + super(id); + } + + /** + * 父对象,只能通过子类实现,父类实现mybatis无法读取 + * @return + */ + @JsonBackReference + @NotNull + public abstract T getParent(); + + /** + * 父对象,只能通过子类实现,父类实现mybatis无法读取 + * @return + */ + public abstract void setParent(T parent); + + @Length(min=1, max=2000) + public String getParentIds() { + return parentIds; + } + + public void setParentIds(String parentIds) { + this.parentIds = parentIds; + } + + @Length(min=1, max=100) + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getSort() { + return sort; + } + + public void setSort(Integer sort) { + this.sort = sort; + } + + public String getParentId() { + String id = null; + if (parent != null){ + id = (String) Reflections.getFieldValue(parent, "id"); + } + return StringUtils.isNotBlank(id) ? id : "0"; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/annotation/MyBatisDao.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/annotation/MyBatisDao.java new file mode 100644 index 0000000000000000000000000000000000000000..23bab3e3d3a13d31c644939c0a490ca4197b29d0 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/annotation/MyBatisDao.java @@ -0,0 +1,32 @@ +/** + * Copyright © 2012-2016 JeeSpring All rights reserved. + */ +package com.jeespring.common.persistence.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.stereotype.Component; + +/** + * 标识MyBatis的DAO,方便{@link org.mybatis.spring.mapper.MapperScannerConfigurer}的扫描。 + * @author 黄炳桂 516821420@qq.com + * @version 2013-8-28 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@Component +public @interface MyBatisDao { + + /** + * The value may indicate a suggestion for a logical component name, + * to be turned into a Spring bean in case of an autodetected component. + * @return the suggested component name, if any + */ + String value() default ""; + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DB2Dialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DB2Dialect.java new file mode 100644 index 0000000000000000000000000000000000000000..34806bfc1be8e99475e121ba10ae3cdfe82aa592 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DB2Dialect.java @@ -0,0 +1,89 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * DB2的分页数据库方言实现 + * + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class DB2Dialect implements Dialect { + @Override + public boolean supportsLimit() { + return true; + } + + private static String getRowNumber(String sql) { + StringBuilder rownumber = new StringBuilder(50) + .append("rownumber() over("); + + int orderByIndex = sql.toLowerCase().indexOf("order by"); + + if (orderByIndex > 0 && !hasDistinct(sql)) { + rownumber.append(sql.substring(orderByIndex)); + } + + rownumber.append(") as rownumber_,"); + + return rownumber.toString(); + } + + private static boolean hasDistinct(String sql) { + return sql.toLowerCase().contains("select distinct"); + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), Integer.toString(limit)); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { + int startOfSelect = sql.toLowerCase().indexOf("select"); + + StringBuilder pagingSelect = new StringBuilder(sql.length() + 100) + .append(sql.substring(0, startOfSelect)) //add the comment + .append("select * from ( select ") //nest the main query in an outer select + .append(getRowNumber(sql)); //add the rownnumber bit into the outer query select list + + if (hasDistinct(sql)) { + pagingSelect.append(" row_.* from ( ") //add another (inner) nested select + .append(sql.substring(startOfSelect)) //add the main query + .append(" ) as row_"); //close off the inner nested select + } else { + pagingSelect.append(sql.substring(startOfSelect + 6)); //add the main query + } + + pagingSelect.append(" ) as temp_ where rownumber_ "); + + //add the restriction to the outer select + if (offset > 0) { +// int end = offset + limit; + String endString = offsetPlaceholder + "+" + limitPlaceholder; + pagingSelect.append("between ").append(offsetPlaceholder) + .append("+1 and ").append(endString); + } else { + pagingSelect.append("<= ").append(limitPlaceholder); + } + + return pagingSelect.toString(); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DerbyDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DerbyDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..049a27a64d6193fa547eb8ed21b1c2b8d75bec52 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/DerbyDialect.java @@ -0,0 +1,44 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class DerbyDialect implements Dialect { + @Override + public boolean supportsLimit() { + return false; + } + + @Override + public String getLimitString(String sql, int offset, int limit) { +// return getLimitString(sql,offset,Integer.toString(offset),limit,Integer.toString(limit)); + throw new UnsupportedOperationException("paged queries not supported"); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limit 分页每页显示纪录条数 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset,String offsetPlaceholder, int limit, String limitPlaceholder) { + throw new UnsupportedOperationException( "paged queries not supported" ); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/Dialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/Dialect.java new file mode 100644 index 0000000000000000000000000000000000000000..a75e6eca84145e4aa2663701c323a0e21c72adb9 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/Dialect.java @@ -0,0 +1,33 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +/** + * 类似hibernate的Dialect,但只精简出分页部分 + * + * @author poplar.yfyang + * @version 1.0 2011-11-18 下午12:31 + * @since JDK 1.5 + */ +public interface Dialect { + + /** + * 数据库本身是否支持分页当前的分页查询方式 + * 如果数据库不支持的话,则不进行数据库分页 + * + * @return true:支持当前的分页查询方式 + */ + boolean supportsLimit(); + + /** + * 将sql转换为分页SQL,分别调用分页sql + * + * @param sql SQL语句 + * @param offset 开始条数 + * @param limit 每页显示多少纪录条数 + * @return 分页查询的sql + */ + String getLimitString(String sql, int offset, int limit); + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/H2Dialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/H2Dialect.java new file mode 100644 index 0000000000000000000000000000000000000000..c707b74c64fc95c8ac77eddf9f50b889ba3a5aa6 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/H2Dialect.java @@ -0,0 +1,46 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * A dialect compatible with the H2 database. + * + * @author JeeSpring + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class H2Dialect implements Dialect { + + @Override + public boolean supportsLimit() { + return true; + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limit 分页每页显示纪录条数 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + private String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) { + return sql + ((offset > 0) ? " limit " + limitPlaceholder + " offset " + + offsetPlaceholder : " limit " + limitPlaceholder); + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), limit, Integer.toString(limit)); + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/HSQLDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/HSQLDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..ebd06ee2f36e8577f5113adf1a1fe48698909d76 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/HSQLDialect.java @@ -0,0 +1,50 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * Dialect for HSQLDB + * + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class HSQLDialect implements Dialect { + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), + Integer.toString(limit)); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { + boolean hasOffset = offset > 0; + return + new StringBuffer(sql.length() + 10) + .append(sql) + .insert(sql.toLowerCase().indexOf("select") + 6, hasOffset ? " limit " + offsetPlaceholder + " " + limitPlaceholder : " top " + limitPlaceholder) + .toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/MySQLDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/MySQLDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..a6215432757b2def4e14c1f391dfbd5cd4a862b3 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/MySQLDialect.java @@ -0,0 +1,54 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * Mysql方言的实现 + * + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class MySQLDialect implements Dialect { + + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), + Integer.toString(limit)); + } + + @Override + public boolean supportsLimit() { + return true; + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { + StringBuilder stringBuilder = new StringBuilder(sql); + stringBuilder.append(" limit "); + if (offset > 0) { + stringBuilder.append(offsetPlaceholder).append(",").append(limitPlaceholder); + } else { + stringBuilder.append(limitPlaceholder); + } + return stringBuilder.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/OracleDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/OracleDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..2d4f059d06efcc4b40b61bdf311d47fa91e6c145 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/OracleDialect.java @@ -0,0 +1,66 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +/** + * Oracle的方言实现 + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class OracleDialect implements Dialect { + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), Integer.toString(limit)); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, String offsetPlaceholder, String limitPlaceholder) { + sql = sql.trim(); + boolean isForUpdate = false; + if (sql.toLowerCase().endsWith(" for update")) { + sql = sql.substring(0, sql.length() - 11); + isForUpdate = true; + } + StringBuilder pagingSelect = new StringBuilder(sql.length() + 100); + + if (offset > 0) { + pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( "); + } else { + pagingSelect.append("select * from ( "); + } + pagingSelect.append(sql); + if (offset > 0) { + String endString = offsetPlaceholder + "+" + limitPlaceholder; + pagingSelect.append(" ) row_ where rownum <= "+endString+") where rownum_ > ").append(offsetPlaceholder); + } else { + pagingSelect.append(" ) where rownum <= "+limitPlaceholder); + } + + if (isForUpdate) { + pagingSelect.append(" for update"); + } + + return pagingSelect.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/PostgreSQLDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/PostgreSQLDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..17d80976fe0da9e426d3ec46373db9005e92aa82 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/PostgreSQLDialect.java @@ -0,0 +1,49 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * Postgre Sql的方言实现 + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class PostgreSQLDialect implements Dialect { + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, Integer.toString(offset), + Integer.toString(limit)); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, + String offsetPlaceholder, String limitPlaceholder) { + StringBuilder pageSql = new StringBuilder().append(sql); + pageSql = offset <= 0 + ? pageSql.append(" limit ").append(limitPlaceholder) : + pageSql.append(" limit ").append(limitPlaceholder).append(" offset ").append(offsetPlaceholder); + return pageSql.toString(); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServer2005Dialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServer2005Dialect.java new file mode 100644 index 0000000000000000000000000000000000000000..c4278b0b26d9a9de79700445eced2e39eee60281 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServer2005Dialect.java @@ -0,0 +1,95 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import org.apache.commons.lang3.StringUtils; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * Sql 2005的方言实现 + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class SQLServer2005Dialect implements Dialect { + + @Override + public boolean supportsLimit() { + return true; + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimitString(sql, offset, + limit, Integer.toString(limit)); + } + + /** + * Add a LIMIT clause to the given SQL SELECT + * + * The LIMIT SQL will look like: + * + * WITH query AS + * (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name) + * SELECT * + * FROM query + * WHERE __row_number__ BETWEEN :offset and :lastRows + * ORDER BY __row_number__ + * + * @param querySqlString The SQL statement to base the limit query off of. + * @param offset Offset of the first row to be returned by the query (zero-based) + * @param limit Maximum number of rows to be returned by the query + * @param limitPlaceholder limitPlaceholder + * @return A new SQL statement with the LIMIT clause applied. + */ + private String getLimitString(String querySqlString, int offset, int limit, String limitPlaceholder) { + StringBuilder pagingBuilder = new StringBuilder(); + String orderby = getOrderByPart(querySqlString); + String distinctStr = ""; + + String loweredString = querySqlString.toLowerCase(); + String sqlPartString = querySqlString; + if (loweredString.trim().startsWith("select")) { + int index = 6; + if (loweredString.startsWith("select distinct")) { + distinctStr = "DISTINCT "; + index = 15; + } + sqlPartString = sqlPartString.substring(index); + } + pagingBuilder.append(sqlPartString); + + // if no ORDER BY is specified use fake ORDER BY field to avoid errors + if (StringUtils.isEmpty(orderby)) { + orderby = "ORDER BY CURRENT_TIMESTAMP"; + } + + StringBuilder result = new StringBuilder(); + result.append("WITH query AS (SELECT ") + .append(distinctStr) + .append("TOP 100 PERCENT ") + .append(" ROW_NUMBER() OVER (") + .append(orderby) + .append(") as __row_number__, ") + .append(pagingBuilder) + .append(") SELECT * FROM query WHERE __row_number__ BETWEEN ") + .append(offset + 1).append(" AND ").append(offset + limit) + .append(" ORDER BY __row_number__"); + + return result.toString(); + } + + static String getOrderByPart(String sql) { + String loweredString = sql.toLowerCase(); + int orderByIndex = loweredString.indexOf("order by"); + if (orderByIndex != -1) { + // if we find a new "order by" then we need to ignore + // the previous one since it was probably used for a subquery + return sql.substring(orderByIndex); + } else { + return ""; + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServerDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServerDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..beceda3ee690abe04e6489e0e08a6eb91be20ba5 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SQLServerDialect.java @@ -0,0 +1,57 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * MSSQLServer 数据库实现分页方言 + * + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class SQLServerDialect implements Dialect { + + @Override + public boolean supportsLimit() { + return true; + } + + static int getAfterSelectInsertPoint(String sql) { + int selectIndex = sql.toLowerCase().indexOf("select"); + final int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct"); + return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6); + } + + @Override + public String getLimitString(String sql, int offset, int limit) { + return getLimit(sql, offset, limit); + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param limit 分页每页显示纪录条数 + * @return 包含占位符的分页sql + */ + public String getLimit(String sql, int offset, int limit) { + if (offset > 0) { + throw new UnsupportedOperationException("sql server has no offset"); + } + return new StringBuffer(sql.length() + 8) + .append(sql) + .insert(getAfterSelectInsertPoint(sql), " top " + limit) + .toString(); + } + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SybaseDialect.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SybaseDialect.java new file mode 100644 index 0000000000000000000000000000000000000000..3f06c8128719e5acb2687b63d99267454160dfda --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/dialect/SybaseDialect.java @@ -0,0 +1,48 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.dialect; + +import com.jeespring.common.persistence.dialect.Dialect; + +/** + * Sybase数据库分页方言实现。 + * 还未实现 + * + * @author poplar.yfyang + * @version 1.0 2010-10-10 下午12:31 + * @since JDK 1.5 + */ +public class SybaseDialect implements Dialect { + + @Override + public boolean supportsLimit() { + return false; + } + + + @Override + public String getLimitString(String sql, int offset, int limit) { + return null; + } + + /** + * 将sql变成分页sql语句,提供将offset及limit使用占位符号(placeholder)替换. + * + * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + * + * + * @param sql 实际SQL语句 + * @param offset 分页开始纪录条数 + * @param offsetPlaceholder 分页开始纪录条数-占位符号 + * @param limit 分页每页显示纪录条数 + * @param limitPlaceholder 分页纪录条数占位符号 + * @return 包含占位符的分页sql + */ + public String getLimitString(String sql, int offset, String offsetPlaceholder, int limit, String limitPlaceholder) { + throw new UnsupportedOperationException("paged queries not supported"); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/BaseInterceptor.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/BaseInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..1cd3e9f5efa343531d79585c6c4243215ebe347b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/BaseInterceptor.java @@ -0,0 +1,96 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.interceptor; + +import com.jeespring.common.config.Global; +import com.jeespring.common.persistence.Page; +import com.jeespring.common.persistence.dialect.*; +import com.jeespring.common.utils.Reflections; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.plugin.Interceptor; + +import java.io.Serializable; +import java.util.Properties; + +/** + * Mybatis分页拦截器基类 + * + * @author poplar.yfyang / HuangBingGui + * @version 2013-8-28 + */ +public abstract class BaseInterceptor implements Interceptor, Serializable { + + private static final long serialVersionUID = 1L; + + protected static final String PAGE = "page"; + + protected static final String DELEGATE = "delegate"; + + protected static final String MAPPED_STATEMENT = "mappedStatement"; + + protected Log log = LogFactory.getLog(this.getClass()); + + protected Dialect DIALECT; + + + /** + * 对参数进行转换和检查 + * + * @param parameterObject 参数对象 + * @param page 分页对象 + * @return 分页对象 + * @throws NoSuchFieldException 无法找到参数 + */ + @SuppressWarnings("unchecked") + protected static Page convertParameter(Object parameterObject, Page page) { + try { + if (parameterObject instanceof Page) { + return (Page) parameterObject; + } else { + return (Page) Reflections.getFieldValue(parameterObject, PAGE); + } + } catch (Exception e) { + return null; + } + } + + /** + * 设置属性,支持自定义方言类和制定数据库的方式 + * dialectClass,自定义方言类。可以不配置这项 + * dbms 数据库类型,插件支持的数据库 + * sqlPattern 需要拦截的SQL ID + * + * @param p 属性 + */ + protected void initProperties(Properties p) { + Dialect dialect = null; + String dbType = Global.getJdbcType(); + if ("db2".equals(dbType)) { + dialect = new DB2Dialect(); + } else if ("derby".equals(dbType)) { + dialect = new DerbyDialect(); + } else if ("h2".equals(dbType)) { + dialect = new H2Dialect(); + } else if ("hsql".equals(dbType)) { + dialect = new HSQLDialect(); + } else if ("mysql".equals(dbType)) { + dialect = new MySQLDialect(); + } else if ("oracle".equals(dbType)) { + dialect = new OracleDialect(); + } else if ("postgre".equals(dbType)) { + dialect = new PostgreSQLDialect(); + } else if ("mssql".equals(dbType) || "sqlserver".equals(dbType)) { + dialect = new SQLServer2005Dialect(); + } else if ("sybase".equals(dbType)) { + dialect = new SybaseDialect(); + } + if (dialect == null) { + log.error("user the mysql dialect"); + dialect = new MySQLDialect(); + } + DIALECT = dialect; + + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PaginationInterceptor.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PaginationInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..cecc6db686db3a46bb20327c1c621a527296c63e --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PaginationInterceptor.java @@ -0,0 +1,129 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.interceptor; + +import java.util.Properties; + +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Plugin; +import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; + +import com.jeespring.common.persistence.Page; +import com.jeespring.common.utils.Reflections; +import com.jeespring.common.utils.StringUtils; + +/** + * 数据库分页插件,只拦截查询语句. + * @author poplar.yfyang / HuangBingGui + * @version 2013-8-28 + */ +@Intercepts({@Signature(type = Executor.class, method = "query", + args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) +public class PaginationInterceptor extends BaseInterceptor { + + private static final long serialVersionUID = 1L; + + @Override + public Object intercept(Invocation invocation) throws Throwable { + + final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; + +// //拦截需要分页的SQL +//// if (mappedStatement.getId().matches(_SQL_PATTERN)) { +// if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), _SQL_PATTERN) != -1) { + Object parameter = invocation.getArgs()[1]; + BoundSql boundSql = mappedStatement.getBoundSql(parameter); + Object parameterObject = boundSql.getParameterObject(); + + //获取分页参数对象 + Page page = null; + if (parameterObject != null) { + page = convertParameter(parameterObject, page); + } + + //如果设置了分页对象,则进行分页 + if (page != null && page.getPageSize() != -1) { + + if (StringUtils.isBlank(boundSql.getSql())){ + return null; + } + String originalSql = boundSql.getSql().trim(); + + //得到总记录数 + page.setCount(SQLHelper.getCount(originalSql, null, mappedStatement, parameterObject, boundSql, log)); + + //分页查询 本地化对象 修改数据库注意修改实现 + String pageSql = SQLHelper.generatePageSql(originalSql, page, DIALECT); +// if (log.isDebugEnabled()) { +// log.debug("PAGE SQL:" + StringUtils.replace(pageSql, "\n", "")); +// } + invocation.getArgs()[2] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT); + BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), pageSql, boundSql.getParameterMappings(), boundSql.getParameterObject()); + //解决MyBatis 分页foreach 参数失效 start + if (Reflections.getFieldValue(boundSql, "metaParameters") != null) { + MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters"); + Reflections.setFieldValue(newBoundSql, "metaParameters", mo); + } + //解决MyBatis 分页foreach 参数失效 end + MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql)); + + invocation.getArgs()[0] = newMs; + } +// } + return invocation.proceed(); + } + + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + @Override + public void setProperties(Properties properties) { + super.initProperties(properties); + } + + private MappedStatement copyFromMappedStatement(MappedStatement ms, + SqlSource newSqlSource) { + MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), + ms.getId(), newSqlSource, ms.getSqlCommandType()); + builder.resource(ms.getResource()); + builder.fetchSize(ms.getFetchSize()); + builder.statementType(ms.getStatementType()); + builder.keyGenerator(ms.getKeyGenerator()); + if (ms.getKeyProperties() != null) { + for (String keyProperty : ms.getKeyProperties()) { + builder.keyProperty(keyProperty); + } + } + builder.timeout(ms.getTimeout()); + builder.parameterMap(ms.getParameterMap()); + builder.resultMaps(ms.getResultMaps()); + builder.cache(ms.getCache()); + builder.useCache(ms.isUseCache()); + return builder.build(); + } + + public static class BoundSqlSqlSource implements SqlSource { + BoundSql boundSql; + + public BoundSqlSqlSource(BoundSql boundSql) { + this.boundSql = boundSql; + } + + @Override + public BoundSql getBoundSql(Object parameterObject) { + return boundSql; + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PreparePaginationInterceptor.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PreparePaginationInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..a509bd07a90020607218d5e0738f2af6e2544caa --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/PreparePaginationInterceptor.java @@ -0,0 +1,89 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.interceptor; + +import java.sql.Connection; +import java.util.Properties; + +import org.apache.ibatis.executor.statement.BaseStatementHandler; +import org.apache.ibatis.executor.statement.RoutingStatementHandler; +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Plugin; +import org.apache.ibatis.plugin.Signature; + +import com.jeespring.common.persistence.Page; +import com.jeespring.common.utils.Reflections; + +/** + * Mybatis数据库分页插件,拦截StatementHandler的prepare方法 + * @author poplar.yfyang / HuangBingGui + * @version 2013-8-28 + */ +@Intercepts({ + @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}) +}) +public class PreparePaginationInterceptor extends BaseInterceptor { + + private static final long serialVersionUID = 1L; + + public PreparePaginationInterceptor() { + super(); + } + + @Override + public Object intercept(Invocation ivk) throws Throwable { + if (ivk.getTarget().getClass().isAssignableFrom(RoutingStatementHandler.class)) { + final RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk.getTarget(); + final BaseStatementHandler delegate = (BaseStatementHandler) Reflections.getFieldValue(statementHandler, DELEGATE); + final MappedStatement mappedStatement = (MappedStatement) Reflections.getFieldValue(delegate, MAPPED_STATEMENT); + +// //拦截需要分页的SQL +//// if (mappedStatement.getId().matches(_SQL_PATTERN)) { +// if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), _SQL_PATTERN) != -1) { + BoundSql boundSql = delegate.getBoundSql(); + //分页SQL中parameterType属性对应的实体参数,即Mapper接口中执行分页方法的参数,该参数不得为空 + Object parameterObject = boundSql.getParameterObject(); + if (parameterObject == null) { + log.error("参数未实例化"); + throw new NullPointerException("parameterObject尚未实例化!"); + } else { + final Connection connection = (Connection) ivk.getArgs()[0]; + final String sql = boundSql.getSql(); + //记录统计 + final int count = SQLHelper.getCount(sql, connection, mappedStatement, parameterObject, boundSql, log); + Page page = null; + page = convertParameter(parameterObject, page); + page.setCount(count); + String pagingSql = SQLHelper.generatePageSql(sql, page, DIALECT); + if (log.isDebugEnabled()) { + log.debug("PAGE SQL:" + pagingSql); + } + //将分页sql语句反射回BoundSql. + Reflections.setFieldValue(boundSql, "sql", pagingSql); + } + + if (boundSql.getSql() == null || "".equals(boundSql.getSql())){ + return null; + } + + } +// } + return ivk.proceed(); + } + + + @Override + public Object plugin(Object o) { + return Plugin.wrap(o, this); + } + + @Override + public void setProperties(Properties properties) { + initProperties(properties); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/SQLHelper.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/SQLHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..a6e12ab25d1816841213b09a29c84111ff490d44 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/interceptor/SQLHelper.java @@ -0,0 +1,198 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.interceptor; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.ibatis.executor.ErrorContext; +import org.apache.ibatis.executor.ExecutorException; +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.ParameterMapping; +import org.apache.ibatis.mapping.ParameterMode; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.property.PropertyTokenizer; +import org.apache.ibatis.scripting.xmltags.ForEachSqlNode; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.type.TypeHandler; +import org.apache.ibatis.type.TypeHandlerRegistry; + +import com.jeespring.common.config.Global; +import com.jeespring.common.persistence.Page; +import com.jeespring.common.persistence.dialect.Dialect; +import com.jeespring.common.utils.Reflections; +import com.jeespring.common.utils.StringUtils; + +/** + * SQL工具类 + * + * @author poplar.yfyang / HuangBingGui + * @version 2013-8-28 + */ +public class SQLHelper { + + /** + * 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter.DefaultParameterHandler + * + * @param ps 表示预编译的 SQL 语句的对象。 + * @param mappedStatement MappedStatement + * @param boundSql SQL + * @param parameterObject 参数对象 + * @throws SQLException 数据库异常 + */ + @SuppressWarnings("unchecked") + public static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException { + ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); + List parameterMappings = boundSql.getParameterMappings(); + if (parameterMappings != null) { + Configuration configuration = mappedStatement.getConfiguration(); + TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); + MetaObject metaObject = parameterObject == null ? null : + configuration.newMetaObject(parameterObject); + for (int i = 0; i < parameterMappings.size(); i++) { + ParameterMapping parameterMapping = parameterMappings.get(i); + if (parameterMapping.getMode() != ParameterMode.OUT) { + Object value; + String propertyName = parameterMapping.getProperty(); + PropertyTokenizer prop = new PropertyTokenizer(propertyName); + if (parameterObject == null) { + value = null; + } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { + value = parameterObject; + } else if (boundSql.hasAdditionalParameter(propertyName)) { + value = boundSql.getAdditionalParameter(propertyName); + } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { + value = boundSql.getAdditionalParameter(prop.getName()); + if (value != null) { + value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length())); + } + } else { + value = metaObject == null ? null : metaObject.getValue(propertyName); + } + @SuppressWarnings("rawtypes") + TypeHandler typeHandler = parameterMapping.getTypeHandler(); + if (typeHandler == null) { + throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId()); + } + typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType()); + } + } + } + } + + + /** + * 查询总纪录数 + * + * @param sql SQL语句 + * @param connection 数据库连接 + * @param mappedStatement mapped + * @param parameterObject 参数 + * @param boundSql boundSql + * @return 总记录数 + * @throws SQLException sql查询错误 + */ + public static int getCount(final String sql, final Connection connection, + final MappedStatement mappedStatement, final Object parameterObject, + final BoundSql boundSql, Log log) throws SQLException { + String dbName = Global.getJdbcType(); + final String countSql; + if ("oracle".equals(dbName)) { + countSql = "select count(1) from (" + sql + ") tmp_count"; + } else { + countSql = "select count(1) from (" + removeOrders(sql) + ") tmp_count"; + } + Connection conn = connection; + PreparedStatement ps = null; + ResultSet rs = null; + try { + if (log.isDebugEnabled()) { + log.debug("COUNT SQL: " + StringUtils.replaceEach(countSql, new String[]{"\n", "\t"}, new String[]{" ", " "})); + } + if (conn == null) { + conn = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection(); + } + ps = conn.prepareStatement(countSql); + BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, + boundSql.getParameterMappings(), parameterObject); + //解决MyBatis 分页foreach 参数失效 start + if (Reflections.getFieldValue(boundSql, "metaParameters") != null) { + MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters"); + Reflections.setFieldValue(countBS, "metaParameters", mo); + } + //解决MyBatis 分页foreach 参数失效 end + SQLHelper.setParameters(ps, mappedStatement, countBS, parameterObject); + rs = ps.executeQuery(); + int count = 0; + if (rs.next()) { + count = rs.getInt(1); + } + return count; + } finally { + if (rs != null) { + rs.close(); + } + if (ps != null) { + ps.close(); + } + if (conn != null) { + conn.close(); + } + } + } + + + /** + * 根据数据库方言,生成特定的分页sql + * + * @param sql Mapper中的Sql语句 + * @param page 分页对象 + * @param dialect 方言类型 + * @return 分页SQL + */ + public static String generatePageSql(String sql, Page page, Dialect dialect) { + if (dialect.supportsLimit()) { + return dialect.getLimitString(sql, page.getFirstResult(), page.getMaxResults()); + } else { + return sql; + } + } + + /** + * 去除qlString的select子句。 + * + * @param qlString + * @return + */ + @SuppressWarnings("unused") + private static String removeSelect(String qlString) { + int beginPos = qlString.toLowerCase().indexOf("from"); + return qlString.substring(beginPos); + } + + /** + * 去除hql的orderBy子句。 + * + * @param qlString + * @return + */ + private static String removeOrders(String qlString) { + Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(qlString); + StringBuffer sb = new StringBuffer(); + while (m.find()) { + m.appendReplacement(sb, ""); + } + m.appendTail(sb); + return sb.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PageConfiguration.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PageConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..39041d0261c010f38775fcf78ef82434d54ea6c0 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PageConfiguration.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.proxy; + +import org.apache.ibatis.binding.MapperRegistry; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSession; + +/** + * + * 自定义Mybatis的配置,扩展. + * + * + * @author poplar.yfyang + * @version 1.0 2012-05-13 上午10:06 + * @since JDK 1.5 + */ +public class PageConfiguration extends Configuration { + + protected MapperRegistry mapperRegistry = new PaginationMapperRegistry(this); + + @Override + public void addMapper(Class type) { + mapperRegistry.addMapper(type); + } + + @Override + public T getMapper(Class type, SqlSession sqlSession) { + return mapperRegistry.getMapper(type, sqlSession); + } + + @Override + public boolean hasMapper(Class> type) { + return mapperRegistry.hasMapper(type); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperMethod.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..8ec78bdc999942b983ecff80bb008df0c7bd9796 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperMethod.java @@ -0,0 +1,191 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.proxy; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.binding.BindingException; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.session.SqlSession; + +import com.jeespring.common.persistence.Page; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * 执行代理类,扩展Mybatis的方式来让其Mapper接口来支持. + * + * + * @author poplar.yfyang + * @version 1.0 2012-05-13 上午10:09 + * @since JDK 1.5 + */ +public class PaginationMapperMethod { + + private final SqlSession sqlSession; + private final Configuration config; + + private SqlCommandType type; + private String commandName; + private String commandCountName; + + private final Class> declaringInterface; + private final Method method; + + private Integer rowBoundsIndex; + private Integer paginationIndex; + + private final List paramNames; + private final List paramPositions; + + private boolean hasNamedParameters; + + public PaginationMapperMethod(Class> declaringInterface, Method method, + SqlSession sqlSession) { + paramNames = new ArrayList(); + paramPositions = new ArrayList(); + this.sqlSession = sqlSession; + this.method = method; + this.config = sqlSession.getConfiguration(); + this.declaringInterface = declaringInterface; + this.hasNamedParameters = false; + setupFields(); + setupMethodSignature(); + setupCommandType(); + validateStatement(); + } + + /** + * 代理执行方法。 + * + * @param args 参数信息 + * @return 执行结果 + */ + @SuppressWarnings("unchecked") + public Object execute(Object[] args) { + final Object param = getParam(args); + Page page; + RowBounds rowBounds; + if (paginationIndex != null) { + page = (Page) args[paginationIndex]; + rowBounds = new RowBounds(page.getFirstResult(), page.getMaxResults()); + } else if (rowBoundsIndex != null) { + rowBounds = (RowBounds) args[rowBoundsIndex]; + page = new Page(); + } else { + throw new BindingException("Invalid bound statement (not found rowBounds or pagination in paramenters)"); + } + page.setCount(executeForCount(param)); + page.setList(executeForList(param, rowBounds)); + return page; + } + + /** + * 执行总数的方法,调用方法执行计算总数,取得总结果 + * + * @param param 参数信息 + * @return 查询的总记录数 + */ + private long executeForCount(Object param) { + Number result = (Number) sqlSession.selectOne(commandCountName, param); + return result.longValue(); + } + + /** + * 取得分页的执行结果,返回的是纪录信息 + * + * @param param 参数 + * @param rowBounds row + * @return 纪录列表 + */ + private List executeForList(Object param, RowBounds rowBounds) { + return sqlSession.selectList(commandName, param, rowBounds); + } + + /** + * 取得当前执行的参数信息 + * + * @param args 参数 + * @return 参数信息 + */ + private Object getParam(Object[] args) { + final int paramCount = paramPositions.size(); + if (args == null || paramCount == 0) { + return null; + } else if (!hasNamedParameters && paramCount == 1) { + return args[paramPositions.get(0)]; + } else { + Map param = new HashMap(); + for (int i = 0; i < paramCount; i++) { + param.put(paramNames.get(i), args[paramPositions.get(i)]); + } + return param; + } + } + + private void setupMethodSignature() { + final Class>[] argTypes = method.getParameterTypes(); + for (int i = 0; i < argTypes.length; i++) { + if (Page.class.isAssignableFrom(argTypes[i])) { + paginationIndex = i; + } else if (RowBounds.class.isAssignableFrom(argTypes[i])) { + rowBoundsIndex = i; + } else { + String paramName = String.valueOf(paramPositions.size()); + paramName = getParamNameFromAnnotation(i, paramName); + paramNames.add(paramName); + paramPositions.add(i); + } + } + } + + private String getParamNameFromAnnotation(int i, String paramName) { + Object[] annotations = method.getParameterAnnotations()[i]; + for (Object annotation : annotations) { + if (annotation instanceof Param) { + hasNamedParameters = true; + paramName = ((Param) annotation).value(); + } + } + return paramName; + } + + /** + * 设置当前的查询总记录数的ID + */ + private void setupFields() { + commandName = declaringInterface.getName() + "." + method.getName(); + commandCountName = commandName + "Count"; // 命名约定 + } + + /** + * 设置当前的参数的类型信息 + */ + private void setupCommandType() { + MappedStatement ms = config.getMappedStatement(commandName); + type = ms.getSqlCommandType(); + if (type != SqlCommandType.SELECT) { + throw new BindingException("Unsupport execution method for: " + commandName); + } + } + + /** + * 验证Statement + */ + private void validateStatement() { + if (!config.hasStatement(commandName)) { + throw new BindingException("Invalid bound statement (not found): " + commandName); + } + if (!config.hasStatement(commandCountName)) { + throw new BindingException("Invalid bound statement (not found): " + commandCountName); + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperProxy.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperProxy.java new file mode 100644 index 0000000000000000000000000000000000000000..2345b52b2d26de09d863789988d412f0c3bc4a46 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperProxy.java @@ -0,0 +1,104 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.proxy; + +import org.apache.ibatis.binding.BindingException; +import org.apache.ibatis.binding.MapperMethod; +import org.apache.ibatis.session.SqlSession; + +import com.jeespring.common.persistence.Page; +import com.jeespring.common.utils.Reflections; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashSet; +import java.util.Set; + +/** + * + * . + * + * + * @author poplar.yfyang + * @version 1.0 2012-05-13 上午10:07 + * @since JDK 1.5 + */ +public class PaginationMapperProxy implements InvocationHandler { + + + private static final Set OBJECT_METHODS = new HashSet() { + private static final long serialVersionUID = -1782950882770203583L; + { + add("toString"); + add("getClass"); + add("hashCode"); + add("equals"); + add("wait"); + add("notify"); + add("notifyAll"); + } + }; + + private boolean isObjectMethod(Method method) { + return OBJECT_METHODS.contains(method.getName()); + } + + private final SqlSession sqlSession; + + private PaginationMapperProxy(final SqlSession sqlSession) { + this.sqlSession = sqlSession; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + if (isObjectMethod(method)) { + return null; + } + final Class> declaringInterface = findDeclaringInterface(proxy, method); + if (Page.class.isAssignableFrom(method.getReturnType())) { + // 分页处理 + return new PaginationMapperMethod(declaringInterface, method, sqlSession).execute(args); + } + // 原处理方式 + final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession.getConfiguration()); + final Object result = mapperMethod.execute(sqlSession, args); + if (result == null && method.getReturnType().isPrimitive()) { + throw new BindingException( + "Mapper method '" + + method.getName() + + "' (" + + method.getDeclaringClass() + + ") attempted to return null from a method with a primitive return type (" + + method.getReturnType() + ")."); + } + return result; + } + + private Class> findDeclaringInterface(Object proxy, Method method) { + Class> declaringInterface = null; + for (Class> mapperFaces : proxy.getClass().getInterfaces()) { + Method m = Reflections.getAccessibleMethod(mapperFaces, + method.getName(), + method.getParameterTypes()); + if (m != null) { + declaringInterface = mapperFaces; + } + } + if (declaringInterface == null) { + throw new BindingException( + "Could not find interface with the given method " + method); + } + return declaringInterface; + } + + @SuppressWarnings("unchecked") + public static T newMapperProxy(Class mapperInterface, SqlSession sqlSession) { + ClassLoader classLoader = mapperInterface.getClassLoader(); + Class>[] interfaces = new Class[]{mapperInterface}; + PaginationMapperProxy proxy = new PaginationMapperProxy(sqlSession); + return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperRegistry.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..6a41600949e432c20a8a825310ba9e562c4dadbb --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/persistence/proxy/PaginationMapperRegistry.java @@ -0,0 +1,36 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.persistence.proxy; + +import org.apache.ibatis.binding.BindingException; +import org.apache.ibatis.binding.MapperRegistry; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSession; + +/** + * + * . + * + * + * @author poplar.yfyang + * @version 1.0 2012-05-13 上午10:06 + * @since JDK 1.5 + */ +public class PaginationMapperRegistry extends MapperRegistry { + public PaginationMapperRegistry(Configuration config) { + super(config); + } + + @Override + public T getMapper(Class type, SqlSession sqlSession) { + if (!hasMapper(type)) { + throw new BindingException("Type " + type + " is not known to the MapperRegistry."); + } + try { + return PaginationMapperProxy.newMapperProxy(type, sqlSession); + } catch (Exception e) { + throw new BindingException("Error getting mapper instance. Cause: " + e, e); + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/JedisUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/JedisUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..269cf183c3da9bee990efcc866e64df15bfa7b96 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/JedisUtils.java @@ -0,0 +1,847 @@ +/** + * Copyright © 2012-2016 getList(String key) { + List value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + value = jedis.lrange(key, 0, -1); + logger.debug("getList {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getList {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 获取List缓存 + * @param key 键 + * @return 值 + */ + public static List getObjectList(String key) { + List value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + List list = jedis.lrange(getBytesKey(key), 0, -1); + value = Lists.newArrayList(); + for (byte[] bs : list){ + value.add(toObject(bs)); + } + logger.debug("getObjectList {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getObjectList {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 设置List缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static long setList(String key, List value, int cacheSeconds) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + jedis.del(key); + } + result = jedis.rpush(key, (String[])value.toArray()); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setList {} = {}", key, value); + } catch (Exception e) { + logger.warn("setList {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 设置List缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static long setObjectList(String key, List value, int cacheSeconds) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + jedis.del(key); + } + List list = Lists.newArrayList(); + for (Object o : value){ + list.add(toBytes(o)); + } + result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray()); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setObjectList {} = {}", key, value); + } catch (Exception e) { + logger.warn("setObjectList {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向List缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static long listAdd(String key, String... value) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.rpush(key, value); + logger.debug("listAdd {} = {}", key, value); + } catch (Exception e) { + logger.warn("listAdd {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向List缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static long listObjectAdd(String key, Object... value) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + List list = Lists.newArrayList(); + for (Object o : value){ + list.add(toBytes(o)); + } + result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray()); + logger.debug("listObjectAdd {} = {}", key, value); + } catch (Exception e) { + logger.warn("listObjectAdd {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 获取缓存 + * @param key 键 + * @return 值 + */ + public static Set getSet(String key) { + Set value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + value = jedis.smembers(key); + logger.debug("getSet {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getSet {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 获取缓存 + * @param key 键 + * @return 值 + */ + public static Set getObjectSet(String key) { + Set value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + value = Sets.newHashSet(); + Set set = jedis.smembers(getBytesKey(key)); + for (byte[] bs : set){ + value.add(toObject(bs)); + } + logger.debug("getObjectSet {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getObjectSet {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 设置Set缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static long setSet(String key, Set value, int cacheSeconds) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + jedis.del(key); + } + result = jedis.sadd(key, (String[])value.toArray()); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setSet {} = {}", key, value); + } catch (Exception e) { + logger.warn("setSet {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 设置Set缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static long setObjectSet(String key, Set value, int cacheSeconds) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + jedis.del(key); + } + Set set = Sets.newHashSet(); + for (Object o : value){ + set.add(toBytes(o)); + } + result = jedis.sadd(getBytesKey(key), (byte[][])set.toArray()); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setObjectSet {} = {}", key, value); + } catch (Exception e) { + logger.warn("setObjectSet {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向Set缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static long setSetAdd(String key, String... value) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.sadd(key, value); + logger.debug("setSetAdd {} = {}", key, value); + } catch (Exception e) { + logger.warn("setSetAdd {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向Set缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static long setSetObjectAdd(String key, Object... value) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + Set set = Sets.newHashSet(); + for (Object o : value){ + set.add(toBytes(o)); + } + result = jedis.rpush(getBytesKey(key), (byte[][])set.toArray()); + logger.debug("setSetObjectAdd {} = {}", key, value); + } catch (Exception e) { + logger.warn("setSetObjectAdd {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 获取Map缓存 + * @param key 键 + * @return 值 + */ + public static Map getMap(String key) { + Map value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + value = jedis.hgetAll(key); + logger.debug("getMap {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getMap {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 获取Map缓存 + * @param key 键 + * @return 值 + */ + public static Map getObjectMap(String key) { + Map value = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + value = Maps.newHashMap(); + Map map = jedis.hgetAll(getBytesKey(key)); + for (Map.Entry e : map.entrySet()){ + value.put(StringUtils.toString(e.getKey()), toObject(e.getValue())); + } + logger.debug("getObjectMap {} = {}", key, value); + } + } catch (Exception e) { + logger.warn("getObjectMap {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return value; + } + + /** + * 设置Map缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static String setMap(String key, Map value, int cacheSeconds) { + String result = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)) { + jedis.del(key); + } + result = jedis.hmset(key, value); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setMap {} = {}", key, value); + } catch (Exception e) { + logger.warn("setMap {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 设置Map缓存 + * @param key 键 + * @param value 值 + * @param cacheSeconds 超时时间,0为不超时 + * @return + */ + public static String setObjectMap(String key, Map value, int cacheSeconds) { + String result = null; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))) { + jedis.del(key); + } + Map map = Maps.newHashMap(); + for (Map.Entry e : value.entrySet()){ + map.put(getBytesKey(e.getKey()), toBytes(e.getValue())); + } + result = jedis.hmset(getBytesKey(key), (Map)map); + if (cacheSeconds != 0) { + jedis.expire(key, cacheSeconds); + } + logger.debug("setObjectMap {} = {}", key, value); + } catch (Exception e) { + logger.warn("setObjectMap {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向Map缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static String mapPut(String key, Map value) { + String result = null; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.hmset(key, value); + logger.debug("mapPut {} = {}", key, value); + } catch (Exception e) { + logger.warn("mapPut {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 向Map缓存中添加值 + * @param key 键 + * @param value 值 + * @return + */ + public static String mapObjectPut(String key, Map value) { + String result = null; + Jedis jedis = null; + try { + jedis = getResource(); + Map map = Maps.newHashMap(); + for (Map.Entry e : value.entrySet()){ + map.put(getBytesKey(e.getKey()), toBytes(e.getValue())); + } + result = jedis.hmset(getBytesKey(key), (Map)map); + logger.debug("mapObjectPut {} = {}", key, value); + } catch (Exception e) { + logger.warn("mapObjectPut {} = {}", key, value, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 移除Map缓存中的值 + * @param key 键 + * @return + */ + public static long mapRemove(String key, String mapKey) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.hdel(key, mapKey); + logger.debug("mapRemove {} {}", key, mapKey); + } catch (Exception e) { + logger.warn("mapRemove {} {}", key, mapKey, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 移除Map缓存中的值 + * @param key 键 + * @return + */ + public static long mapObjectRemove(String key, String mapKey) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.hdel(getBytesKey(key), getBytesKey(mapKey)); + logger.debug("mapObjectRemove {} {}", key, mapKey); + } catch (Exception e) { + logger.warn("mapObjectRemove {} {}", key, mapKey, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 判断Map缓存中的Key是否存在 + * @param key 键 + * @return + */ + public static boolean mapExists(String key, String mapKey) { + boolean result = false; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.hexists(key, mapKey); + logger.debug("mapExists {} {}", key, mapKey); + } catch (Exception e) { + logger.warn("mapExists {} {}", key, mapKey, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 判断Map缓存中的Key是否存在 + * @param key 键 + * @return + */ + public static boolean mapObjectExists(String key, String mapKey) { + boolean result = false; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.hexists(getBytesKey(key), getBytesKey(mapKey)); + logger.debug("mapObjectExists {} {}", key, mapKey); + } catch (Exception e) { + logger.warn("mapObjectExists {} {}", key, mapKey, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 删除缓存 + * @param key 键 + * @return + */ + public static long del(String key) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(key)){ + result = jedis.del(key); + logger.debug("del {}", key); + }else{ + logger.debug("del {} not exists", key); + } + } catch (Exception e) { + logger.warn("del {}", key, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 删除缓存 + * @param key 键 + * @return + */ + public static long delObject(String key) { + long result = 0; + Jedis jedis = null; + try { + jedis = getResource(); + if (jedis.exists(getBytesKey(key))){ + result = jedis.del(getBytesKey(key)); + logger.debug("delObject {}", key); + }else{ + logger.debug("delObject {} not exists", key); + } + } catch (Exception e) { + logger.warn("delObject {}", key, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 缓存是否存在 + * @param key 键 + * @return + */ + public static boolean exists(String key) { + boolean result = false; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.exists(key); + logger.debug("exists {}", key); + } catch (Exception e) { + logger.warn("exists {}", key, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 缓存是否存在 + * @param key 键 + * @return + */ + public static boolean existsObject(String key) { + boolean result = false; + Jedis jedis = null; + try { + jedis = getResource(); + result = jedis.exists(getBytesKey(key)); + logger.debug("existsObject {}", key); + } catch (Exception e) { + logger.warn("existsObject {}", key, e); + } finally { + returnResource(jedis); + } + return result; + } + + /** + * 获取资源 + * @return + * @throws JedisException + */ + public static Jedis getResource() throws JedisException { + Jedis jedis = null; + try { + jedis = jedisPool.getResource(); +// logger.debug("getResource.", jedis); + } catch (JedisException e) { + logger.warn("getResource.", e); + returnBrokenResource(jedis); + throw e; + } + return jedis; + } + + /** + * 归还资源 + * @param jedis + */ + public static void returnBrokenResource(Jedis jedis) { + if (jedis != null) { + jedisPool.returnBrokenResource(jedis); + } + } + + /** + * 释放资源 + * @param jedis + */ + public static void returnResource(Jedis jedis) { + if (jedis != null) { + jedisPool.returnResource(jedis); + } + } + + /** + * 获取byte[]类型Key + * @return + */ + public static byte[] getBytesKey(Object object){ + if(object instanceof String){ + return StringUtils.getBytes((String)object); + }else{ + return ObjectUtils.serialize(object); + } + } + + /** + * 获取byte[]类型Key + * @param key + * @return + */ + public static Object getObjectKey(byte[] key){ + try{ + return StringUtils.toString(key); + }catch(UnsupportedOperationException uoe){ + try{ + return JedisUtils.toObject(key); + }catch(UnsupportedOperationException uoe2){ + uoe2.printStackTrace(); + } + } + return null; + } + + /** + * Object转换byte[]类型 + * @return + */ + public static byte[] toBytes(Object object){ + return ObjectUtils.serialize(object); + } + + /** + * byte[]型转换Object + * @return + */ + public static Object toObject(byte[] bytes){ + return ObjectUtils.unserialize(bytes); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisConfig.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..2d939171752fd38b6dfae1ee7d6da749427a2efe --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisConfig.java @@ -0,0 +1,41 @@ +package com.jeespring.common.redis; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import redis.clients.jedis.JedisPoolConfig; + +@Configuration +@EnableAutoConfiguration +public class RedisConfig { + + //private static Logger logger = Logger.getLogger(RedisConfig.class); + + @Bean + @ConfigurationProperties(prefix="spring.redis") + public JedisPoolConfig getRedisConfig(){ + JedisPoolConfig config = new JedisPoolConfig(); + return config; + } + + @Bean + @ConfigurationProperties(prefix="spring.redis") + public JedisConnectionFactory getConnectionFactory(){ + JedisConnectionFactory factory = new JedisConnectionFactory(); + JedisPoolConfig config = getRedisConfig(); + factory.setPoolConfig(config); + //logger.info("JedisConnectionFactory bean init success."); + return factory; + } + + + @Bean + public RedisTemplate, ?> getRedisTemplate(){ + RedisTemplate,?> template = new StringRedisTemplate(getConnectionFactory()); + return template; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisRestController.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisRestController.java new file mode 100644 index 0000000000000000000000000000000000000000..581ed2c43338321b198cbfd1f69eed578810d031 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisRestController.java @@ -0,0 +1,231 @@ +package com.jeespring.common.redis; + +import com.jeespring.common.web.Result; +import com.jeespring.common.web.ResultFactory; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.Serializable; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +@RestController +@RequestMapping("/rest/redis") +@Api(value="Redis云数据缓存接口", description="Redis云数据缓存接口") +public class RedisRestController { + + @Autowired + private RedisUtils redisUtils; + + @RequestMapping(value = "/test",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis Test信息(Content-Type为text/html)", notes="Redis Test(Content-Type为text/html)") + public String test(){ + redisUtils.set("Redis Test", "Redis Test"); + String string= redisUtils.get("Redis Test").toString(); + return string; + } + + /** + * 批量删除对应的value + * + * @param keys + */ + @RequestMapping(value ="/removeList",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis remove接口(Content-Type为text/html)", notes="Redis remove接口(Content-Type为text/html)") + public Result removeList(@RequestParam(required=false) String keys) { + String [] keysList=keys.split(","); + for(String key:keysList) { + redisUtils.remove(key); + } + return ResultFactory.getSuccessResult("移除成功!"); + } + + /** + * 批量删除key + * + * @param pattern + */ + @RequestMapping(value ="/removePattern",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis remove pattern接口(Content-Type为text/html)", notes="Redis remove pattern接口接口(Content-Type为text/html)") + public Result removePattern(@RequestParam(required=false) String pattern) { + redisUtils.removePattern(pattern); + return ResultFactory.getSuccessResult("移除成功!"); + } + + @RequestMapping(value ="/removePatternShiroRedis",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis remove pattern Shiro Reids接口(Content-Type为text/html)", notes="Redis remove pattern Shiro Reids接口接口(Content-Type为text/html)") + public Result removePatternShiroReids(@RequestParam(required=false) String pattern) { + redisUtils.removePatternShiroReids(pattern); + return ResultFactory.getSuccessResult("移除成功!"); + } + + /** + * 删除对应的value + * + * @param key + */ + @RequestMapping(value ="/remove",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis remove接口(Content-Type为text/html)", notes="Redis remove接口(Content-Type为text/html)") + public Result remove(@RequestParam(required=false) String key) { + redisUtils.remove(key); + return ResultFactory.getSuccessResult("移除成功!"); + } + + /** + * 判断缓存中是否有对应的value + * + * @param key + * @return + */ + @RequestMapping(value ="/exists",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis exists接口(Content-Type为text/html)", notes="Redis exists接口(Content-Type为text/html)") + public Result exists(@RequestParam(required=false) String key) { + if(redisUtils.exists(key)) { + return ResultFactory.getSuccessResult("存在!"); + } else { + return ResultFactory.getErrorResult("不存在!"); + } + } + + /** + * 读取缓存 + * + * @param key + * @return + */ + @RequestMapping(value ="/get",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get接口(Content-Type为text/html)", notes="Redis get接口(Content-Type为text/html)") + public Result get(@RequestParam(required=false) String key) { + if(redisUtils.exists(key)){ + Result result = ResultFactory.getSuccessResult(); + Object obj=redisUtils.get(key); + if(obj!=null) { + result.setResultObject(obj.toString()); + } + return result; + }else{ + return ResultFactory.getErrorResult("不存在!"); + } + } + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + @RequestMapping(value ="/set",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis set接口(Content-Type为text/html)", notes="Redis set接口(Content-Type为text/html)") + public Result set(@RequestParam(required=false) String key,@RequestParam(required=false) String value) { + if(redisUtils.set(key,value)){ + Result result = ResultFactory.getSuccessResult("添加/更新成功!"); + return result; + }else{ + return ResultFactory.getErrorResult("添加/更新失败!"); + } + } + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + @RequestMapping(value ="/setExpireTime",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis set expireTime接口(Content-Type为text/html)", notes="Redis set expireTime接口接口(Content-Type为text/html)") + public Result set(@RequestParam(required=false) String key,@RequestParam(required=false) String value,@RequestParam(required=false) Long expireTime) { + if(redisUtils.set(key,value,expireTime)){ + Result result = ResultFactory.getSuccessResult("添加/更新成功!"); + return result; + }else{ + return ResultFactory.getErrorResult("添加/更新失败!"); + } + } + + /** + * 获取keys + * + * @param pattern + */ + @RequestMapping(value ="/getKyes",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get kyes接口(Content-Type为text/html)", notes="Redis get kyes接口接口(Content-Type为text/html)") + public Result getKyes(@RequestParam(required=false) String pattern) { + Set keys = redisUtils.getKyes(pattern); + Result result = ResultFactory.getSuccessResult("获取Keys成功!"); + result.setResultObject(keys); + return result; + } + + @RequestMapping(value ="/getKyesAll",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get kyes all接口(Content-Type为text/html)", notes="Redis get kyes all接口(Content-Type为text/html)") + public Result getKyesAll() { + Set keys = redisUtils.getKyesAll(); + Result result = ResultFactory.getSuccessResult("获取Keys成功!"); + result.setResultObject(keys); + return result; + } + + /** + * 获取keys + * + * @param pattern + */ + @RequestMapping(value ="/getCount",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get count接口(Content-Type为text/html)", notes="Redis get count接口(Content-Type为text/html)") + public Result getCount(@RequestParam(required=false) String pattern) { + Result result = ResultFactory.getSuccessResult("获取数量成功!"); + result.setResultObject(redisUtils.getCount()); + return result; + } + + @RequestMapping(value ="/getCountShiro",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get count shiro接口(Content-Type为text/html)", notes="Redis get count shiro接口(Content-Type为text/html)") + public Result getCountShiro(@RequestParam(required=false) String pattern) { + Result result = ResultFactory.getSuccessResult("获取数量成功!"); + result.setResultObject(redisUtils.getCountShiro()); + return result; + } + + /** + * 获取token的有效期(秒) + * @param key + */ + @RequestMapping(value ="/getExpireTime",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get ExpireTime接口(Content-Type为text/html)", notes="Redis get ExpireTime接口接口(Content-Type为text/html)") + public Result getExpireTime(@RequestParam(required=false) String key){ + Result result = ResultFactory.getSuccessResult("获取token的有效期(秒)成功!"); + result.setResultObject(redisUtils.getExpireTime(key)); + return result; + } + + /** + * 获取缓存有效期成功 + */ + @RequestMapping(value ="/getExpire",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get getExpire(Content-Type为text/html)", notes="Redis get getExpire(Content-Type为text/html)") + public Result getExpire(){ + Result result = ResultFactory.getSuccessResult("获取缓存有效期成功!"); + result.setResultObject(RedisUtils.getExpire()); + return result; + } + + /** + * 获取单点登录缓存有效期成功 + */ + @RequestMapping(value ="/getExpireShiro",method ={RequestMethod.POST,RequestMethod.GET}) + @ApiOperation(value="Redis get getExpireShiro(Content-Type为text/html)", notes="Redis get getExpireShiro(Content-Type为text/html)") + public Result getExpireShiro(){ + Result result = ResultFactory.getSuccessResult("获取单点登录缓存有效期成功!"); + result.setResultObject(RedisUtils.getExpireShiro()); + return result; + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..60236a677ecfa6f22339701084c912a9a226937c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/redis/RedisUtils.java @@ -0,0 +1,416 @@ +package com.jeespring.common.redis; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import com.jeespring.common.config.Global; +import com.jeespring.common.security.MD5Tools; +import com.sun.tools.javac.util.Convert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; +import redis.clients.jedis.Jedis; + +/** + * redicache 工具类 + * 在application.yml文件内的Spring-redis的run配置启动,true为启动;false为不启动; + */ +@SuppressWarnings("unchecked") +@Component +public class RedisUtils { + /** + * 日志对象 + */ + private static Logger logger = LoggerFactory.getLogger(RedisUtils.class); + + public static String SHIRO_REDIS="shiro_redis_cache"; + public static String SHIRO_REDIS_OBJECT="org.apache.shiro.subject.SimplePrincipalCollection"; + public static String GET_ID =".get id="; + public static String TOTAL_KEY =".total key="; + public static String FIND_LIST_KEY =".findList key="; + public static String FIND_LIST_FIRST_KEY =".findListFirst key="; + public static String FIND_PAGE_KEY =".findPage key="; + public static String FIND_LIST_KEY_PATTERN =".findList key=*"; + public static String FIND_LIST_FIRST_KEY_PATTERN =".findListFirst key=*"; + public static String FIND_PAGE_KEY_PATTERN =".findPage key=*"; + public static String KEY_PREFIX =Global.getConfig("spring.redis.keyPrefix"); + public static Long expireTime= Long.parseLong(Global.getConfig("spring.redis.expireTime")); + public static Long expireTimeShiro= Long.parseLong(Global.getConfig("spring.redis.expireTimeShiro")); + public static String RUN_MESSAGE="请开启Redis服务,还有Redis密码配置是否有误,而且密码不能为空(为空时Redis服务会连接不上)。"; + @SuppressWarnings("rawtypes") + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private StringRedisTemplate stringRedisTemplate; + + public static String getExpire(){ + if(expireTime!=null) { + return String.valueOf(expireTime / 60) + "分钟"; + } else { + return "0分钟"; + } + } + + public static String getExpireShiro(){ + if(expireTimeShiro!=null) { + return String.valueOf(expireTimeShiro / 60) + "分钟"; + } else { + return "0分钟"; + } + } + + public static String getKey(String className,String keyName,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+keyName+keyId; + } + + public static String getIdKey(String className,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+RedisUtils.GET_ID+keyId; + } + + public static String getTotalKey(String className,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+RedisUtils.TOTAL_KEY+MD5Tools.MD5(keyId).substring(0,20); + } + + public static String getFindListKey(String className,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+RedisUtils.FIND_LIST_KEY+MD5Tools.MD5(keyId).substring(0,20); + } + + public static String getFindListFirstKey(String className,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+RedisUtils.FIND_LIST_FIRST_KEY+MD5Tools.MD5(keyId).substring(0,20); + } + + public static String getFindPageKey(String className,String keyId){ + if(className==null){className="";} + if(keyId==null){keyId="";} + return RedisUtils.KEY_PREFIX+className+RedisUtils.FIND_PAGE_KEY+MD5Tools.MD5(keyId).substring(0,20); + } + + public static String getFindListKeyPattern(String className){ + if(className==null){className="";} + return RedisUtils.KEY_PREFIX+className+FIND_LIST_KEY_PATTERN; + } + + public static String getFinPageKeyPattern(String className){ + if(className==null){className="";} + return RedisUtils.KEY_PREFIX+className+FIND_PAGE_KEY_PATTERN; + } + + /** + * 获取token的有效期(秒) + * @param key + */ + public long getExpireTime(String key){ + long time = redisTemplate.getExpire(key,TimeUnit.SECONDS); + return time; + } + + /** + * 批量删除对应的value + * + * @param keys + */ + public void remove(final String... keys) { + if(!run()) { return; } + try{ + for (String key : keys) { + remove(key); + } + } catch (Exception e) { + logger.error("RedisUtils remove:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + } + + /** + * 批量删除key + * + * @param pattern + */ + public void removePattern(String pattern) { + if(!run()) { return;} + if(!listFlush()){ + return ; + } + try{ + if(pattern==null) { + pattern = ""; + } + Set keys=getKyes(pattern); + if (keys.size() > 0) { + redisTemplate.delete(keys); + } + } catch (Exception e) { + logger.error("RedisUtils removePattern:"+RUN_MESSAGE+e.getMessage(),RUN_MESSAGE+ e.getMessage()); + } + } + + public void removePatternShiroReids(String pattern){ + if(!run()) { return;} + if(!listFlush()){ + return ; + } + try{ + if(pattern==null) { + pattern = ""; + } + Set keys=getKyesShiroReids(pattern); + if (keys.size() > 0){ + stringRedisTemplate.delete(keys); + redisTemplate.delete(keys); + } + } catch (Exception e) { + logger.error("RedisUtils removePattern:"+RUN_MESSAGE+e.getMessage(),RUN_MESSAGE+ e.getMessage()); + } + } + /** + * 获取keys + * + * @param pattern + */ + public Set getKyes(String pattern) { + if(!run()) { return null; } + try{ + if(pattern==null){ pattern=""; } + Set keys=stringRedisTemplate.keys("*"+pattern); + Set keysnew=new HashSet(); + Iterator it = keys.iterator(); + while (it.hasNext()) { + keysnew.add(it.next().substring(7)); + } + return keysnew; + } catch (Exception e) { + logger.error("RedisUtils getKyes:"+RUN_MESSAGE+e.getMessage(), e.getMessage()); + return null; + } + } + + public Set getKyesShiroReids(String pattern) { + if(!run()) { return null; } + try{ + if(pattern==null){ pattern=""; } + Set keys=stringRedisTemplate.keys("*"+pattern); + Set keysnew=new HashSet(); + Iterator it = keys.iterator(); + while (it.hasNext()) { + String tr = it.next(); + if(tr.contains(SHIRO_REDIS)) { + keysnew.add(tr); + } else if(tr.contains(SHIRO_REDIS_OBJECT)) { + keysnew.add(tr.substring(8)); + } + } + return keysnew; + } catch (Exception e) { + logger.error("RedisUtils getKyes:"+RUN_MESSAGE+e.getMessage(), e.getMessage()); + return null; + } + } + + public Set getKyesAll() { + if(!run()) { return null; } + try{ + Set keys=stringRedisTemplate.keys("*"); + Set keysnew=new HashSet(); + Iterator it = keys.iterator(); + while (it.hasNext()) { + keysnew.add(it.next()); + } + return keysnew; + } catch (Exception e) { + logger.error("RedisUtils getKyes:"+RUN_MESSAGE+e.getMessage(), e.getMessage()); + return null; + } + } + + /** + * 获取Count + * + */ + public int getCount() { + if(!run()) { return 0; } + try{ + Set keys=stringRedisTemplate.keys("*"); + return keys.size(); + } catch (Exception e) { + logger.error("RedisUtils getCount:"+RUN_MESSAGE+e.getMessage(), e.getMessage()); + return 0; + } + } + + public int getCountShiro() { + if(!run()) { return 0; } + try{ + Set keys=stringRedisTemplate.keys(SHIRO_REDIS+"*"); + return keys.size(); + } catch (Exception e) { + logger.error("RedisUtils getCount:"+RUN_MESSAGE+e.getMessage(), e.getMessage()); + return 0; + } + } + /** + * 删除对应的value + * + * @param key + */ + public void remove(final String key) { + if(!run()) { return ; } + try{ + if(key.contains(SHIRO_REDIS)) { + stringRedisTemplate.delete(key); + }else{ + redisTemplate.delete(key); + } + } catch (Exception e) { + logger.error("RedisUtils exists:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + } + + /** + * 判断缓存中是否有对应的value + * + * @param key + * @return + */ + public boolean exists(final String key) { + if(!run()) { return false; } + boolean retuslt=false; + try{ + if(key.contains(SHIRO_REDIS)) { + retuslt = stringRedisTemplate.hasKey(key); + } else { + retuslt = redisTemplate.hasKey(key); + } + } catch (Exception e) { + logger.error("RedisUtils exists:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + return retuslt; + } + + /** + * 读取缓存 + * + * @param key + * @return + */ + public Object get(final String key) { + if(!run()) { return null; } + Object result = null; + try{ + if(key.contains(SHIRO_REDIS)){ + ValueOperations operationsString = stringRedisTemplate.opsForValue(); + result = operationsString.get(key); + }else { + ValueOperations operations = redisTemplate.opsForValue(); + result = operations.get(key); + } + return result; + }catch (Exception e){ + logger.error("RedisUtils get:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + return result; + } + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value) { + if(!run()) { return false; } + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); + result = true; + } catch (Exception e) { + logger.error("RedisUtils set:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + return result; + } + + /** + * 写入缓存 + * + * @param key + * @param value + * @return + */ + public boolean set(final String key, Object value, Long expireTime) { + if(!run()) { return false; } + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + redisTemplate.expire(key, expireTime, TimeUnit.SECONDS); + result = true; + } catch (Exception e) { + logger.error("RedisUtils set:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + return result; + } + + public boolean set(final String key, Object value, Long expireTime,TimeUnit unit) { + if(!run()) { return false; } + boolean result = false; + try { + ValueOperations operations = redisTemplate.opsForValue(); + operations.set(key, value); + redisTemplate.expire(key, expireTime, unit); + result = true; + } catch (Exception e) { + logger.error("RedisUtils set:"+RUN_MESSAGE+e.getMessage(), RUN_MESSAGE+e.getMessage()); + } + return result; + } + + private boolean run(){ + if(Global.getConfig("spring.redis.run")=="true") { + return true; + } + return false; + } + + public static boolean isRun(){ + if(Global.getConfig("spring.redis.run")=="true") { + return true; + } + return false; + } + + public static boolean isShireRedis(){ + if(Global.getConfig("spring.redis.run")!="true") { + return false; + } + if(Global.getConfig("shiro.redis")!="true") { + return false; + } + return true; + } + + private boolean listFlush(){ + if(Global.getConfig("spring.redis.listFlush")=="true") { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Cryptos.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Cryptos.java new file mode 100644 index 0000000000000000000000000000000000000000..8e5cf34cdeddb26061bbf8e07ebfa1e9e1d0f8d7 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Cryptos.java @@ -0,0 +1,260 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.security; + +import java.io.UnsupportedEncodingException; +import java.security.GeneralSecurityException; +import java.security.SecureRandom; +import java.util.Arrays; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import com.jeespring.common.utils.Encodes; +import com.jeespring.common.utils.Exceptions; + +/** + * 支持HMAC-SHA1消息签名 及 DES/AES对称加密的工具类. + * + * 支持Hex与Base64两种编码方式. + * + * @author calvin + */ +public class Cryptos { + + private static final String AES = "AES"; + private static final String AES_CBC = "AES/CBC/PKCS5Padding"; + private static final String HMACSHA1 = "HmacSHA1"; + + private static final String DEFAULT_URL_ENCODING = "UTF-8"; + private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401 + private static final int DEFAULT_AES_KEYSIZE = 128; + private static final int DEFAULT_IVSIZE = 16; + + private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125}; + + private static SecureRandom random = new SecureRandom(); + + //-- HMAC-SHA1 funciton --// + /** + * 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节. + * + * @param input 原始输入字符数组 + * @param key HMAC-SHA1密钥 + */ + public static byte[] hmacSha1(byte[] input, byte[] key) { + try { + SecretKey secretKey = new SecretKeySpec(key, HMACSHA1); + Mac mac = Mac.getInstance(HMACSHA1); + mac.init(secretKey); + return mac.doFinal(input); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 校验HMAC-SHA1签名是否正确. + * + * @param expected 已存在的签名 + * @param input 原始输入字符串 + * @param key 密钥 + */ + public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) { + byte[] actual = hmacSha1(input, key); + return Arrays.equals(expected, actual); + } + + /** + * 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节). + * HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节). + */ + public static byte[] generateHmacSha1Key() { + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1); + keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE); + SecretKey secretKey = keyGenerator.generateKey(); + return secretKey.getEncoded(); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + //-- AES funciton --// + + /** + * 使用AES加密原始字符串. + * + * @param input 原始输入字符数组 + */ + public static String aesEncrypt(String input) { + try { + return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY)); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + /** + * 使用AES加密原始字符串. + * + * @param input 原始输入字符数组 + * @param key 符合AES要求的密钥 + */ + public static String aesEncrypt(String input, String key) { + try { + return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key))); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + /** + * 使用AES加密原始字符串. + * + * @param input 原始输入字符数组 + * @param key 符合AES要求的密钥 + */ + public static byte[] aesEncrypt(byte[] input, byte[] key) { + return aes(input, key, Cipher.ENCRYPT_MODE); + } + + /** + * 使用AES加密原始字符串. + * + * @param input 原始输入字符数组 + * @param key 符合AES要求的密钥 + * @param iv 初始向量 + */ + public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) { + return aes(input, key, iv, Cipher.ENCRYPT_MODE); + } + + /** + * 使用AES解密字符串, 返回原始字符串. + * + * @param input Hex编码的加密字符串 + */ + public static String aesDecrypt(String input) { + try { + return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + /** + * 使用AES解密字符串, 返回原始字符串. + * + * @param input Hex编码的加密字符串 + * @param key 符合AES要求的密钥 + */ + public static String aesDecrypt(String input, String key) { + try { + return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + /** + * 使用AES解密字符串, 返回原始字符串. + * + * @param input Hex编码的加密字符串 + * @param key 符合AES要求的密钥 + */ + public static byte[] aesDecrypt(byte[] input, byte[] key) { + return aes(input, key, Cipher.DECRYPT_MODE); + } + + /** + * 使用AES解密字符串, 返回原始字符串. + * + * @param input Hex编码的加密字符串 + * @param key 符合AES要求的密钥 + * @param iv 初始向量 + */ + public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) { + return aes(input, key, iv, Cipher.DECRYPT_MODE); + } + + /** + * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果. + * + * @param input 原始字节数组 + * @param key 符合AES要求的密钥 + * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE + */ + private static byte[] aes(byte[] input, byte[] key, int mode) { + try { + SecretKey secretKey = new SecretKeySpec(key, AES); + Cipher cipher = Cipher.getInstance(AES); + cipher.init(mode, secretKey); + return cipher.doFinal(input); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果. + * + * @param input 原始字节数组 + * @param key 符合AES要求的密钥 + * @param iv 初始向量 + * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE + */ + private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) { + try { + SecretKey secretKey = new SecretKeySpec(key, AES); + IvParameterSpec ivSpec = new IvParameterSpec(iv); + Cipher cipher = Cipher.getInstance(AES_CBC); + cipher.init(mode, secretKey, ivSpec); + return cipher.doFinal(input); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 生成AES密钥,返回字节数组, 默认长度为128位(16字节). + */ + public static String generateAesKeyString() { + return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE)); + } + + /** + * 生成AES密钥,返回字节数组, 默认长度为128位(16字节). + */ + public static byte[] generateAesKey() { + return generateAesKey(DEFAULT_AES_KEYSIZE); + } + + /** + * 生成AES密钥,可选长度为128,192,256位. + */ + public static byte[] generateAesKey(int keysize) { + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance(AES); + keyGenerator.init(keysize); + SecretKey secretKey = keyGenerator.generateKey(); + return secretKey.getEncoded(); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 生成随机向量,默认大小为cipher.getBlockSize(), 16字节. + */ + public static byte[] generateIV() { + byte[] bytes = new byte[DEFAULT_IVSIZE]; + random.nextBytes(bytes); + return bytes; + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Digests.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Digests.java new file mode 100644 index 0000000000000000000000000000000000000000..aefd8bda353c88b3fca3e49876245c63d2039d32 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/Digests.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.security; + +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.SecureRandom; + +import org.apache.commons.lang3.Validate; + +import com.jeespring.common.utils.Exceptions; + +/** + * 支持SHA-1/MD5消息摘要的工具类. + * + * 返回ByteSource,可进一步被编码为Hex, Base64或UrlSafeBase64 + * + * @author JeeSpring + */ +public class Digests { + + private static final String SHA1 = "SHA-1"; + private static final String MD5 = "MD5"; + + private static SecureRandom random = new SecureRandom(); + + /** + * 对输入字符串进行md5散列. + */ + public static byte[] md5(byte[] input) { + return digest(input, MD5, null, 1); + } + public static byte[] md5(byte[] input, int iterations) { + return digest(input, MD5, null, iterations); + } + + /** + * 对输入字符串进行sha1散列. + */ + public static byte[] sha1(byte[] input) { + return digest(input, SHA1, null, 1); + } + + public static byte[] sha1(byte[] input, byte[] salt) { + return digest(input, SHA1, salt, 1); + } + + public static byte[] sha1(byte[] input, byte[] salt, int iterations) { + return digest(input, SHA1, salt, iterations); + } + + /** + * 对字符串进行散列, 支持md5与sha1算法. + */ + private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) { + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + + if (salt != null) { + digest.update(salt); + } + + byte[] result = digest.digest(input); + + for (int i = 1; i < iterations; i++) { + digest.reset(); + result = digest.digest(result); + } + return result; + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * 生成随机的Byte[]作为salt. + * + * @param numBytes byte数组的大小 + */ + public static byte[] generateSalt(int numBytes) { + Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes); + + byte[] bytes = new byte[numBytes]; + random.nextBytes(bytes); + return bytes; + } + + /** + * 对文件进行md5散列. + */ + public static byte[] md5(InputStream input) throws IOException { + return digest(input, MD5); + } + + /** + * 对文件进行sha1散列. + */ + public static byte[] sha1(InputStream input) throws IOException { + return digest(input, SHA1); + } + + private static byte[] digest(InputStream input, String algorithm) throws IOException { + try { + MessageDigest messageDigest = MessageDigest.getInstance(algorithm); + int bufferLength = 8 * 1024; + byte[] buffer = new byte[bufferLength]; + int read = input.read(buffer, 0, bufferLength); + + while (read > -1) { + messageDigest.update(buffer, 0, read); + read = input.read(buffer, 0, bufferLength); + } + + return messageDigest.digest(); + } catch (GeneralSecurityException e) { + throw Exceptions.unchecked(e); + } + } + + public static String string2MD5(String inStr){ + MessageDigest md5 = null; + try{ + md5 = MessageDigest.getInstance("MD5"); + }catch (Exception e){ + System.out.println(e.toString()); + e.printStackTrace(); + return ""; + } + char[] charArray = inStr.toCharArray(); + byte[] byteArray = new byte[charArray.length]; + + for (int i = 0; i < charArray.length; i++) { + byteArray[i] = (byte) charArray[i]; + } + byte[] md5Bytes = md5.digest(byteArray); + StringBuffer hexValue = new StringBuffer(); + for (int i = 0; i < md5Bytes.length; i++){ + int val = ((int) md5Bytes[i]) & 0xff; + if (val < 16) { + hexValue.append("0"); + } + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/MD5Tools.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/MD5Tools.java new file mode 100644 index 0000000000000000000000000000000000000000..faccf024184bcfd94b1aae34c8e91baf62b073de --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/MD5Tools.java @@ -0,0 +1,50 @@ +package com.jeespring.common.security; + +import java.security.MessageDigest; + +/** + * MD5加密工具类 + * <功能详细描述> + * + * @author chenlujun + * @version [版本号, 2014年10月1日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +public class MD5Tools +{ + public final static String MD5(String pwd) { + //用于加密的字符 + char[] md5String = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + try { + //使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte数组中 + byte[] btInput = pwd.getBytes(); + + //信息摘要是安全的单向哈希函数,它接收任意大小的数据,并输出固定长度的哈希值。 + MessageDigest mdInst = MessageDigest.getInstance("MD5"); + + //MessageDigest对象通过使用 update方法处理数据, 使用指定的byte数组更新摘要 + mdInst.update(btInput); + + // 摘要更新之后,通过调用digest()执行哈希计算,获得密文 + byte[] md = mdInst.digest(); + + // 把密文转换成十六进制的字符串形式 + int j = md.length; + char[] str = new char[j * 2]; + int k = 0; + for (int i = 0; i < j; i++) { // i = 0 + byte byte0 = md[i]; //95 + str[k++] = md5String[byte0 >>> 4 & 0xf]; // 5 + str[k++] = md5String[byte0 & 0xf]; // F + } + + //返回经过加密后的字符串 + return new String(str); + + } catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/ShiroUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/ShiroUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..5a4030c5c2ebf1053595da45a92a57fb3914b55c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/ShiroUtils.java @@ -0,0 +1,85 @@ +package com.jeespring.common.security; + +import com.jeespring.modules.sys.entity.User; +import com.jeespring.modules.sys.entity.UserRealm; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.mgt.RealmSecurityManager; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.SimplePrincipalCollection; +import org.apache.shiro.subject.Subject; +import com.jeespring.common.utils.StringUtils; +import com.jeespring.common.utils.bean.BeanUtils; + +/** + * shiro 工具类 + * + * @author JeeSpring + */ +public class ShiroUtils +{ + + public static Subject getSubjct() + { + return SecurityUtils.getSubject(); + } + + public static Session getSession() + { + return SecurityUtils.getSubject().getSession(); + } + + public static void logout() + { + getSubjct().logout(); + } + + public static User getUser() + { + User user = null; + Object obj = getSubjct().getPrincipal(); + if (StringUtils.isNotNull(obj)) + { + user = new User(); + BeanUtils.copyBeanProp(user, obj); + } + return user; + } + + public static void setUser(User user) + { + Subject subject = getSubjct(); + PrincipalCollection principalCollection = subject.getPrincipals(); + String realmName = principalCollection.getRealmNames().iterator().next(); + PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName); + // 重新加载Principal + subject.runAs(newPrincipalCollection); + } + + public static void clearCachedAuthorizationInfo() + { + RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager(); + UserRealm realm = (UserRealm) rsm.getRealms().iterator().next(); + realm.clearCachedAuthorizationInfo(); + } + + public static Long getUserId() + { + return Long.valueOf(getUser().getId()); + } + + public static String getLoginName() + { + return getUser().getLoginName(); + } + + public static String getIp() + { + return getSubjct().getSession().getHost(); + } + + public static String getSessionId() + { + return String.valueOf(getSubjct().getSession().getId()); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/HasAnyPermissionsTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/HasAnyPermissionsTag.java new file mode 100644 index 0000000000000000000000000000000000000000..acbbe79757e16a578b269b43240d931fc4dfd826 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/HasAnyPermissionsTag.java @@ -0,0 +1,40 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.security.shiro; + +import org.apache.shiro.subject.Subject; +import org.apache.shiro.web.tags.PermissionTag; + +/** + * Shiro HasAnyPermissions Tag. + * + * @author calvin + */ +public class HasAnyPermissionsTag extends PermissionTag { + + private static final long serialVersionUID = 1L; + private static final String PERMISSION_NAMES_DELIMETER = ","; + + @Override + protected boolean showTagBody(String permissionNames) { + boolean hasAnyPermission = false; + + Subject subject = getSubject(); + + if (subject != null) { + // Iterate through permissions and check to see if the user has one of the permissions + for (String permission : permissionNames.split(PERMISSION_NAMES_DELIMETER)) { + + if (subject.isPermitted(permission.trim())) { + hasAnyPermission = true; + break; + } + + } + } + + return hasAnyPermission; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/cache/SessionCacheManager.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/cache/SessionCacheManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e24b4699d53bf92c186a31c86ad8a5dd4da44950 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/cache/SessionCacheManager.java @@ -0,0 +1,144 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.security.shiro.cache; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.UnavailableSecurityManagerException; +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheException; +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.session.InvalidSessionException; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Sets; +import com.jeespring.common.web.Servlets; + +/** + * 自定义授权缓存管理类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-7-21 + */ +public class SessionCacheManager implements CacheManager { + + @Override + public Cache getCache(String name) throws CacheException { + return new SessionCache(name); + } + + /** + * SESSION缓存管理类 + */ + public class SessionCache implements Cache { + + private Logger logger = LoggerFactory.getLogger(getClass()); + + private String cacheKeyName = null; + + public SessionCache(String cacheKeyName) { + this.cacheKeyName = cacheKeyName; + } + + public Session getSession(){ + Session session = null; + try{ + Subject subject = SecurityUtils.getSubject(); + session = subject.getSession(false); + if (session == null){ + session = subject.getSession(); + } + }catch (InvalidSessionException e){ + logger.error("Invalid session error", e); + }catch (UnavailableSecurityManagerException e2){ + logger.error("Unavailable SecurityManager error", e2); + } + return session; + } + + @SuppressWarnings("unchecked") + @Override + public V get(K key) throws CacheException { + if (key == null){ + return null; + } + + V v = null; + HttpServletRequest request = Servlets.getRequest(); + if (request != null){ + v = (V)request.getAttribute(cacheKeyName); + if (v != null){ + return v; + } + } + + V value = null; + value = (V)getSession().getAttribute(cacheKeyName); + logger.debug("get {} {} {}", cacheKeyName, key, request != null ? request.getRequestURI() : ""); + + if (request != null && value != null){ + request.setAttribute(cacheKeyName, value); + } + return value; + } + + @Override + public V put(K key, V value) throws CacheException { + if (key == null){ + return null; + } + + getSession().setAttribute(cacheKeyName, value); + + if (logger.isDebugEnabled()){ + HttpServletRequest request = Servlets.getRequest(); + logger.debug("put {} {} {}", cacheKeyName, key, request != null ? request.getRequestURI() : ""); + } + + return value; + } + + @SuppressWarnings("unchecked") + @Override + public V remove(K key) throws CacheException { + + V value = null; + value = (V)getSession().removeAttribute(cacheKeyName); + logger.debug("remove {} {}", cacheKeyName, key); + + return value; + } + + @Override + public void clear() throws CacheException { + getSession().removeAttribute(cacheKeyName); + logger.debug("clear {}", cacheKeyName); + } + + @Override + public int size() { + logger.debug("invoke session size abstract size method not supported."); + return 0; + } + + @Override + public Set keys() { + logger.debug("invoke session keys abstract size method not supported."); + return Sets.newHashSet(); + } + + @Override + public Collection values() { + logger.debug("invoke session values abstract size method not supported."); + return Collections.emptyList(); + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/CacheSessionDAO.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/CacheSessionDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..f970d92e92a860001d839beef69a217df23d249a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/CacheSessionDAO.java @@ -0,0 +1,194 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.security.shiro.session; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.cache.CacheManager; +import org.apache.shiro.session.Session; +import org.apache.shiro.session.UnknownSessionException; +import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.support.DefaultSubjectContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.common.collect.Sets; +import com.jeespring.common.config.Global; +import com.jeespring.common.utils.DateUtils; +import com.jeespring.common.utils.IdGen; +import com.jeespring.common.utils.StringUtils; +import com.jeespring.common.web.Servlets; + +/** + * 系统安全认证实现类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-7-24 + */ +@Component("sessionDAO") +public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements SessionDAO,InitializingBean{ + + private Logger logger = LoggerFactory.getLogger(getClass()); + @Autowired + private IdGen idgen; + @Autowired + private CacheManager cacheManager; + + @Override + public void afterPropertiesSet() throws Exception { + setSessionIdGenerator(idgen); + setActiveSessionsCacheName("activeSessionsCache"); + setCacheManager(cacheManager); + } + + public CacheSessionDAO() { + super(); + } + + + + @Override + protected void doUpdate(Session session) { + if (session == null || session.getId() == null) { + return; + } + + HttpServletRequest request = Servlets.getRequest(); + if (request != null){ + String uri = request.getServletPath(); + // 如果是静态文件,则不更新SESSION + if (Servlets.isStaticFile(uri)){ + return; + } + // 如果是视图文件,则不更新SESSION + if (StringUtils.startsWith(uri, Global.getConfig("spring.mvc.view.prefix")) + && StringUtils.endsWith(uri, Global.getConfig("spring.mvc.view.suffix"))){ + return; + } + // 手动控制不更新SESSION + String updateSession = request.getParameter("updateSession"); + if (Global.FALSE.equals(updateSession) || Global.NO.equals(updateSession)){ + return; + } + } + super.doUpdate(session); + logger.debug("update {} {}", session.getId(), request != null ? request.getRequestURI() : ""); + } + + @Override + protected void doDelete(Session session) { + if (session == null || session.getId() == null) { + return; + } + + super.doDelete(session); + logger.debug("delete {} ", session.getId()); + } + + @Override + protected Serializable doCreate(Session session) { + HttpServletRequest request = Servlets.getRequest(); + if (request != null){ + String uri = request.getServletPath(); + // 如果是静态文件,则不创建SESSION + if (Servlets.isStaticFile(uri)){ + return null; + } + } + super.doCreate(session); + logger.debug("doCreate {} {}", session, request != null ? request.getRequestURI() : ""); + return session.getId(); + } + + @Override + protected Session doReadSession(Serializable sessionId) { + return super.doReadSession(sessionId); + } + + @Override + public Session readSession(Serializable sessionId) throws UnknownSessionException { + try{ + Session s = null; + HttpServletRequest request = Servlets.getRequest(); + if (request != null){ + String uri = request.getServletPath(); + // 如果是静态文件,则不获取SESSION + if (Servlets.isStaticFile(uri)){ + return null; + } + s = (Session)request.getAttribute("session_"+sessionId); + } + if (s != null){ + return s; + } + + Session session = super.readSession(sessionId); + logger.debug("readSession {} {}", sessionId, request != null ? request.getRequestURI() : ""); + + if (request != null && session != null){ + request.setAttribute("session_"+sessionId, session); + } + + return session; + }catch (UnknownSessionException e) { + return null; + } + } + + /** + * 获取活动会话 + * @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话) + * @return + */ + @Override + public Collection getActiveSessions(boolean includeLeave) { + return getActiveSessions(includeLeave, null, null); + } + + /** + * 获取活动会话 + * @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话) + * @param principal 根据登录者对象获取活动会话 + * @param filterSession 不为空,则过滤掉(不包含)这个会话。 + * @return + */ + @Override + public Collection getActiveSessions(boolean includeLeave, Object principal, Session filterSession) { + // 如果包括离线,并无登录者条件。 + if (includeLeave && principal == null){ + return getActiveSessions(); + } + Set sessions = Sets.newHashSet(); + for (Session session : getActiveSessions()){ + boolean isActiveSession = false; + // 不包括离线并符合最后访问时间小于等于3分钟条件。 + if (includeLeave || DateUtils.pastMinutes(session.getLastAccessTime()) <= 3){ + isActiveSession = true; + } + // 符合登陆者条件。 + if (principal != null){ + PrincipalCollection pc = (PrincipalCollection)session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + if (principal.toString().equals(pc != null ? pc.getPrimaryPrincipal().toString() : StringUtils.EMPTY)){ + isActiveSession = true; + } + } + // 过滤掉的SESSION + if (filterSession != null && filterSession.getId().equals(session.getId())){ + isActiveSession = false; + } + if (isActiveSession){ + sessions.add(session); + } + } + return sessions; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionDAO.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionDAO.java new file mode 100644 index 0000000000000000000000000000000000000000..570d9c71d63e49240d564d8d5b7da363fbc80f31 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionDAO.java @@ -0,0 +1,25 @@ +package com.jeespring.common.security.shiro.session; + +import java.util.Collection; + +import org.apache.shiro.session.Session; + +public interface SessionDAO extends org.apache.shiro.session.mgt.eis.SessionDAO { + + /** + * 获取活动会话 + * @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话) + * @return + */ + Collection getActiveSessions(boolean includeLeave); + + /** + * 获取活动会话 + * @param includeLeave 是否包括离线(最后访问时间大于3分钟为离线会话) + * @param principal 根据登录者对象获取活动会话 + * @param filterSession 不为空,则过滤掉(不包含)这个会话。 + * @return + */ + Collection getActiveSessions(boolean includeLeave, Object principal, Session filterSession); + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionManager.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..c3d4c2116557581fbb348b4ed98785ca61147102 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/security/shiro/session/SessionManager.java @@ -0,0 +1,222 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.security.shiro.session; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Date; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.jeespring.common.utils.StringUtils; +import org.apache.shiro.session.InvalidSessionException; +import org.apache.shiro.session.Session; +import org.apache.shiro.session.UnknownSessionException; +import org.apache.shiro.session.mgt.SessionContext; +import org.apache.shiro.session.mgt.SessionKey; +import org.apache.shiro.session.mgt.SimpleSession; +import org.apache.shiro.web.servlet.Cookie; +import org.apache.shiro.web.servlet.ShiroHttpServletRequest; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.apache.shiro.web.util.WebUtils; + +import org.springframework.stereotype.Component; + +/** + * 自定义WEB会话管理类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-7-20 + */ +@Component +public class SessionManager extends DefaultWebSessionManager { + + public SessionManager() { + super(); + } + + @Override + protected Serializable getSessionId(ServletRequest request, ServletResponse response) { + // 如果参数中包含“__sid”参数,则使用此sid会话。 例如:http://localhost/project?__sid=xxx&__cookie=true + String sid = request.getParameter("__sid"); + if (StringUtils.isNotBlank(sid)) { + // 是否将sid保存到cookie,浏览器模式下使用此参数。 + if (WebUtils.isTrue(request, "__cookie")){ + HttpServletRequest rq = (HttpServletRequest)request; + HttpServletResponse rs = (HttpServletResponse)response; + Cookie template = getSessionIdCookie(); + Cookie cookie = new SimpleCookie(template); + cookie.setValue(sid); cookie.saveTo(rq, rs); + } + // 设置当前session状态 + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, + ShiroHttpServletRequest.URL_SESSION_ID_SOURCE); // session来源与url + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sid); + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE); + return sid; + }else{ + return super.getSessionId(request, response); + } + } + + @Override + public void validateSessions() { + super.validateSessions(); + } + + @Override + protected Session retrieveSession(SessionKey sessionKey) { + try{ + return super.retrieveSession(sessionKey); + }catch (UnknownSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public Date getStartTimestamp(SessionKey key) { + try{ + return super.getStartTimestamp(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public Date getLastAccessTime(SessionKey key) { + try{ + return super.getLastAccessTime(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public long getTimeout(SessionKey key){ + try{ + return super.getTimeout(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return 0; + } + } + + @Override + public void setTimeout(SessionKey key, long maxIdleTimeInMillis) { + try{ + super.setTimeout(key, maxIdleTimeInMillis); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + } + } + + @Override + public void touch(SessionKey key) { + try{ + super.touch(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + } + } + + @Override + public String getHost(SessionKey key) { + try{ + return super.getHost(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public Collection getAttributeKeys(SessionKey key) { + try{ + return super.getAttributeKeys(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public Object getAttribute(SessionKey sessionKey, Object attributeKey) { + try{ + return super.getAttribute(sessionKey, attributeKey); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public void setAttribute(SessionKey sessionKey, Object attributeKey, Object value) { + try{ + super.setAttribute(sessionKey, attributeKey, value); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + } + } + + @Override + public Object removeAttribute(SessionKey sessionKey, Object attributeKey) { + try{ + return super.removeAttribute(sessionKey, attributeKey); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + return null; + } + } + + @Override + public void stop(SessionKey key) { + try{ + super.stop(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + } + } + + @Override + public void checkValid(SessionKey key) { + try{ + super.checkValid(key); + }catch (InvalidSessionException e) { + // 获取不到SESSION不抛出异常 + } + } + + @Override + protected Session doCreateSession(SessionContext context) { + try{ + return super.doCreateSession(context); + }catch (IllegalStateException e) { + return null; + } + } + + @Override + protected Session newSessionInstance(SessionContext context) { + Session session = super.newSessionInstance(context); + session.setTimeout(getGlobalSessionTimeout()); + return session; + } + + @Override + public Session start(SessionContext context) { + try{ + return super.start(context); + }catch (NullPointerException e) { + SimpleSession session = new SimpleSession(); + session.setId(0); + return session; + } + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractBaseService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractBaseService.java new file mode 100644 index 0000000000000000000000000000000000000000..d45ed9a5c33ad8a5b5514b9a732ee8d482b24805 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractBaseService.java @@ -0,0 +1,130 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.service; + +import com.jeespring.common.persistence.InterfaceBaseDao; +import com.jeespring.common.persistence.AbstractBaseEntity; +import com.jeespring.common.persistence.Page; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * Service基类 + * + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +@Transactional(readOnly = true) +public abstract class AbstractBaseService, T extends AbstractBaseEntity> extends AbstractService { + + /** + * 持久层对象 + */ + @Autowired + protected Dao dao; + + /** + * 获取单条数据 + * + * @param id + * @return + */ + public T get(String id) { + return dao.get(id); + } + + /** + * 获取单条数据 + * + * @param entity + * @return + */ + public T get(T entity) { + return dao.get(entity); + } + + /** + * 查询统计数据 + * + * @param entity + * @return + */ + public List total(T entity) { + return dao.total(entity); + } + + /** + * 查询列表数据 + * + * @param entity + * @return + */ + public List findList(T entity) { + return dao.findList(entity); + } + + /** + * 查询所有 + * + * @param entity + * @return + */ + public List findAllList(T entity) { + return dao.findAllList(entity); + } + + /** + * 查询分页数据 + * + * @param page 分页对象 + * @param entity + * @return + */ + public Page findPage(Page page, T entity) { + entity.setPage(page); + page.setList(dao.findList(entity)); + return page; + } + + /** + * 保存数据(插入或更新) + * + * @param entity + */ + @Transactional(readOnly = false) + public void save(T entity) { + int result=0; + if (entity.getIsNewRecord()) { + entity.preInsert(); + result=dao.insert(entity); + } else { + entity.preUpdate(); + result=dao.update(entity); + } + } + + /** + * 删除数据 + * + * @param entity + */ + @Transactional(readOnly = false) + public void delete(T entity) { + dao.delete(entity); + } + + /** + * 删除数据(逻辑删除,更新del_flag字段为1,在表包含字段del_flag时,可以调用此方法,将数据隐藏) + * @param entity + * @return + */ + @Transactional(readOnly = false) + public void deleteByLogic(T entity) { + dao.deleteByLogic(entity); + } + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractService.java new file mode 100644 index 0000000000000000000000000000000000000000..1580a864d365f9b847e77c183b6370c04f848c31 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/AbstractService.java @@ -0,0 +1,187 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.service; + +import java.util.List; + +import com.jeespring.common.persistence.AbstractEntity; +import com.jeespring.common.utils.StringUtils; +import com.jeespring.modules.sys.entity.Role; +import com.jeespring.modules.sys.entity.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; + +/** + * Service基类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +@Transactional(readOnly = true) +public abstract class AbstractService implements InterfaceService { + + /** + * 日志对象 + */ + protected Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * 数据范围过滤 + * @param user 当前用户对象,通过“entity.getCurrentUser()”获取 + * @param officeAlias 机构表别名,多个用“,”逗号隔开。 + * @param userAlias 用户表别名,多个用“,”逗号隔开,传递空,忽略此参数 + * @return 标准连接条件对象 + */ + public static String dataScopeFilter(User user, String officeAlias, String userAlias) { + + StringBuilder sqlString = new StringBuilder(); + + // 进行权限过滤,多个角色权限范围之间为或者关系。 + List dataScope = Lists.newArrayList(); + + // 超级管理员,跳过权限过滤 + if (!user.isAdmin()){ + boolean isDataScopeAll = false; + for (Role r : user.getRoleList()){ + for (String oa : StringUtils.split(officeAlias, ",")){ + if (!dataScope.contains(r.getDataScope()) && StringUtils.isNotBlank(oa)){ + if (Role.DATA_SCOPE_ALL.equals(r.getDataScope())){ + isDataScopeAll = true; + } + else if (Role.DATA_SCOPE_COMPANY_AND_CHILD.equals(r.getDataScope())){ + sqlString.append(" OR " + oa + ".id = '" + user.getCompany().getId() + "'"); + sqlString.append(" OR " + oa + ".parent_ids LIKE '" + user.getCompany().getParentIds() + user.getCompany().getId() + ",%'"); + } + else if (Role.DATA_SCOPE_COMPANY.equals(r.getDataScope())){ + sqlString.append(" OR " + oa + ".id = '" + user.getCompany().getId() + "'"); + // 包括本公司下的部门 (type=1:公司;type=2:部门) + sqlString.append(" OR (" + oa + ".parent_id = '" + user.getCompany().getId() + "' AND " + oa + ".type = '2')"); + } + else if (Role.DATA_SCOPE_OFFICE_AND_CHILD.equals(r.getDataScope())){ + sqlString.append(" OR " + oa + ".id = '" + user.getOffice().getId() + "'"); + sqlString.append(" OR " + oa + ".parent_ids LIKE '" + user.getOffice().getParentIds() + user.getOffice().getId() + ",%'"); + } + else if (Role.DATA_SCOPE_OFFICE.equals(r.getDataScope())){ + sqlString.append(" OR " + oa + ".id = '" + user.getOffice().getId() + "'"); + } + else if (Role.DATA_SCOPE_CUSTOM.equals(r.getDataScope())){ + sqlString.append(" OR EXISTS (SELECT 1 FROM sys_role_office WHERE role_id = '" + r.getId() + "'"); + sqlString.append(" AND office_id = " + oa +".id)"); + } + //else if (Role.DATA_SCOPE_SELF.equals(r.getDataScope())){ + dataScope.add(r.getDataScope()); + } + } + } + // 如果没有全部数据权限,并设置了用户别名,则当前权限为本人;如果未设置别名,当前无权限为已植入权限 + if (!isDataScopeAll){ + if (StringUtils.isNotBlank(userAlias)){ + for (String ua : StringUtils.split(userAlias, ",")){ + sqlString.append(" OR " + ua + ".id = '" + user.getId() + "'"); + } + }else { + for (String oa : StringUtils.split(officeAlias, ",")){ + //sqlString.append(" OR " + oa + ".id = " + user.getOffice().getId()); + sqlString.append(" OR " + oa + ".id IS NULL"); + } + } + }else{ + // 如果包含全部权限,则去掉之前添加的所有条件,并跳出循环。 + sqlString = new StringBuilder(); + } + } + if (StringUtils.isNotBlank(sqlString.toString())){ + return " AND (" + sqlString.substring(4) + ")"; + } + return ""; + } + + /** + * 数据范围过滤(符合业务表字段不同的时候使用,采用exists方法) + * @param entity 当前过滤的实体类 + * @param sqlMapKey sqlMap的键值,例如设置“dsf”时,调用方法:${sqlMap.sdf} + * @param officeWheres office表条件,组成:部门表字段=业务表的部门字段 + * @param userWheres user表条件,组成:用户表字段=业务表的用户字段 + * @example + * dataScopeFilter(user, "dsf", "id=a.office_id", "id=a.create_by"); + * dataScopeFilter(entity, "dsf", "code=a.jgdm", "no=a.cjr"); // 适应于业务表关联不同字段时使用,如果关联的不是机构id是code。 + */ + public static void dataScopeFilter(AbstractEntity> entity, String sqlMapKey, String officeWheres, String userWheres) { + + User user = entity.getCurrentUser(); + + // 如果是超级管理员,则不过滤数据 + if (user.isAdmin()) { + return; + } + + // 数据范围(1:所有数据;2:所在公司及以下数据;3:所在公司数据;4:所在部门及以下数据;5:所在部门数据;8:仅本人数据;9:按明细设置) + StringBuilder sqlString = new StringBuilder(); + + // 获取到最大的数据权限范围 + String roleId = ""; + int dataScopeInteger = 8; + for (Role r : user.getRoleList()){ + int ds = Integer.valueOf(r.getDataScope()); + if (ds == 9){ + roleId = r.getId(); + dataScopeInteger = ds; + break; + }else if (ds < dataScopeInteger){ + roleId = r.getId(); + dataScopeInteger = ds; + } + } + String dataScopeString = String.valueOf(dataScopeInteger); + + // 生成部门权限SQL语句 + for (String where : StringUtils.split(officeWheres, ",")){ + if (Role.DATA_SCOPE_COMPANY_AND_CHILD.equals(dataScopeString)){ + // 包括本公司下的部门 (type=1:公司;type=2:部门) + sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE"); + sqlString.append(" WHERE type='2'"); + sqlString.append(" AND (id = '" + user.getCompany().getId() + "'"); + sqlString.append(" OR parent_ids LIKE '" + user.getCompany().getParentIds() + user.getCompany().getId() + ",%')"); + sqlString.append(" AND " + where +")"); + } + else if (Role.DATA_SCOPE_COMPANY.equals(dataScopeString)){ + sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE"); + sqlString.append(" WHERE type='2'"); + sqlString.append(" AND id = '" + user.getCompany().getId() + "'"); + sqlString.append(" AND " + where +")"); + } + else if (Role.DATA_SCOPE_OFFICE_AND_CHILD.equals(dataScopeString)){ + sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE"); + sqlString.append(" WHERE (id = '" + user.getOffice().getId() + "'"); + sqlString.append(" OR parent_ids LIKE '" + user.getOffice().getParentIds() + user.getOffice().getId() + ",%')"); + sqlString.append(" AND " + where +")"); + } + else if (Role.DATA_SCOPE_OFFICE.equals(dataScopeString)){ + sqlString.append(" AND EXISTS (SELECT 1 FROM SYS_OFFICE"); + sqlString.append(" WHERE id = '" + user.getOffice().getId() + "'"); + sqlString.append(" AND " + where +")"); + } + else if (Role.DATA_SCOPE_CUSTOM.equals(dataScopeString)){ + sqlString.append(" AND EXISTS (SELECT 1 FROM sys_role_office ro123456, sys_office o123456"); + sqlString.append(" WHERE ro123456.office_id = o123456.id"); + sqlString.append(" AND ro123456.role_id = '" + roleId + "'"); + sqlString.append(" AND o123456." + where +")"); + } + } + // 生成个人权限SQL语句 + for (String where : StringUtils.split(userWheres, ",")){ + if (Role.DATA_SCOPE_SELF.equals(dataScopeString)){ + sqlString.append(" AND EXISTS (SELECT 1 FROM sys_user"); + sqlString.append(" WHERE id='" + user.getId() + "'"); + sqlString.append(" AND " + where + ")"); + } + } + // 设置到自定义SQL对象 + entity.getSqlMap().put(sqlMapKey, sqlString.toString()); + + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ICommonService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ICommonService.java new file mode 100644 index 0000000000000000000000000000000000000000..e71e719e67289a86c16f5e1c7b177f01140e7d57 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ICommonService.java @@ -0,0 +1,75 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.service; + +import com.jeespring.common.persistence.Page; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * Service基类 + * + * @author HuangBingGui + * @version 2014-05-16 + */ +public interface ICommonService { + /** + * 获取单条数据 + * + * @param id + * @return + */ + T get(String id); + + /** + * 获取单条数据 + * + * @param entity + * @return + */ + T get(T entity); + + /** + * 查询列表数据 + * + * @param entity + * @return + */ + List findList(T entity); + + /** + * 查询所有 + * + * @param entity + * @return + */ + List findAllList(T entity); + + /** + * 查询分页数据 + * + * @param page 分页对象 + * @param entity + * @return + */ + Page findPage(Page page, T entity) ; + + /** + * 保存数据(插入或更新) + * + * @param entity + */ + @Transactional(readOnly = false) + void save(T entity) ; + + /** + * 删除数据 + * + * @param entity + */ + @Transactional(readOnly = false) + void delete(T entity); + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/InterfaceService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/InterfaceService.java new file mode 100644 index 0000000000000000000000000000000000000000..04ae74bae9dbbf5583a135d3b10fff0a2f2184a5 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/InterfaceService.java @@ -0,0 +1,6 @@ +package com.jeespring.common.service; + +import com.jeespring.modules.sys.entity.User; + +public interface InterfaceService { +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ServiceException.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ServiceException.java new file mode 100644 index 0000000000000000000000000000000000000000..296219da53514bae2c5bb17d44481e8c383cd3a4 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/ServiceException.java @@ -0,0 +1,22 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.service; + +/** + * Service层公用的Exception, 从由Spring管理事务的函数中抛出时会触发事务回滚. + * @author 黄炳桂 516821420@qq.com + */ +public class ServiceException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public ServiceException(String message) { + super(message); + } + + public ServiceException(Throwable cause) { + super(cause); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/TreeService.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/TreeService.java new file mode 100644 index 0000000000000000000000000000000000000000..4bd9d10a64837d0c25f08ae566a953722b1fe7c8 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/service/TreeService.java @@ -0,0 +1,84 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.service; + +import java.util.List; + +import org.springframework.transaction.annotation.Transactional; + +import com.jeespring.common.persistence.TreeDao; +import com.jeespring.common.persistence.TreeEntity; +import com.jeespring.common.utils.Reflections; +import com.jeespring.common.utils.StringUtils; + +/** + * Service基类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-05-16 + */ +@Transactional(readOnly = true) +public abstract class TreeService, T extends TreeEntity> extends AbstractBaseService { + + @Override + @Transactional(readOnly = false) + public void save(T entity) { + + @SuppressWarnings("unchecked") + Class entityClass = Reflections.getClassGenricType(getClass(), 1); + + // 如果没有设置父节点,则代表为跟节点,有则获取父节点实体 + if (entity.getParent() == null || StringUtils.isBlank(entity.getParentId()) + || "0".equals(entity.getParentId())){ + entity.setParent(null); + }else{ + entity.setParent(super.get(entity.getParentId())); + } + if (entity.getParent() == null){ + T parentEntity = null; + try { + parentEntity = entityClass.getConstructor(String.class).newInstance("0"); + } catch (Exception e) { + throw new ServiceException(e); + } + entity.setParent(parentEntity); + entity.getParent().setParentIds(StringUtils.EMPTY); + } + + // 获取修改前的parentIds,用于更新子节点的parentIds + String oldParentIds = entity.getParentIds(); + + // 设置新的父节点串 + entity.setParentIds(entity.getParent().getParentIds()+entity.getParent().getId()+","); + + // 保存或更新实体 + super.save(entity); + + // 更新子节点 parentIds + T o = null; + try { + o = entityClass.newInstance(); + } catch (Exception e) { + throw new ServiceException(e); + } + o.setParentIds("%,"+entity.getId()+",%"); + List list = dao.findByParentIdsLike(o); + for (T e : list){ + if (e.getParentIds() != null && oldParentIds != null){ + e.setParentIds(e.getParentIds().replace(oldParentIds, entity.getParentIds())); + preUpdateChild(entity, e); + dao.updateParentIds(e); + } + } + + } + + /** + * 预留接口,用户更新子节前调用 + * @param childEntity + */ + protected void preUpdateChild(T entity, T childEntity) { + + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/CKFinderConnectorServlet.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/CKFinderConnectorServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..26a2749b71bb60422c4d23dcfdbd8fb1ac9a9b51 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/CKFinderConnectorServlet.java @@ -0,0 +1,77 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.ckfinder.connector.ConnectorServlet; +import com.jeespring.common.config.Global; +import com.jeespring.common.utils.FileUtils; +import com.jeespring.modules.sys.security.SystemAuthorizingRealm.Principal; +import com.jeespring.modules.sys.utils.UserUtils; + +/** + * CKFinderConnectorServlet + * @author 黄炳桂 516821420@qq.com + * @version 2014-06-25 + */ +@WebServlet(urlPatterns = "/static/ckfinder/core/connector/java/connector.java", initParams = { + @WebInitParam(name = "XMLConfig", value = "classpath:ckfinder.xml"), + @WebInitParam(name = "debug", value = "false"), + @WebInitParam(name = "configuration", value = "com.jeespring.common.web.CKFinderConfig") +}, loadOnStartup = 1) +public class CKFinderConnectorServlet extends ConnectorServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + prepareGetResponse(request, response, false); + super.doGet(request, response); + } + + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + prepareGetResponse(request, response, true); + super.doPost(request, response); + } + + private void prepareGetResponse(final HttpServletRequest request, + final HttpServletResponse response, final boolean post) throws ServletException { + Principal principal = UserUtils.getPrincipal(); + if (principal == null) { + return; + } + String command = request.getParameter("command"); + String type = request.getParameter("type"); + // 初始化时,如果startupPath文件夹不存在,则自动创建startupPath文件夹 + if ("Init".equals(command)) { + String startupPath = request.getParameter("startupPath");// 当前文件夹可指定为模块名 + if (startupPath != null) { + String[] ss = startupPath.split(":"); + if (ss.length == 2) { + String realPath = Global.getUserfilesBaseDir() + Global.USERFILES_BASE_URL + + principal + "/" + ss[0] + ss[1]; + FileUtils.createDirectory(FileUtils.path(realPath)); + } + } + } + // 快捷上传,自动创建当前文件夹,并上传到该路径 + else if ("QuickUpload".equals(command) && type != null) { + String currentFolder = request.getParameter("currentFolder");// 当前文件夹可指定为模块名 + String realPath = Global.getUserfilesBaseDir() + Global.USERFILES_BASE_URL + + principal + "/" + type + (currentFolder != null ? currentFolder : ""); + FileUtils.createDirectory(FileUtils.path(realPath)); + } + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/UserfilesDownloadServlet.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/UserfilesDownloadServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..29876dc7d99c7b3381f7d7fefa20faa7ecfa9dd0 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/UserfilesDownloadServlet.java @@ -0,0 +1,64 @@ +package com.jeespring.common.servlet; + +import com.jeespring.common.config.Global; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.util.UriUtils; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; + +/** + * 查看CK上传的图片 + * + * @author 黄炳桂 516821420@qq.com + * @version 2014-06-25 + */ +@WebServlet(urlPatterns = "/userfiles/*") +public class UserfilesDownloadServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private Logger logger = LoggerFactory.getLogger(getClass()); + + public void fileOutputStream(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + String filepath = req.getRequestURI(); + int index = filepath.indexOf(Global.USERFILES_BASE_URL); + if (index >= 0) { + filepath = filepath.substring(index + Global.USERFILES_BASE_URL.length()); + } + try { + filepath = UriUtils.decode(filepath, "UTF-8"); + //} catch (UnsupportedEncodingException e1) { + } catch (Exception e1) { + logger.error(String.format("解释文件路径失败,URL地址为%s", filepath), e1); + } + File file = new File(Global.getUserfilesBaseDir() + Global.USERFILES_BASE_URL + filepath); + try { + FileCopyUtils.copy(new FileInputStream(file), resp.getOutputStream()); + resp.setHeader("Content-Type", "application/octet-stream"); + //resp.setHeader("Cache-Control", "max-age=604800");//设置缓存 + return; + } catch (FileNotFoundException e) { + req.setAttribute("exception", new FileNotFoundException("请求的文件不存在")); + req.getRequestDispatcher("/webapp/WEB-INF/views/error/404.jsp").forward(req, resp); + } + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + fileOutputStream(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + fileOutputStream(req, resp); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/ValidateCodeServlet.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/ValidateCodeServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..4690643f3c89294ea25b90cdc961acff1601cd1f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/servlet/ValidateCodeServlet.java @@ -0,0 +1,179 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.servlet; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Random; + +import javax.imageio.ImageIO; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.math.NumberUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * 生成随机验证码 + * @author 黄炳桂 516821420@qq.com + * @version 2014-7-27 + */ +@SuppressWarnings("serial") +@WebServlet(urlPatterns = "/servlet/validateCodeServlet") +public class ValidateCodeServlet extends HttpServlet { + + public static final String VALIDATE_CODE = "validateCode"; + + //private int w = 70; + //private int h = 26; + private int w = 80; + private int h = 40; + + public ValidateCodeServlet() { + super(); + } + + @Override + public void destroy() { + super.destroy(); + } + + public static boolean validate(HttpServletRequest request, String validateCode){ + String code = (String)request.getSession().getAttribute(VALIDATE_CODE); + return validateCode.toUpperCase().equals(code); + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + String validateCode = request.getParameter(VALIDATE_CODE); // AJAX验证,成功返回true + if (StringUtils.isNotBlank(validateCode)){ + response.getOutputStream().print(validate(request, validateCode)?"true":"false"); + }else{ + this.doPost(request, response); + } + } + + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + createImage(request,response); + } + + private void createImage(HttpServletRequest request, + HttpServletResponse response) throws IOException { + + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + response.setContentType("image/jpeg"); + + /* + * 得到参数高,宽,都为数字时,则使用设置高宽,否则使用默认值 + */ + String width = request.getParameter("width"); + String height = request.getParameter("height"); + if (StringUtils.isNumeric(width) && StringUtils.isNumeric(height)) { + w = NumberUtils.toInt(width); + h = NumberUtils.toInt(height); + } + + BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics g = image.getGraphics(); + + /* + * 生成背景 + */ + createBackground(g); + + /* + * 生成字符 + */ + String s = createCharacter(g); + createLine(g); + request.getSession().setAttribute(VALIDATE_CODE, s); + + g.dispose(); + OutputStream out = response.getOutputStream(); + ImageIO.write(image, "JPEG", out); + out.close(); + + } + + private Color getRandColor(int fc,int bc) { + int f = fc; + int b = bc; + Random random=new Random(); + if(f>255) { + f=255; + } + if(b>255) { + b=255; + } + return new Color(f+random.nextInt(b-f),f+random.nextInt(b-f),f+random.nextInt(b-f)); + } + + private void createBackground(Graphics g) { + // 填充背景 + //g.setColor(getRandColor(220,250)); + g.setColor(new Color(255,255,255)); + g.fillRect(0, 0, w, h); + // 加入干扰线条 + //干扰线条先注释 + for (int i = 0; i < 20; i++) { + /*g.setColor(getRandColor(40,150)); + Random random = new Random(); + int x = random.nextInt(w); + int y = random.nextInt(h); + int x1 = random.nextInt(w); + int y1 = random.nextInt(h); + g.drawLine(x, y, x1, y1);*/ + } + } + private void createLine(Graphics g) { + // 加入干扰线条 + //干扰线条先注释 + Random randomTimes = new Random(); + int times=randomTimes.nextInt(25); + for (int i = 0; i T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static Class> getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/swagger/Swagger.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/swagger/Swagger.java new file mode 100644 index 0000000000000000000000000000000000000000..493ff74dd197c908561ef403d83be01b3664e0b5 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/swagger/Swagger.java @@ -0,0 +1,62 @@ +package com.jeespring.common.swagger; + +import com.google.common.base.Predicates; +import com.jeespring.common.web.AbstractBaseController; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +@Configuration +@EnableSwagger2 +public class Swagger { + + @Bean("JeeSpring云接口") + public Docket createJeeSpringRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .groupName("JeeSpring云接口") + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) //这里采用包含注解的方式来确定要显示的接口 + //.apis(RequestHandlerSelectors.basePackage("com.jeespring.modules")) //这里采用包扫描的方式来确定要显示的接口 + //.apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) + //.paths(PathSelectors.regex("/rest/.*")) + //.paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("Swagger2构建RESTful APIs") + .description("更多JeeSpring相关文章") + .termsOfServiceUrl("http://www.jeespring.com/") + .contact("contact") + .version("1.0") + .build(); + } + + /*注解 + @ApiOperation(value="创建用户", notes="根据User对象创建用户") + @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User") + + + @ApiOperation("生成代码") + @ApiImplicitParams({ + @ApiImplicitParam(name = "moduleName", value = "模块名称", required = true, dataType = "String"), + @ApiImplicitParam(name = "bizChName", value = "业务名称", required = true, dataType = "String"), + @ApiImplicitParam(name = "bizEnName", value = "业务英文名称", required = true, dataType = "String"), + @ApiImplicitParam(name = "path", value = "项目生成类路径", required = true, dataType = "String") + }) + */ +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/AceMenuTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/AceMenuTag.java new file mode 100644 index 0000000000000000000000000000000000000000..b6e56e6f0d51a6532f3a8840230a16657fdc032c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/AceMenuTag.java @@ -0,0 +1,132 @@ +package com.jeespring.common.tag; + +import java.io.IOException; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspTagException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.tagext.TagSupport; + +import com.jeespring.common.config.Global; +import com.jeespring.common.utils.SpringContextHolder; +import com.jeespring.modules.sys.entity.Menu; +import com.jeespring.modules.sys.utils.UserUtils; + +/** + * + * 类描述:菜单标签 + * + * 刘高峰 + * + * @date: 日期:2015-1-23 时间:上午10:17:45 + * @version 1.0 + */ +public class AceMenuTag extends TagSupport { + private static final long serialVersionUID = 1L; + protected Menu menu;// 菜单Map + + public Menu getMenu() { + return menu; + } + + public void setMenu(Menu menu) { + this.menu = menu; + } + + @Override + public int doStartTag() throws JspTagException { + return EVAL_PAGE; + } + + @Override + public int doEndTag() throws JspTagException { + try { + JspWriter out = this.pageContext.getOut(); + String menu = (String) this.pageContext.getSession().getAttribute( + "menu"); + if (menu != null) { + out.print(menu); + } else { + menu = end().toString(); + out.print(menu); + + } + + } catch (IOException e) { + e.printStackTrace(); + } + return EVAL_PAGE; + } + + public StringBuffer end() { + StringBuffer sb = new StringBuffer(); + sb.append(getChildOfTree(menu, 0, UserUtils.getMenuList())); + + System.out.println(sb); + return sb; + + } + + private static String getChildOfTree(Menu parent, int level, List menuList) { + StringBuffer menuString = new StringBuffer(); + String href = ""; + if (!parent.hasPermisson()) { + return ""; + } + + ServletContext context = SpringContextHolder + .getBean(ServletContext.class); + if (parent.getHref() != null && parent.getHref().length() > 0) { + + if (parent.getHref().endsWith(".html") + && !parent.getHref().endsWith("ckfinder.html")) {// 如果是静态资源并且不是ckfinder.html,直接访问不加adminPath + href = context.getContextPath() + parent.getHref(); + } else { + href = context.getContextPath() + Global.getAdminPath() + + parent.getHref(); + } + + } + + if (level > 0) {// level 为0是功能菜单 + menuString.append(""); + if ((parent.getHref() == null || "".equals(parent.getHref().trim())) && "1".equals(parent.getIsShow())) { + menuString.append(""); + } else { + menuString.append(""); + } + menuString.append(""); + menuString.append(""+parent.getName()+""); + if ((parent.getHref() == null || "".equals(parent.getHref().trim())) && "1".equals(parent.getIsShow())) { + menuString.append(""); + } + menuString.append(""); + menuString.append(""); + } + if ((parent.getHref() == null || "".equals(parent.getHref().trim())) && "1".equals(parent.getIsShow())) { + if (level == 0) { + menuString.append(""); + } else { + menuString.append(""); + } + + for (Menu child : menuList) { + + if (child.getParentId().equals(parent.getId())&& "1".equals(child.getIsShow())) { + menuString.append(getChildOfTree(child, level + 1, menuList)); + } + + } + menuString.append(""); + } + if (level > 0) { + menuString.append(""); + } + return menuString.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/MenuTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/MenuTag.java new file mode 100644 index 0000000000000000000000000000000000000000..0ca9537783b54064a3fd8d44588b458681210a8b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/MenuTag.java @@ -0,0 +1,145 @@ +package com.jeespring.common.tag; + +import java.io.IOException; + +import javax.servlet.ServletContext; +import javax.servlet.jsp.JspTagException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.tagext.TagSupport; + +import com.jeespring.common.config.Global; +import com.jeespring.common.utils.SpringContextHolder; +import com.jeespring.modules.sys.entity.Menu; +import com.jeespring.modules.sys.utils.UserUtils; + + +/** + * + * 类描述:菜单标签 + * + * + * @date: 日期:2012-12-7 时间:上午10:17:45 + * @version 1.0 + */ +public class MenuTag extends TagSupport { + private static final long serialVersionUID = 1L; + protected Menu menu;//菜单Map + + + + public Menu getMenu() { + return menu; + } + + public void setMenu(Menu menu) { + this.menu = menu; + } + + @Override + public int doStartTag() throws JspTagException { + return EVAL_PAGE; + } + + @Override + public int doEndTag() throws JspTagException { + try { + JspWriter out = this.pageContext.getOut(); + String menu = (String) this.pageContext.getSession().getAttribute("menu"); + if(menu!=null){ + out.print(menu); + }else{ + menu=end().toString(); + out.print(menu); + + } + + } catch (IOException e) { + e.printStackTrace(); + } + return EVAL_PAGE; + } + + public StringBuffer end() { + StringBuffer sb = new StringBuffer(); + sb.append(getChildOfTree(menu,0)); + //System.out.println(sb); + return sb; + + } + + private static String getChildOfTree(Menu parent, int level) { + StringBuffer menuString = new StringBuffer(); + String href = ""; + if (!parent.hasPermisson()) { + return ""; + } + if (level > 0) {//level 为0是功能菜单 + if(parent.hasChildren()) + //menu-open + { + menuString.append(""); + } else { + menuString.append(""); + } + + ServletContext context = SpringContextHolder + .getBean(ServletContext.class); + if (parent.getHref() != null && parent.getHref().length() > 0) { + + + if(parent.getHref().endsWith(".html")&&!parent.getHref().endsWith("ckfinder.html")){//如果是静态资源并且不是ckfinder.html,直接访问不加adminPath + href = context.getContextPath() + parent.getHref(); + } + else if(parent.getHref().contains("http://") || parent.getHref().contains("https://")){ + href = context.getContextPath() + parent.getHref(); + } + else{ + href = context.getContextPath() + Global.getAdminPath() + + parent.getHref(); + } + } + } + + if (parent.hasChildren()) { + if (level > 0) { + menuString + .append(" " + + parent.getName() + //+ ""); + + ""); + } + if (level == 1) { + menuString.append(""); + } else if (level == 2) { + menuString.append(""); + }else if (level == 3) { + menuString.append(""); + } else if (level == 4) { + menuString.append(""); + } + for (Menu child : parent.getChildren()) { + if ("1".equals(child.getIsShow())) { + menuString.append(getChildOfTree(child, level + 1)); + } + } + if (level > 0) { + menuString.append(""); + } + } else { + //javascript: + menuString.append(" "+parent.getName()+""); + } + if (level > 0) { + menuString.append(""); + } + + return menuString.toString(); + } + + + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsBarTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsBarTag.java new file mode 100644 index 0000000000000000000000000000000000000000..bd40a38eb0502aece19924eeb3b4aab45a8e28f1 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsBarTag.java @@ -0,0 +1,180 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.axis.CategoryAxis; +import com.github.abel533.echarts.axis.ValueAxis; +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; + +public class EChartsBarTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id; + private String title; + private String subtitle; + private String xAxisName; + private String yAxisName; + private List xAxisData; + private Map yAxisIndex; + private Map> yAxisData; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + } catch (IOException e) { + System.err.print(e); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public String getxAxisName() { + return xAxisName; + } + + public void setxAxisName(String xAxisName) { + this.xAxisName = xAxisName; + } + + public String getyAxisName() { + return yAxisName; + } + + public void setyAxisName(String yAxisName) { + this.yAxisName = yAxisName; + } + + public List getxAxisData() { + return xAxisData; + } + + public void setxAxisData(List xAxisData) { + this.xAxisData = xAxisData; + } + + public Map getyAxisIndex() { + return yAxisIndex; + } + + public void setyAxisIndex(Map yAxisIndex) { + this.yAxisIndex = yAxisIndex; + } + + public Map> getyAxisData() { + return yAxisData; + } + + public void setyAxisData(Map> yAxisData) { + this.yAxisData = yAxisData; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineDoubleNumTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineDoubleNumTag.java new file mode 100644 index 0000000000000000000000000000000000000000..11a0ff39c45e7e9501d27432a0911fe8349fd5d6 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineDoubleNumTag.java @@ -0,0 +1,181 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.axis.CategoryAxis; +import com.github.abel533.echarts.axis.ValueAxis; +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; +import com.github.abel533.echarts.style.LineStyle; + +public class EChartsLineDoubleNumTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id; + private String title; + private String subtitle; + private String xAxisName; + private String yAxisName; + private Map yAxisIndex; + private Map axisDataArr; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @SuppressWarnings("unchecked") + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + + } catch (IOException e) { + e.printStackTrace(); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public String getxAxisName() { + return xAxisName; + } + + public void setxAxisName(String xAxisName) { + this.xAxisName = xAxisName; + } + + public String getyAxisName() { + return yAxisName; + } + + public void setyAxisName(String yAxisName) { + this.yAxisName = yAxisName; + } + + public Map getyAxisIndex() { + return yAxisIndex; + } + + public void setyAxisIndex(Map yAxisIndex) { + this.yAxisIndex = yAxisIndex; + } + + public Map getAxisDataArr() { + return axisDataArr; + } + + public void setAxisDataArr(Map axisDataArr) { + this.axisDataArr = axisDataArr; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTag.java new file mode 100644 index 0000000000000000000000000000000000000000..1336b2f49684735e55cf389af4248e5d5be75bbd --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTag.java @@ -0,0 +1,181 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.axis.CategoryAxis; +import com.github.abel533.echarts.axis.ValueAxis; +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; + +public class EChartsLineTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id ; + private String title; + private String subtitle; + private String xAxisName; + private String yAxisName; + private List xAxisData; + private Map yAxisIndex; + private Map> yAxisData; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + } catch (IOException e) { + System.err.print(e); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public String getxAxisName() { + return xAxisName; + } + + public void setxAxisName(String xAxisName) { + this.xAxisName = xAxisName; + } + + public String getyAxisName() { + return yAxisName; + } + + public void setyAxisName(String yAxisName) { + this.yAxisName = yAxisName; + } + + public List getxAxisData() { + return xAxisData; + } + + public void setxAxisData(List xAxisData) { + this.xAxisData = xAxisData; + } + + public Map getyAxisIndex() { + return yAxisIndex; + } + + public void setyAxisIndex(Map yAxisIndex) { + this.yAxisIndex = yAxisIndex; + } + + public Map> getyAxisData() { + return yAxisData; + } + + public void setyAxisData(Map> yAxisData) { + this.yAxisData = yAxisData; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTimeLineTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTimeLineTag.java new file mode 100644 index 0000000000000000000000000000000000000000..134988e2ced3baf767c1aa9f0652bbb9616295ae --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsLineTimeLineTag.java @@ -0,0 +1,282 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.axis.CategoryAxis; +import com.github.abel533.echarts.axis.ValueAxis; +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; + +public class EChartsLineTimeLineTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id; + private String title; + private String subtitle; + private String xAxisName; + private String yAxisName; + private List xAxisData; + private Map yAxisIndex; + private Map> yAxisData; + private List timelineData; + private List>> timelineAxisData; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + + } catch (IOException e) { + System.err.print(e); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public String getxAxisName() { + return xAxisName; + } + + public void setxAxisName(String xAxisName) { + this.xAxisName = xAxisName; + } + + public String getyAxisName() { + return yAxisName; + } + + public void setyAxisName(String yAxisName) { + this.yAxisName = yAxisName; + } + + public List getxAxisData() { + return xAxisData; + } + + public void setxAxisData(List xAxisData) { + this.xAxisData = xAxisData; + } + + public Map getyAxisIndex() { + return yAxisIndex; + } + + public void setyAxisIndex(Map yAxisIndex) { + this.yAxisIndex = yAxisIndex; + } + + public Map> getyAxisData() { + return yAxisData; + } + + public void setyAxisData(Map> yAxisData) { + this.yAxisData = yAxisData; + } + + public List getTimelineData() { + return timelineData; + } + + public void setTimelineData(List timelineData) { + this.timelineData = timelineData; + } + + public List>> getTimelineAxisData() { + return timelineAxisData; + } + + public void setTimelineAxisData( + List>> timelineAxisData) { + this.timelineAxisData = timelineAxisData; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsPieTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsPieTag.java new file mode 100644 index 0000000000000000000000000000000000000000..4bef8471dfaaf66f076b7db0192a26d14da686ea --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsPieTag.java @@ -0,0 +1,121 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.data.Data; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; + +public class EChartsPieTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id; + private String title; + private String subtitle; + private Map orientData; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + } catch (IOException e) { + System.err.print(e); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public Map getOrientData() { + return orientData; + } + + public void setOrientData(Map orientData) { + this.orientData = orientData; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsRadarTag.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsRadarTag.java new file mode 100644 index 0000000000000000000000000000000000000000..411a12bf0c1635e91c5fada30162baeabb16821f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/tag/echarts/EChartsRadarTag.java @@ -0,0 +1,169 @@ +package com.jeespring.common.tag.echarts; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.tagext.BodyTag; +import javax.servlet.jsp.tagext.BodyTagSupport; +import javax.servlet.jsp.tagext.Tag; + +import com.github.abel533.echarts.Polar; +import com.github.abel533.echarts.code.*; +import com.github.abel533.echarts.data.Data; +import com.github.abel533.echarts.feature.MagicType; +import com.github.abel533.echarts.json.GsonOption; +import com.github.abel533.echarts.series.Line; + +public class EChartsRadarTag extends BodyTagSupport { + private static final long serialVersionUID = 1L; + private String id; + private String title; + private String subtitle; + private Integer polarType; + private List> orientData; + + @Override + public int doStartTag() throws JspException { + return BodyTag.EVAL_BODY_BUFFERED; + } + + @Override + public int doEndTag() throws JspException { + StringBuffer sb = new StringBuffer(); + sb.append(""); + try { + this.pageContext.getOut().write(sb.toString()); + + } catch (IOException e) { + e.printStackTrace(); + } + return Tag.EVAL_PAGE;// 继续处理页面 + } + + @Override + public String getId() { + return id; + } + + @Override + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubtitle() { + return subtitle; + } + + public void setSubtitle(String subtitle) { + this.subtitle = subtitle; + } + + public Integer getPolarType() { + return polarType; + } + + public void setPolarType(Integer polarType) { + this.polarType = polarType; + } + + public List> getOrientData() { + return orientData; + } + + public void setOrientData(List> orientData) { + this.orientData = orientData; + } + + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/AddressUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/AddressUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..28fbdf22243175ec345e848518d72b89a623d74b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/AddressUtils.java @@ -0,0 +1,42 @@ +package com.jeespring.common.utils; + +import com.alibaba.fastjson.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.jeespring.common.utils.http.HttpUtils; +import org.springframework.beans.factory.annotation.Value; + +/** + * 获取地址类 + * + * @author JeeSpring + */ +public class AddressUtils +{ + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + + public static final String IP_URL = "http://ip.taobao.com/service/getIpInfo.php"; + /** 获取地址开关 */ + private static boolean addressEnabled=false; + + public static String getRealAddressByIP(String ip) + { + String address = ""; + try + { + if (addressEnabled) { + address = HttpUtils.sendPost(IP_URL, "ip=" + ip); + JSONObject json = JSONObject.parseObject(address); + JSONObject object = json.getObject("data", JSONObject.class); + String region = object.getString("region"); + String city = object.getString("city"); + address = region + " " + city; + } + } + catch (Exception e) + { + log.error("获取地理位置异常:", e.getMessage()); + } + return address; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Base64ImageUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Base64ImageUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..97e9be1d225c303c9522bc844c199440446ecaca --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Base64ImageUtils.java @@ -0,0 +1,99 @@ +package com.jeespring.common.utils; + +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Created by zhangwenchao on 2017/9/29. + * 本地或者网络图片资源转为Base64字符串 + */ +public class Base64ImageUtils { + /** + * @Title: GetImageStrFromUrl + * @Description: 将一张网络图片转化成Base64字符串 + * @param imgURL 网络资源位置 + * @return Base64字符串 + */ + public static String GetImageStrFromUrl(String imgURL) { + byte[] data = null; + try { + // 创建URL + URL url = new URL(imgURL); + // 创建链接 + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(5 * 1000); + InputStream inStream = conn.getInputStream(); + data = new byte[inStream.available()]; + inStream.read(data); + inStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + // 对字节数组Base64编码 + BASE64Encoder encoder = new BASE64Encoder(); + // 返回Base64编码过的字节数组字符串 + return encoder.encode(data); + } + + /** + * @Title: GetImageStrFromPath + * @Description: (将一张本地图片转化成Base64字符串) + * @param imgPath + * @return + */ + public static String GetImageStrFromPath(String imgPath) { + InputStream in = null; + byte[] data = null; + // 读取图片字节数组 + try { + in = new FileInputStream(imgPath); + data = new byte[in.available()]; + in.read(data); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + // 对字节数组Base64编码 + BASE64Encoder encoder = new BASE64Encoder(); + // 返回Base64编码过的字节数组字符串 + return encoder.encode(data); + } + + /** + * @Title: GenerateImage + * @Description: base64字符串转化成图片 + * @param imgStr + * @param imgFilePath 图片文件名,如“E:/tmp.jpg” + * @return + */ + public static boolean saveImage(String imgStr,String imgFilePath) { + if (imgStr == null) // 图像数据为空 + { + return false; + } + BASE64Decoder decoder = new BASE64Decoder(); + try { + // Base64解码 + byte[] b = decoder.decodeBuffer(imgStr); + for (int i = 0; i < b.length; ++i) { + if (b[i] < 0) {// 调整异常数据 + b[i] += 256; + } + } + // 生成jpeg图片 + OutputStream out = new FileOutputStream(imgFilePath); + out.write(b); + out.flush(); + out.close(); + return true; + } catch (Exception e) { + return false; + } + } +} + diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CacheUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CacheUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..9f5f7c776f7f86bdd3c141f0efd049881aaf8dae --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CacheUtils.java @@ -0,0 +1,123 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import org.apache.shiro.cache.Cache; +import org.apache.shiro.cache.CacheManager; + +/** + * Cache工具类 + * + * @author 黄炳桂 516821420@qq.com + * @version 2013-5-29 + */ +public class CacheUtils { + + private static CacheManager cacheManager = SpringContextHolder.getBean(CacheManager.class); + + private static final String SYS_CACHE = "sysCache"; + + /** + * 获取SYS_CACHE缓存 + * + * @param key + * @return + */ + public static Object get(String key) { + return get(SYS_CACHE, key); + } + + /** + * 获取SYS_CACHE缓存 + * + * @param key + * @param defaultValue + * @return + */ + public static Object get(String key, Object defaultValue) { + Object value = get(key); + return value != null ? value : defaultValue; + } + + /** + * 写入SYS_CACHE缓存 + * + * @param key + * @return + */ + public static void put(String key, Object value) { + put(SYS_CACHE, key, value); + } + + /** + * 从SYS_CACHE缓存中移除 + * + * @param key + * @return + */ + public static void remove(String key) { + remove(SYS_CACHE, key); + } + + /** + * 获取缓存 + * + * @param cacheName + * @param key + * @return + */ + public static Object get(String cacheName, String key) { + return getCache(cacheName).get(key); + } + + /** + * 获取缓存 + * + * @param cacheName + * @param key + * @param defaultValue + * @return + */ + public static Object get(String cacheName, String key, Object defaultValue) { + Object value = get(cacheName, key); + return value != null ? value : defaultValue; + } + + /** + * 写入缓存 + * + * @param cacheName + * @param key + * @param value + */ + public static void put(String cacheName, String key, Object value) { + getCache(cacheName).put(key, value); + } + + /** + * 从缓存中移除 + * + * @param cacheName + * @param key + */ + public static void remove(String cacheName, String key) { + getCache(cacheName).remove(key); + } + + + /** + * 获得一个Cache,没有则显示日志。 + * + * @param cacheName + * @return + */ + private static Cache getCache(String cacheName) { + Cache cache = cacheManager.getCache(cacheName); + if (cache == null) { + throw new RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。"); + } + return cache; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CharsetKit.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CharsetKit.java new file mode 100644 index 0000000000000000000000000000000000000000..a6f00cbd12aa42a2da8967d8fd23d34de2f2af1d --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CharsetKit.java @@ -0,0 +1,87 @@ +package com.jeespring.common.utils; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * 字符集工具类 + * + * @author JeeSpring + * + */ +public class CharsetKit +{ + /** ISO-8859-1 */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** UTF-8 */ + public static final String UTF_8 = "UTF-8"; + /** GBK */ + public static final String GBK = "GBK"; + + /** ISO-8859-1 */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** GBK */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转换为Charset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) + { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) + { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) + { + if (null == srcCharset) + { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) + { + srcCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) + { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return 系统字符集编码 + */ + public static String systemCharset() + { + return Charset.defaultCharset().name(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Collections3.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Collections3.java new file mode 100644 index 0000000000000000000000000000000000000000..8d524dfe90b6fcc22d36398f517b78ee33460696 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Collections3.java @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang3.StringUtils; + +/** + * Collections工具集. + * 在JDK的Collections和Guava的Collections2后, 命名为Collections3. + * @author calvin + * @version 2013-01-15 + */ +@SuppressWarnings("rawtypes") +public class Collections3 { + + /** + * 提取集合中的对象的两个属性(通过Getter函数), 组合成Map. + * + * @param collection 来源集合. + * @param keyPropertyName 要提取为Map中的Key值的属性名. + * @param valuePropertyName 要提取为Map中的Value值的属性名. + */ + @SuppressWarnings("unchecked") + public static Map extractToMap(final Collection collection, final String keyPropertyName, + final String valuePropertyName) { + Map map = new HashMap(collection.size()); + + try { + for (Object obj : collection) { + map.put(PropertyUtils.getProperty(obj, keyPropertyName), + PropertyUtils.getProperty(obj, valuePropertyName)); + } + } catch (Exception e) { + throw Reflections.convertReflectionExceptionToUnchecked(e); + } + + return map; + } + + /** + * 提取集合中的对象的一个属性(通过Getter函数), 组合成List. + * + * @param collection 来源集合. + * @param propertyName 要提取的属性名. + */ + @SuppressWarnings("unchecked") + public static List extractToList(final Collection collection, final String propertyName) { + List list = new ArrayList(collection.size()); + + try { + for (Object obj : collection) { + list.add(PropertyUtils.getProperty(obj, propertyName)); + } + } catch (Exception e) { + throw Reflections.convertReflectionExceptionToUnchecked(e); + } + + return list; + } + + /** + * 提取集合中的对象的一个属性(通过Getter函数), 组合成由分割符分隔的字符串. + * + * @param collection 来源集合. + * @param propertyName 要提取的属性名. + * @param separator 分隔符. + */ + public static String extractToString(final Collection collection, final String propertyName, final String separator) { + List list = extractToList(collection, propertyName); + return StringUtils.join(list, separator); + } + + /** + * 转换Collection所有元素(通过toString())为String, 中间以 separator分隔。 + */ + public static String convertToString(final Collection collection, final String separator) { + return StringUtils.join(collection, separator); + } + + /** + * 转换Collection所有元素(通过toString())为String, 每个元素的前面加入prefix,后面加入postfix,如mymessage。 + */ + public static String convertToString(final Collection collection, final String prefix, final String postfix) { + StringBuilder builder = new StringBuilder(); + for (Object o : collection) { + builder.append(prefix).append(o).append(postfix); + } + return builder.toString(); + } + + /** + * 判断是否为空. + */ + public static boolean isEmpty(Collection collection) { + return (collection == null || collection.isEmpty()); + } + + /** + * 取得Collection的第一个元素,如果collection为空返回null. + */ + public static T getFirst(Collection collection) { + if (isEmpty(collection)) { + return null; + } + + return collection.iterator().next(); + } + + /** + * 获取Collection的最后一个元素 ,如果collection为空返回null. + */ + public static T getLast(Collection collection) { + if (isEmpty(collection)) { + return null; + } + + //当类型为List时,直接取得最后一个元素 。 + if (collection instanceof List) { + List list = (List) collection; + return list.get(list.size() - 1); + } + + //其他类型通过iterator滚动到最后一个元素. + Iterator iterator = collection.iterator(); + while (true) { + T current = iterator.next(); + if (!iterator.hasNext()) { + return current; + } + } + } + + /** + * 返回a+b的新List. + */ + public static List union(final Collection a, final Collection b) { + List result = new ArrayList(a); + result.addAll(b); + return result; + } + + /** + * 返回a-b的新List. + */ + public static List subtract(final Collection a, final Collection b) { + List list = new ArrayList(a); + for (T element : b) { + list.remove(element); + } + + return list; + } + + /** + * 返回a与b的交集的新List. + */ + public static List intersection(Collection a, Collection b) { + List list = new ArrayList(); + + for (T element : a) { + if (b.contains(element)) { + list.add(element); + } + } + return list; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Convert.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Convert.java new file mode 100644 index 0000000000000000000000000000000000000000..8fdff7ecf849c175005ecdd40eca33440b4cbfc4 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Convert.java @@ -0,0 +1,1001 @@ +package com.jeespring.common.utils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author JeeSpring + * + */ +public class Convert +{ + /** + * 转换为字符串 + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串 + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符 + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符 + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为byte + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short + * 如果给定的值为null,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Short + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Number + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为int + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组 + * + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组 + * + * @param split 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组 + * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组 + * + * @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null + * @param values 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组 + * + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组 + * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long + * 如果给定的值为null,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean + * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + return true; + case "false": + return false; + case "yes": + return true; + case "ok": + return true; + case "no": + return false; + case "1": + return true; + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象 + * 如果给定的值为空,或者转换失败,返回默认值 + * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象 + * 如果给定的值为空,或者转换失败,返回默认值null + * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger + * 如果给定的值为空,或者转换失败,返回默认值null + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return new BigDecimal((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal + * 如果给定的值为空,或者转换失败,返回默认值 + * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串 + * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[] || obj instanceof Byte[]) + { + return str((Byte[]) obj, charset); + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "角", "分" }; + String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; + String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) + { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", + "零元整"); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CookieUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CookieUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e79936f18a08495fb779e7c1ed2acfbec5b33608 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/CookieUtils.java @@ -0,0 +1,115 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Cookie工具类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-01-15 + */ +public class CookieUtils { + + /** + * 设置 Cookie(生成时间为1天) + * @param name 名称 + * @param value 值 + */ + public static void setCookie(HttpServletResponse response, String name, String value) { + setCookie(response, name, value, 60*60*24); + } + + /** + * 设置 Cookie + * @param name 名称 + * @param value 值 + * @param maxAge 生存时间(单位秒) + * @param uri 路径 + */ + public static void setCookie(HttpServletResponse response, String name, String value, String path) { + setCookie(response, name, value, path, 60*60*24); + } + + /** + * 设置 Cookie + * @param name 名称 + * @param value 值 + * @param maxAge 生存时间(单位秒) + * @param uri 路径 + */ + public static void setCookie(HttpServletResponse response, String name, String value, int maxAge) { + setCookie(response, name, value, "/", maxAge); + } + + /** + * 设置 Cookie + * @param name 名称 + * @param value 值 + * @param maxAge 生存时间(单位秒) + * @param uri 路径 + */ + public static void setCookie(HttpServletResponse response, String name, String value, String path, int maxAge) { + Cookie cookie = new Cookie(name, null); + cookie.setPath(path); + cookie.setMaxAge(maxAge); + try { + cookie.setValue(URLEncoder.encode(value, "utf-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + response.addCookie(cookie); + } + + /** + * 获得指定Cookie的值 + * @param name 名称 + * @return 值 + */ + public static String getCookie(HttpServletRequest request, String name) { + return getCookie(request, null, name, false); + } + /** + * 获得指定Cookie的值,并删除。 + * @param name 名称 + * @return 值 + */ + public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name) { + return getCookie(request, response, name, true); + } + /** + * 获得指定Cookie的值 + * @param request 请求对象 + * @param response 响应对象 + * @param name 名字 + * @param isRemove 是否移除 + * @return 值 + */ + public static String getCookie(HttpServletRequest request, HttpServletResponse response, String name, boolean isRemove) { + String value = null; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(name)) { + try { + value = URLDecoder.decode(cookie.getValue(), "utf-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + if (isRemove) { + cookie.setMaxAge(0); + response.addCookie(cookie); + } + } + } + } + return value; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/DateUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/DateUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..2ac686015270477051e18f1ffa10c67239c64c7a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/DateUtils.java @@ -0,0 +1,183 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.text.ParseException; +import java.util.Date; + +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 日期工具类, 继承org.apache.commons.lang.time.DateUtils类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-4-15 + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils { + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 得到当前日期字符串 格式(yyyy-MM-dd) + */ + public static String getDate() { + return getDate("yyyy-MM-dd"); + } + + /** + * 得到当前日期字符串 格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" + */ + public static String getDate(String pattern) { + return DateFormatUtils.format(new Date(), pattern); + } + + /** + * 得到日期字符串 默认格式(yyyy-MM-dd) pattern可以为:"yyyy-MM-dd" "HH:mm:ss" "E" + */ + public static String formatDate(Date date, Object... pattern) { + String formatDate = null; + if (pattern != null && pattern.length > 0) { + formatDate = DateFormatUtils.format(date, pattern[0].toString()); + } else { + formatDate = DateFormatUtils.format(date, "yyyy-MM-dd"); + } + return formatDate; + } + + /** + * 得到日期时间字符串,转换格式(yyyy-MM-dd HH:mm:ss) + */ + public static String formatDateTime(Date date) { + return formatDate(date, "yyyy-MM-dd HH:mm:ss"); + } + + /** + * 得到当前时间字符串 格式(HH:mm:ss) + */ + public static String getTime() { + return formatDate(new Date(), "HH:mm:ss"); + } + + /** + * 得到当前日期和时间字符串 格式(yyyy-MM-dd HH:mm:ss) + */ + public static String getDateTime() { + return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"); + } + + /** + * 得到当前年份字符串 格式(yyyy) + */ + public static String getYear() { + return formatDate(new Date(), "yyyy"); + } + + /** + * 得到当前月份字符串 格式(MM) + */ + public static String getMonth() { + return formatDate(new Date(), "MM"); + } + + /** + * 得到当天字符串 格式(dd) + */ + public static String getDay() { + return formatDate(new Date(), "dd"); + } + + /** + * 得到当前星期字符串 格式(E)星期几 + */ + public static String getWeek() { + return formatDate(new Date(), "E"); + } + + /** + * 日期型字符串转化为日期 格式 + * { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", + * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", + * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm" } + */ + public static Date parseDate(Object str) { + if (str == null){ + return null; + } + try { + return parseDate(str.toString(), parsePatterns); + } catch (ParseException e) { + return null; + } + } + + /** + * 获取过去的天数 + * @param date + * @return + */ + public static long pastDays(Date date) { + long t = new Date().getTime()-date.getTime(); + return t/(24*60*60*1000); + } + + /** + * 获取过去的小时 + * @param date + * @return + */ + public static long pastHour(Date date) { + long t = new Date().getTime()-date.getTime(); + return t/(60*60*1000); + } + + /** + * 获取过去的分钟 + * @param date + * @return + */ + public static long pastMinutes(Date date) { + long t = new Date().getTime()-date.getTime(); + return t/(60*1000); + } + + /** + * 转换为时间(天,时:分:秒.毫秒) + * @param timeMillis + * @return + */ + public static String formatDateTime(long timeMillis){ + long day = timeMillis/(24*60*60*1000); + long hour = (timeMillis/(60*60*1000)-day*24); + long min = ((timeMillis/(60*1000))-day*24*60-hour*60); + long s = (timeMillis/1000-day*24*60*60-hour*60*60-min*60); + long sss = (timeMillis-day*24*60*60*1000-hour*60*60*1000-min*60*1000-s*1000); + return (day>0?day+",":"")+hour+":"+min+":"+s+"."+sss; + } + + /** + * 获取两个日期之间的天数 + * + * @param before + * @param after + * @return + */ + public static double getDistanceOfTwoDate(Date before, Date after) { + long beforeTime = before.getTime(); + long afterTime = after.getTime(); + return (afterTime - beforeTime) / (1000 * 60 * 60 * 24); + } + + /** + * @param args + * @throws ParseException + */ +// public static void main(String[] args) throws ParseException { +// System.out.println(formatDate(parseDate("2010/3/6"))); +// System.out.println(getDate("yyyy年MM月dd日 E")); +// long time = new Date().getTime()-parseDate("2012-11-19").getTime(); +// System.out.println(time/(24*60*60*1000)); +// } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Encodes.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Encodes.java new file mode 100644 index 0000000000000000000000000000000000000000..c0054439efe144ecd1df0bf1f1af70310c96c2d3 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Encodes.java @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.lang3.StringEscapeUtils; + +/** + * 封装各种格式的编码解码工具类. + * 1.Commons-Codec的 hex/base64 编码 + * 2.自制的base62 编码 + * 3.Commons-Lang的xml/html escape + * 4.JDK提供的URLEncoder + * @author calvin + * @version 2013-01-15 + */ +public class Encodes { + + private static final String DEFAULT_URL_ENCODING = "UTF-8"; + private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray(); + + /** + * Hex编码. + */ + public static String encodeHex(byte[] input) { + return new String(Hex.encodeHex(input)); + } + + /** + * Hex解码. + */ + public static byte[] decodeHex(String input) { + try { + return Hex.decodeHex(input.toCharArray()); + } catch (DecoderException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * Base64编码. + */ + public static String encodeBase64(byte[] input) { + return new String(Base64.encodeBase64(input)); + } + + /** + * Base64编码. + */ + public static String encodeBase64(String input) { + try { + return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING))); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + +// /** +// * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548). +// */ +// public static String encodeUrlSafeBase64(byte[] input) { +// return Base64.encodeBase64URLSafe(input); +// } + + /** + * Base64解码. + */ + public static byte[] decodeBase64(String input) { + return Base64.decodeBase64(input.getBytes()); + } + + /** + * Base64解码. + */ + public static String decodeBase64String(String input) { + try { + return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING); + } catch (UnsupportedEncodingException e) { + return ""; + } + } + + /** + * Base62编码。 + */ + public static String encodeBase62(byte[] input) { + char[] chars = new char[input.length]; + for (int i = 0; i < input.length; i++) { + chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)]; + } + return new String(chars); + } + + /** + * Html 转码. + */ + public static String escapeHtml(String html) { + return StringEscapeUtils.escapeHtml4(html); + } + + /** + * Html 解码. + */ + public static String unescapeHtml(String htmlEscaped) { + return StringEscapeUtils.unescapeHtml4(htmlEscaped); + } + + /** + * Xml 转码. + */ + public static String escapeXml(String xml) { + return StringEscapeUtils.escapeXml10(xml); + } + + /** + * Xml 解码. + */ + public static String unescapeXml(String xmlEscaped) { + return StringEscapeUtils.unescapeXml(xmlEscaped); + } + + /** + * URL 编码, Encode默认为UTF-8. + */ + public static String urlEncode(String part) { + try { + return URLEncoder.encode(part, DEFAULT_URL_ENCODING); + } catch (UnsupportedEncodingException e) { + throw Exceptions.unchecked(e); + } + } + + /** + * URL 解码, Encode默认为UTF-8. + */ + public static String urlDecode(String part) { + + try { + return URLDecoder.decode(part, DEFAULT_URL_ENCODING); + } catch (UnsupportedEncodingException e) { + throw Exceptions.unchecked(e); + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Exceptions.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Exceptions.java new file mode 100644 index 0000000000000000000000000000000000000000..160a3af43bf68b08ac902c61b2b3c91564997c29 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Exceptions.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; + +/** + * 关于异常的工具类. + * + * @author calvin + * @version 2013-01-15 + */ +public class Exceptions { + + /** + * 将CheckedException转换为UncheckedException. + */ + public static RuntimeException unchecked(Exception e) { + if (e instanceof RuntimeException) { + return RuntimeException.class.cast(e); + } else { + return new RuntimeException(e); + } + } + + /** + * 将ErrorStack转化为String. + */ + public static String getStackTraceAsString(Throwable e) { + if (e == null) { + return ""; + } + StringWriter stringWriter = new StringWriter(); + e.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } + + /** + * 判断异常是否由某些底层的异常引起. + */ + @SuppressWarnings("unchecked") + public static boolean isCausedBy(Exception ex, Class extends Exception>... causeExceptionClasses) { + Throwable cause = ex.getCause(); + while (cause != null) { + for (Class extends Exception> causeClass : causeExceptionClasses) { + if (causeClass.isInstance(cause)) { + return true; + } + } + cause = cause.getCause(); + } + return false; + } + + /** + * 在request中获取异常类 + * + * @param request + * @return + */ + public static Throwable getThrowable(HttpServletRequest request) { + Throwable ex = null; + try { + if (request.getAttribute("exception") != null) { + ex = Throwable.class.cast(request.getAttribute("exception")); + } else if (request.getAttribute("javax.servlet.error.exception") != null) { + ex = Throwable.class.cast(request.getAttribute("javax.servlet.error.exception")); + } + } catch (Exception e) { + e.printStackTrace(); + } + return ex; + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileSizeHelper.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileSizeHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..471fd2b1079f378325444d97cf16babc3a270904 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileSizeHelper.java @@ -0,0 +1,68 @@ +package com.jeespring.common.utils; + +import java.text.DecimalFormat; + +/** + * + * 文件大小工具类. + * + * + * @author poplar.yfyang + * @version 1.0 2013-01-02 12:50 PM + * @since JDK 1.5 + */ +public class FileSizeHelper { + public static long ONE_KB = 1024; + public static long ONE_MB = ONE_KB * 1024; + public static long ONE_GB = ONE_MB * 1024; + public static long ONE_TB = ONE_GB * (long)1024; + public static long ONE_PB = ONE_TB * (long)1024; + + public static String getHumanReadableFileSize(Long fileSize) { + if(fileSize == null) { + return null; + } + return getHumanReadableFileSize(fileSize.longValue()); + } + + public static String getHumanReadableFileSize(long fileSize) { + if(fileSize < 0) { + return String.valueOf(fileSize); + } + String result = getHumanReadableFileSize(fileSize, ONE_PB, "PB"); + if(result != null) { + return result; + } + + result = getHumanReadableFileSize(fileSize, ONE_TB, "TB"); + if(result != null) { + return result; + } + result = getHumanReadableFileSize(fileSize, ONE_GB, "GB"); + if(result != null) { + return result; + } + result = getHumanReadableFileSize(fileSize, ONE_MB, "MB"); + if(result != null) { + return result; + } + result = getHumanReadableFileSize(fileSize, ONE_KB, "KB"); + if(result != null) { + return result; + } + return String.valueOf(fileSize)+"B"; + } + + private static String getHumanReadableFileSize(long fileSize, long unit, String unitName) { + if(fileSize == 0) { + return "0"; + } + + if(fileSize / unit >= 1) { + double value = fileSize / (double)unit; + DecimalFormat df = new DecimalFormat("######.##"+unitName); + return df.format(value); + } + return null; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtil.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..b6e482b5e5f3d29abb055ba823a487ef39287826 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtil.java @@ -0,0 +1,72 @@ +package com.jeespring.common.utils; + +import java.io.*; + +/** + * 文件读取工具类 + */ +public class FileUtil { + + /** + * 读取文件内容,作为字符串返回 + */ + public static String readFileAsString(String filePath) throws IOException { + File file = new File(filePath); + if (!file.exists()) { + throw new FileNotFoundException(filePath); + } + + if (file.length() > 1024 * 1024 * 1024) { + throw new IOException("File is too large"); + } + + StringBuilder sb = new StringBuilder((int) (file.length())); + // 创建字节输入流 + FileInputStream fis = new FileInputStream(filePath); + // 创建一个长度为10240的Buffer + byte[] bbuf = new byte[10240]; + // 用于保存实际读取的字节数 + int hasRead = 0; + while ((hasRead = fis.read(bbuf)) > 0) { + sb.append(new String(bbuf, 0, hasRead)); + } + fis.close(); + return sb.toString(); + } + + /** + * 根据文件路径读取byte[] 数组 + */ + public static byte[] readFileByBytes(String filePath) throws IOException { + File file = new File(filePath); + if (!file.exists()) { + throw new FileNotFoundException(filePath); + } else { + ByteArrayOutputStream bos = new ByteArrayOutputStream((int) file.length()); + BufferedInputStream in = null; + + try { + in = new BufferedInputStream(new FileInputStream(file)); + short bufSize = 1024; + byte[] buffer = new byte[bufSize]; + int len1; + while (-1 != (len1 = in.read(buffer, 0, bufSize))) { + bos.write(buffer, 0, len1); + } + + byte[] var7 = bos.toByteArray(); + return var7; + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException var14) { + var14.printStackTrace(); + } + + bos.close(); + } + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..b59645054f84cb0599d8c8232263234dc9b0d4bd --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FileUtils.java @@ -0,0 +1,969 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.util.Enumeration; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.tools.zip.ZipEntry; +import org.apache.tools.zip.ZipFile; +import org.apache.tools.zip.ZipOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.Lists; + +/** + * 文件操作工具类 + * 实现文件的创建、删除、复制、压缩、解压以及目录的创建、删除、复制、压缩解压等功能 + * @author 黄炳桂 516821420@qq.com + * @version 2015-3-16 + */ +public class FileUtils extends org.apache.commons.io.FileUtils { + + private static Logger logger = LoggerFactory.getLogger(FileUtils.class); + + /** + * 复制单个文件,如果目标文件存在,则不覆盖 + * @param srcFileName 待复制的文件名 + * @param descFileName 目标文件名 + * @return 如果复制成功,则返回true,否则返回false + */ + public static boolean copyFile(String srcFileName, String descFileName) { + return FileUtils.copyFileCover(srcFileName, descFileName, false); + } + + /** + * 复制单个文件 + * @param srcFileName 待复制的文件名 + * @param descFileName 目标文件名 + * @param coverlay 如果目标文件已存在,是否覆盖 + * @return 如果复制成功,则返回true,否则返回false + */ + public static boolean copyFileCover(String srcFileName, + String descFileName, boolean coverlay) { + File srcFile = new File(srcFileName); + // 判断源文件是否存在 + if (!srcFile.exists()) { + logger.debug("复制文件失败,源文件 " + srcFileName + " 不存在!"); + return false; + } + // 判断源文件是否是合法的文件 + else if (!srcFile.isFile()) { + logger.debug("复制文件失败," + srcFileName + " 不是一个文件!"); + return false; + } + File descFile = new File(descFileName); + // 判断目标文件是否存在 + if (descFile.exists()) { + // 如果目标文件存在,并且允许覆盖 + if (coverlay) { + logger.debug("目标文件已存在,准备删除!"); + if (!FileUtils.delFile(descFileName)) { + logger.debug("删除目标文件 " + descFileName + " 失败!"); + return false; + } + } else { + logger.debug("复制文件失败,目标文件 " + descFileName + " 已存在!"); + return false; + } + } else { + if (!descFile.getParentFile().exists()) { + // 如果目标文件所在的目录不存在,则创建目录 + logger.debug("目标文件所在的目录不存在,创建目录!"); + // 创建目标文件所在的目录 + if (!descFile.getParentFile().mkdirs()) { + logger.debug("创建目标文件所在的目录失败!"); + return false; + } + } + } + + // 准备复制文件 + // 读取的位数 + int readByte = 0; + InputStream ins = null; + OutputStream outs = null; + try { + // 打开源文件 + ins = new FileInputStream(srcFile); + // 打开目标文件的输出流 + outs = new FileOutputStream(descFile); + byte[] buf = new byte[1024]; + // 一次读取1024个字节,当readByte为-1时表示文件已经读取完毕 + while ((readByte = ins.read(buf)) != -1) { + // 将读取的字节流写入到输出流 + outs.write(buf, 0, readByte); + } + logger.debug("复制单个文件 " + srcFileName + " 到" + descFileName + + "成功!"); + return true; + } catch (Exception e) { + logger.debug("复制文件失败:" + e.getMessage()); + return false; + } finally { + // 关闭输入输出流,首先关闭输出流,然后再关闭输入流 + if (outs != null) { + try { + outs.close(); + } catch (IOException oute) { + oute.printStackTrace(); + } + } + if (ins != null) { + try { + ins.close(); + } catch (IOException ine) { + ine.printStackTrace(); + } + } + } + } + + /** + * 复制整个目录的内容,如果目标目录存在,则不覆盖 + * @param srcDirName 源目录名 + * @param descDirName 目标目录名 + * @return 如果复制成功返回true,否则返回false + */ + public static boolean copyDirectory(String srcDirName, String descDirName) { + return FileUtils.copyDirectoryCover(srcDirName, descDirName, + false); + } + + /** + * 复制整个目录的内容 + * @param srcDirName 源目录名 + * @param descDirName 目标目录名 + * @param coverlay 如果目标目录存在,是否覆盖 + * @return 如果复制成功返回true,否则返回false + */ + public static boolean copyDirectoryCover(String srcDirName, + String descDirName, boolean coverlay) { + File srcDir = new File(srcDirName); + // 判断源目录是否存在 + if (!srcDir.exists()) { + logger.debug("复制目录失败,源目录 " + srcDirName + " 不存在!"); + return false; + } + // 判断源目录是否是目录 + else if (!srcDir.isDirectory()) { + logger.debug("复制目录失败," + srcDirName + " 不是一个目录!"); + return false; + } + // 如果目标文件夹名不以文件分隔符结尾,自动添加文件分隔符 + String descDirNames = descDirName; + if (!descDirNames.endsWith(File.separator)) { + descDirNames = descDirNames + File.separator; + } + File descDir = new File(descDirNames); + // 如果目标文件夹存在 + if (descDir.exists()) { + if (coverlay) { + // 允许覆盖目标目录 + logger.debug("目标目录已存在,准备删除!"); + if (!FileUtils.delFile(descDirNames)) { + logger.debug("删除目录 " + descDirNames + " 失败!"); + return false; + } + } else { + logger.debug("目标目录复制失败,目标目录 " + descDirNames + " 已存在!"); + return false; + } + } else { + // 创建目标目录 + logger.debug("目标目录不存在,准备创建!"); + if (!descDir.mkdirs()) { + logger.debug("创建目标目录失败!"); + return false; + } + + } + + boolean flag = true; + // 列出源目录下的所有文件名和子目录名 + File[] files = srcDir.listFiles(); + for (int i = 0; i < files.length; i++) { + // 如果是一个单个文件,则直接复制 + if (files[i].isFile()) { + flag = FileUtils.copyFile(files[i].getAbsolutePath(), + descDirName + files[i].getName()); + // 如果拷贝文件失败,则退出循环 + if (!flag) { + break; + } + } + // 如果是子目录,则继续复制目录 + if (files[i].isDirectory()) { + flag = FileUtils.copyDirectory(files[i] + .getAbsolutePath(), descDirName + files[i].getName()); + // 如果拷贝目录失败,则退出循环 + if (!flag) { + break; + } + } + } + + if (!flag) { + logger.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 失败!"); + return false; + } + logger.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 成功!"); + return true; + + } + + /** + * + * 删除文件,可以删除单个文件或文件夹 + * + * @param fileName 被删除的文件名 + * @return 如果删除成功,则返回true,否是返回false + */ + public static boolean delFile(String fileName) { + File file = new File(fileName); + if (!file.exists()) { + logger.debug(fileName + " 文件不存在!"); + return true; + } else { + if (file.isFile()) { + return FileUtils.deleteFile(fileName); + } else { + return FileUtils.deleteDirectory(fileName); + } + } + } + + /** + * + * 删除单个文件 + * + * @param fileName 被删除的文件名 + * @return 如果删除成功,则返回true,否则返回false + */ + public static boolean deleteFile(String fileName) { + File file = new File(fileName); + if (file.exists() && file.isFile()) { + if (file.delete()) { + logger.debug("删除文件 " + fileName + " 成功!"); + return true; + } else { + logger.debug("删除文件 " + fileName + " 失败!"); + return false; + } + } else { + logger.debug(fileName + " 文件不存在!"); + return true; + } + } + + /** + * + * 删除目录及目录下的文件 + * + * @param dirName 被删除的目录所在的文件路径 + * @return 如果目录删除成功,则返回true,否则返回false + */ + public static boolean deleteDirectory(String dirName) { + String dirNames = dirName; + if (!dirNames.endsWith(File.separator)) { + dirNames = dirNames + File.separator; + } + File dirFile = new File(dirNames); + if (!dirFile.exists() || !dirFile.isDirectory()) { + logger.debug(dirNames + " 目录不存在!"); + return true; + } + boolean flag = true; + // 列出全部文件及子目录 + File[] files = dirFile.listFiles(); + for (int i = 0; i < files.length; i++) { + // 删除子文件 + if (files[i].isFile()) { + flag = FileUtils.deleteFile(files[i].getAbsolutePath()); + // 如果删除文件失败,则退出循环 + if (!flag) { + break; + } + } + // 删除子目录 + else if (files[i].isDirectory()) { + flag = FileUtils.deleteDirectory(files[i] + .getAbsolutePath()); + // 如果删除子目录失败,则退出循环 + if (!flag) { + break; + } + } + } + + if (!flag) { + logger.debug("删除目录失败!"); + return false; + } + // 删除当前目录 + if (dirFile.delete()) { + logger.debug("删除目录 " + dirName + " 成功!"); + return true; + } else { + logger.debug("删除目录 " + dirName + " 失败!"); + return false; + } + + } + + /** + * 创建单个文件 + * @param descFileName 文件名,包含路径 + * @return 如果创建成功,则返回true,否则返回false + */ + public static boolean createFile(String descFileName) { + File file = new File(descFileName); + if (file.exists()) { + logger.debug("文件 " + descFileName + " 已存在!"); + return false; + } + if (descFileName.endsWith(File.separator)) { + logger.debug(descFileName + " 为目录,不能创建目录!"); + return false; + } + if (!file.getParentFile().exists()) { + // 如果文件所在的目录不存在,则创建目录 + if (!file.getParentFile().mkdirs()) { + logger.debug("创建文件所在的目录失败!"); + return false; + } + } + + // 创建文件 + try { + if (file.createNewFile()) { + logger.debug(descFileName + " 文件创建成功!"); + return true; + } else { + logger.debug(descFileName + " 文件创建失败!"); + return false; + } + } catch (Exception e) { + e.printStackTrace(); + logger.debug(descFileName + " 文件创建失败!"); + return false; + } + + } + + /** + * 创建目录 + * @param descDirName 目录名,包含路径 + * @return 如果创建成功,则返回true,否则返回false + */ + public static boolean createDirectory(String descDirName) { + String descDirNames = descDirName; + if (!descDirNames.endsWith(File.separator)) { + descDirNames = descDirNames + File.separator; + } + File descDir = new File(descDirNames); + if (descDir.exists()) { + logger.debug("目录 " + descDirNames + " 已存在!"); + return false; + } + // 创建目录 + if (descDir.mkdirs()) { + logger.debug("目录 " + descDirNames + " 创建成功!"); + return true; + } else { + logger.debug("目录 " + descDirNames + " 创建失败!"); + return false; + } + + } + + /** + * 写入文件 + * @param file 要写入的文件 + */ + public static void writeToFile(String fileName, String content, boolean append) { + try { + FileUtils.write(new File(fileName), content, "utf-8", append); + logger.debug("文件 " + fileName + " 写入成功!"); + } catch (IOException e) { + logger.debug("文件 " + fileName + " 写入失败! " + e.getMessage()); + } + } + + /** + * 写入文件 + * @param file 要写入的文件 + */ + public static void writeToFile(String fileName, String content, String encoding, boolean append) { + try { + FileUtils.write(new File(fileName), content, encoding, append); + logger.debug("文件 " + fileName + " 写入成功!"); + } catch (IOException e) { + logger.debug("文件 " + fileName + " 写入失败! " + e.getMessage()); + } + } + + /** + * 压缩文件或目录 + * @param srcDirName 压缩的根目录 + * @param fileName 根目录下的待压缩的文件名或文件夹名,其中*或""表示跟目录下的全部文件 + * @param descFileName 目标zip文件 + */ + public static void zipFiles(String srcDirName, String fileName, + String descFileName) { + // 判断目录是否存在 + if (srcDirName == null) { + logger.debug("文件压缩失败,目录 " + srcDirName + " 不存在!"); + return; + } + File fileDir = new File(srcDirName); + if (!fileDir.exists() || !fileDir.isDirectory()) { + logger.debug("文件压缩失败,目录 " + srcDirName + " 不存在!"); + return; + } + String dirPath = fileDir.getAbsolutePath(); + File descFile = new File(descFileName); + try { + ZipOutputStream zouts = new ZipOutputStream(new FileOutputStream( + descFile)); + if ("*".equals(fileName) || "".equals(fileName)) { + FileUtils.zipDirectoryToZipFile(dirPath, fileDir, zouts); + } else { + File file = new File(fileDir, fileName); + if (file.isFile()) { + FileUtils.zipFilesToZipFile(dirPath, file, zouts); + } else { + FileUtils + .zipDirectoryToZipFile(dirPath, file, zouts); + } + } + zouts.close(); + logger.debug(descFileName + " 文件压缩成功!"); + } catch (Exception e) { + logger.debug("文件压缩失败:" + e.getMessage()); + e.printStackTrace(); + } + + } + + /** + * 解压缩ZIP文件,将ZIP文件里的内容解压到descFileName目录下 + * @param zipFileName 需要解压的ZIP文件 + * @param descFileName 目标文件 + */ + public static boolean unZipFiles(String zipFileName, String descFileName) { + String descFileNames = descFileName; + if (!descFileNames.endsWith(File.separator)) { + descFileNames = descFileNames + File.separator; + } + try { + // 根据ZIP文件创建ZipFile对象 + ZipFile zipFile = new ZipFile(zipFileName); + ZipEntry entry = null; + String entryName = null; + String descFileDir = null; + byte[] buf = new byte[4096]; + int readByte = 0; + // 获取ZIP文件里所有的entry + @SuppressWarnings("rawtypes") + Enumeration enums = zipFile.getEntries(); + // 遍历所有entry + while (enums.hasMoreElements()) { + entry = (ZipEntry) enums.nextElement(); + // 获得entry的名字 + entryName = entry.getName(); + descFileDir = descFileNames + entryName; + if (entry.isDirectory()) { + // 如果entry是一个目录,则创建目录 + new File(descFileDir).mkdirs(); + continue; + } else { + // 如果entry是一个文件,则创建父目录 + new File(descFileDir).getParentFile().mkdirs(); + } + File file = new File(descFileDir); + // 打开文件输出流 + OutputStream os = new FileOutputStream(file); + // 从ZipFile对象中打开entry的输入流 + InputStream is = zipFile.getInputStream(entry); + while ((readByte = is.read(buf)) != -1) { + os.write(buf, 0, readByte); + } + os.close(); + is.close(); + } + zipFile.close(); + logger.debug("文件解压成功!"); + return true; + } catch (Exception e) { + logger.debug("文件解压失败:" + e.getMessage()); + return false; + } + } + + /** + * 将目录压缩到ZIP输出流 + * @param dirPath 目录路径 + * @param fileDir 文件信息 + * @param zouts 输出流 + */ + public static void zipDirectoryToZipFile(String dirPath, File fileDir, ZipOutputStream zouts) { + if (fileDir.isDirectory()) { + File[] files = fileDir.listFiles(); + // 空的文件夹 + if (files.length == 0) { + // 目录信息 + ZipEntry entry = new ZipEntry(getEntryName(dirPath, fileDir)); + try { + zouts.putNextEntry(entry); + zouts.closeEntry(); + } catch (Exception e) { + e.printStackTrace(); + } + return; + } + + for (int i = 0; i < files.length; i++) { + if (files[i].isFile()) { + // 如果是文件,则调用文件压缩方法 + FileUtils + .zipFilesToZipFile(dirPath, files[i], zouts); + } else { + // 如果是目录,则递归调用 + FileUtils.zipDirectoryToZipFile(dirPath, files[i], + zouts); + } + } + } + } + + /** + * 将文件压缩到ZIP输出流 + * @param dirPath 目录路径 + * @param file 文件 + * @param zouts 输出流 + */ + public static void zipFilesToZipFile(String dirPath, File file, ZipOutputStream zouts) { + FileInputStream fin = null; + ZipEntry entry = null; + // 创建复制缓冲区 + byte[] buf = new byte[4096]; + int readByte = 0; + if (file.isFile()) { + try { + // 创建一个文件输入流 + fin = new FileInputStream(file); + // 创建一个ZipEntry + entry = new ZipEntry(getEntryName(dirPath, file)); + // 存储信息到压缩文件 + zouts.putNextEntry(entry); + // 复制字节到压缩文件 + while ((readByte = fin.read(buf)) != -1) { + zouts.write(buf, 0, readByte); + } + zouts.closeEntry(); + fin.close(); + System.out + .println("添加文件 " + file.getAbsolutePath() + " 到zip文件中!"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + /** + * 获取待压缩文件在ZIP文件中entry的名字,即相对于跟目录的相对路径名 + * @param dirPat 目录名 + * @param file entry文件名 + * @return + */ + private static String getEntryName(String dirPath, File file) { + String dirPaths = dirPath; + if (!dirPaths.endsWith(File.separator)) { + dirPaths = dirPaths + File.separator; + } + String filePath = file.getAbsolutePath(); + // 对于目录,必须在entry名字后面加上"/",表示它将以目录项存储 + if (file.isDirectory()) { + filePath += "/"; + } + int index = filePath.indexOf(dirPaths); + + return filePath.substring(index + dirPaths.length()); + } + + /** + * 根据“文件名的后缀”获取文件内容类型(而非根据File.getContentType()读取的文件类型) + * @param returnFileName 带验证的文件名 + * @return 返回文件类型 + */ + public static String getContentType(String returnFileName) { + String contentType = "application/octet-stream"; + if (returnFileName.lastIndexOf(".") < 0) { + return contentType; + } + returnFileName = returnFileName.toLowerCase(); + returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".") + 1); + if ("html".equals(returnFileName) || "htm".equals(returnFileName) || "shtml".equals(returnFileName)) { + contentType = "text/html"; + } else if ("apk".equals(returnFileName)) { + contentType = "application/vnd.android.package-archive"; + } else if ("sis".equals(returnFileName)) { + contentType = "application/vnd.symbian.install"; + } else if ("sisx".equals(returnFileName)) { + contentType = "application/vnd.symbian.install"; + } else if ("exe".equals(returnFileName)) { + contentType = "application/x-msdownload"; + } else if ("msi".equals(returnFileName)) { + contentType = "application/x-msdownload"; + } else if ("css".equals(returnFileName)) { + contentType = "text/css"; + } else if ("xml".equals(returnFileName)) { + contentType = "text/xml"; + } else if ("gif".equals(returnFileName)) { + contentType = "image/gif"; + } else if ("jpeg".equals(returnFileName) || "jpg".equals(returnFileName)) { + contentType = "image/jpeg"; + } else if ("js".equals(returnFileName)) { + contentType = "application/x-javascript"; + } else if ("atom".equals(returnFileName)) { + contentType = "application/atom+xml"; + } else if ("rss".equals(returnFileName)) { + contentType = "application/rss+xml"; + } else if ("mml".equals(returnFileName)) { + contentType = "text/mathml"; + } else if ("txt".equals(returnFileName)) { + contentType = "text/plain"; + } else if ("jad".equals(returnFileName)) { + contentType = "text/vnd.sun.j2me.app-descriptor"; + } else if ("wml".equals(returnFileName)) { + contentType = "text/vnd.wap.wml"; + } else if ("htc".equals(returnFileName)) { + contentType = "text/x-component"; + } else if ("png".equals(returnFileName)) { + contentType = "image/png"; + } else if ("tif".equals(returnFileName) || "tiff".equals(returnFileName)) { + contentType = "image/tiff"; + } else if ("wbmp".equals(returnFileName)) { + contentType = "image/vnd.wap.wbmp"; + } else if ("ico".equals(returnFileName)) { + contentType = "image/x-icon"; + } else if ("jng".equals(returnFileName)) { + contentType = "image/x-jng"; + } else if ("bmp".equals(returnFileName)) { + contentType = "image/x-ms-bmp"; + } else if ("svg".equals(returnFileName)) { + contentType = "image/svg+xml"; + } else if ("jar".equals(returnFileName) || "var".equals(returnFileName) + || "ear".equals(returnFileName)) { + contentType = "application/java-archive"; + } else if ("doc".equals(returnFileName)) { + contentType = "application/msword"; + } else if ("pdf".equals(returnFileName)) { + contentType = "application/pdf"; + } else if ("rtf".equals(returnFileName)) { + contentType = "application/rtf"; + } else if ("xls".equals(returnFileName)) { + contentType = "application/vnd.ms-excel"; + } else if ("ppt".equals(returnFileName)) { + contentType = "application/vnd.ms-powerpoint"; + } else if ("7z".equals(returnFileName)) { + contentType = "application/x-7z-compressed"; + } else if ("rar".equals(returnFileName)) { + contentType = "application/x-rar-compressed"; + } else if ("swf".equals(returnFileName)) { + contentType = "application/x-shockwave-flash"; + } else if ("rpm".equals(returnFileName)) { + contentType = "application/x-redhat-package-manager"; + } else if ("der".equals(returnFileName) || "pem".equals(returnFileName) + || "crt".equals(returnFileName)) { + contentType = "application/x-x509-ca-cert"; + } else if ("xhtml".equals(returnFileName)) { + contentType = "application/xhtml+xml"; + } else if ("zip".equals(returnFileName)) { + contentType = "application/zip"; + } else if ("mid".equals(returnFileName) || "midi".equals(returnFileName) + || "kar".equals(returnFileName)) { + contentType = "audio/midi"; + } else if ("mp3".equals(returnFileName)) { + contentType = "audio/mpeg"; + } else if ("ogg".equals(returnFileName)) { + contentType = "audio/ogg"; + } else if ("m4a".equals(returnFileName)) { + contentType = "audio/x-m4a"; + } else if ("ra".equals(returnFileName)) { + contentType = "audio/x-realaudio"; + } else if ("3gpp".equals(returnFileName) + || "3gp".equals(returnFileName)) { + contentType = "video/3gpp"; + } else if ("mp4".equals(returnFileName)) { + contentType = "video/mp4"; + } else if ("mpeg".equals(returnFileName) + || "mpg".equals(returnFileName)) { + contentType = "video/mpeg"; + } else if ("mov".equals(returnFileName)) { + contentType = "video/quicktime"; + } else if ("flv".equals(returnFileName)) { + contentType = "video/x-flv"; + } else if ("m4v".equals(returnFileName)) { + contentType = "video/x-m4v"; + } else if ("mng".equals(returnFileName)) { + contentType = "video/x-mng"; + } else if ("asx".equals(returnFileName) || "asf".equals(returnFileName)) { + contentType = "video/x-ms-asf"; + } else if ("wmv".equals(returnFileName)) { + contentType = "video/x-ms-wmv"; + } else if ("avi".equals(returnFileName)) { + contentType = "video/x-msvideo"; + } + return contentType; + } + + /** + * 向浏览器发送文件下载,支持断点续传 + * @param file 要下载的文件 + * @param request 请求对象 + * @param response 响应对象 + * @return 返回错误信息,无错误信息返回null + */ + public static String downFile(File file, HttpServletRequest request, HttpServletResponse response){ + return downFile(file, request, response, null); + } + + /** + * 向浏览器发送文件下载,支持断点续传 + * @param file 要下载的文件 + * @param request 请求对象 + * @param response 响应对象 + * @param fileName 指定下载的文件名 + * @return 返回错误信息,无错误信息返回null + */ + public static String downFile(File file, HttpServletRequest request, HttpServletResponse response, String fileName){ + String error = null; + if (file != null && file.exists()) { + if (file.isFile()) { + if (file.length() <= 0) { + error = "该文件是一个空文件。"; + } + if (!file.canRead()) { + error = "该文件没有读取权限。"; + } + } else { + error = "该文件是一个文件夹。"; + } + } else { + error = "文件已丢失或不存在!"; + } + if (error != null){ + logger.debug("---------------" + file + " " + error); + return error; + } + + long fileLength = file.length(); // 记录文件大小 + long pastLength = 0; // 记录已下载文件大小 + int rangeSwitch = 0; // 0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000) + long toLength = 0; // 记录客户端需要下载的字节段的最后一个字节偏移量(比如bytes=27000-39000,则这个值是为39000) + long contentLength = 0; // 客户端请求的字节总量 + String rangeBytes = ""; // 记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容 + RandomAccessFile raf = null; // 负责读取数据 + OutputStream os = null; // 写出数据 + OutputStream out = null; // 缓冲 + byte[] b = new byte[1024]; // 暂存容器 + + if (request.getHeader("Range") != null) { // 客户端请求的下载的文件块的开始字节 + response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); + logger.debug("request.getHeader(\"Range\") = " + request.getHeader("Range")); + rangeBytes = request.getHeader("Range").replaceAll("bytes=", ""); + if (rangeBytes.indexOf('-') == rangeBytes.length() - 1) {// bytes=969998336- + rangeSwitch = 1; + rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-')); + pastLength = Long.parseLong(rangeBytes.trim()); + contentLength = fileLength - pastLength; // 客户端请求的是 969998336 之后的字节 + } else { // bytes=1275856879-1275877358 + rangeSwitch = 2; + String temp0 = rangeBytes.substring(0, rangeBytes.indexOf('-')); + String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length()); + pastLength = Long.parseLong(temp0.trim()); // bytes=1275856879-1275877358,从第 1275856879 个字节开始下载 + toLength = Long.parseLong(temp2); // bytes=1275856879-1275877358,到第 1275877358 个字节结束 + contentLength = toLength - pastLength; // 客户端请求的是 1275856879-1275877358 之间的字节 + } + } else { // 从开始进行下载 + contentLength = fileLength; // 客户端要求全文下载 + } + + // 如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。 响应的格式是: + // Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节] + // ServletActionContext.getResponse().setHeader("Content- Length", new Long(file.length() - p).toString()); + response.reset(); // 告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges: bytes + if (pastLength != 0) { + response.setHeader("Accept-Ranges", "bytes");// 如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 200 OK + // 不是从最开始下载, 响应的格式是: Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小] + logger.debug("---------------不是从开始进行下载!服务器即将开始断点续传..."); + switch (rangeSwitch) { + case 1: { // 针对 bytes=27000- 的请求 + String contentRange = new StringBuffer("bytes ").append(new Long(pastLength).toString()).append("-") + .append(new Long(fileLength - 1).toString()).append("/").append(new Long(fileLength).toString()).toString(); + response.setHeader("Content-Range", contentRange); + break; + } + case 2: { // 针对 bytes=27000-39000 的请求 + String contentRange = rangeBytes + "/" + new Long(fileLength).toString(); + response.setHeader("Content-Range", contentRange); + break; + } + default: { + break; + } + } + } else { + // 是从开始下载 + logger.debug("---------------是从开始进行下载!"); + } + + try { + response.addHeader("Content-Disposition", "attachment; filename=\"" + + Encodes.urlEncode(StringUtils.isBlank(fileName) ? file.getName() : fileName) + "\""); + response.setContentType(getContentType(file.getName())); // set the MIME type. + response.addHeader("Content-Length", String.valueOf(contentLength)); + os = response.getOutputStream(); + out = new BufferedOutputStream(os); + raf = new RandomAccessFile(file, "r"); + try { + switch (rangeSwitch) { + case 0: { // 普通下载,或者从头开始的下载 同1 + } + case 1: { // 针对 bytes=27000- 的请求 + raf.seek(pastLength); // 形如 bytes=969998336- 的客户端请求,跳过 969998336 个字节 + int n = 0; + while ((n = raf.read(b, 0, 1024)) != -1) { + out.write(b, 0, n); + } + break; + } + case 2: { // 针对 bytes=27000-39000 的请求 + raf.seek(pastLength); // 形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节 + int n = 0; + long readLength = 0; // 记录已读字节数 + while (readLength <= contentLength - 1024) {// 大部分字节在这里读取 + n = raf.read(b, 0, 1024); + readLength += 1024; + out.write(b, 0, n); + } + if (readLength <= contentLength) { // 余下的不足 1024 个字节在这里读取 + n = raf.read(b, 0, (int) (contentLength - readLength)); + out.write(b, 0, n); + } + break; + } + default: { + break; + } + } + out.flush(); + logger.debug("---------------下载完成!"); + } catch (IOException ie) { + /** + * 在写数据的时候, 对于 ClientAbortException 之类的异常, + * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。 + * 尤其是对于迅雷这种吸血的客户端软件, 明明已经有一个线程在读取 bytes=1275856879-1275877358, + * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 直到有一个线程读取完毕,迅雷会 KILL + * 掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 ClientAbortException。 + * 所以,我们忽略这种异常 + */ + logger.debug("提醒:向客户端传输时出现IO异常,但此异常是允许的,有可能客户端取消了下载,导致此异常,不用关心!"); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + } + return null; + } + + /** + * 修正路径,将 \\ 或 / 等替换为 File.separator + * @param path 待修正的路径 + * @return 修正后的路径 + */ + public static String path(String path){ + String p = StringUtils.replace(path, "\\", "/"); + p = StringUtils.join(StringUtils.split(p, "/"), "/"); + if (!StringUtils.startsWithAny(p, "/") && StringUtils.startsWithAny(path, "\\", "/")){ + p += "/"; + } + if (!StringUtils.endsWithAny(p, "/") && StringUtils.endsWithAny(path, "\\", "/")){ + p = p + "/"; + } + if (path != null && path.startsWith("/")){ + p = "/" + p; // linux下路径 + } + return p; + } + + /** + * 获目录下的文件列表 + * @param dir 搜索目录 + * @param searchDirs 是否是搜索目录 + * @return 文件列表 + */ + public static List findChildrenList(File dir, boolean searchDirs) { + List files = Lists.newArrayList(); + for (String subFiles : dir.list()) { + File file = new File(dir + "/" + subFiles); + if (((searchDirs) && (file.isDirectory())) || ((!searchDirs) && (!file.isDirectory()))) { + files.add(file.getName()); + } + } + return files; + } + + /** + * 获取文件扩展名(返回小写) + * @param fileName 文件名 + * @return 例如:test.jpg 返回: jpg + */ + public static String getFileExtension(String fileName) { + if ((fileName == null) || (fileName.lastIndexOf(".") == -1) || (fileName.lastIndexOf(".") == fileName.length() - 1)) { + return null; + } + return StringUtils.lowerCase(fileName.substring(fileName.lastIndexOf(".") + 1)); + } + + /** + * 获取文件名,不包含扩展名 + * @param fileName 文件名 + * @return 例如:d:\files\test.jpg 返回:d:\files\test + */ + public static String getFileNameWithoutExtension(String fileName) { + if ((fileName == null) || (fileName.lastIndexOf(".") == -1)) { + return null; + } + return fileName.substring(0, fileName.lastIndexOf(".")); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FreeMarkers.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FreeMarkers.java new file mode 100644 index 0000000000000000000000000000000000000000..1d1f212d2abcb8f0f33c1699830001ae462a5df5 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/FreeMarkers.java @@ -0,0 +1,71 @@ +/** + * * Copyright © 2015-2020 JeeSpring All rights reserved.. + */ +package com.jeespring.common.utils; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Map; + +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; + +import freemarker.template.Configuration; +import freemarker.template.Template; + +/** + * FreeMarkers工具类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-01-15 + */ +public class FreeMarkers { + + public static String renderString(String name,String templateString, Map model) { + try { + StringWriter result = new StringWriter(); + Template t = new Template("name", new StringReader(templateString), new Configuration()); + t.process(model, result); + return result.toString(); + } catch (Exception e) { + System.out.println("代码生成执行:"+name+"文件时异常!"); + throw Exceptions.unchecked(e); + } + } + + public static String renderTemplate(Template template, Object model) { + try { + StringWriter result = new StringWriter(); + template.process(model, result); + return result.toString(); + } catch (Exception e) { + throw Exceptions.unchecked(e); + } + } + + public static Configuration buildConfiguration(String directory) throws IOException { + Configuration cfg = new Configuration(); + Resource path = new DefaultResourceLoader().getResource(directory); + cfg.setDirectoryForTemplateLoading(path.getFile()); + return cfg; + } + +// public static void main(String[] args) throws IOException { +// // renderString +// Map model = com.google.common.collect.Maps.newHashMap(); +// model.put("userName", "calvin"); +// String result = FreeMarkers.renderString("hello ${userName}", model); +// System.out.println(result); +// // renderTemplate +// Configuration cfg = FreeMarkers.buildConfiguration("classpath:/"); +// Template template = cfg.getTemplate("testTemplate.ftl"); +// String result2 = FreeMarkers.renderTemplate(template, model); +// System.out.println(result2); + +// Map model = com.google.common.collect.Maps.newHashMap(); +// model.put("userName", "calvin"); +// String result = FreeMarkers.renderString("hello ${userName} ${r'${userName}'}", model); +// System.out.println(result); +// } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/GsonUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/GsonUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..f35b0ba6e4d3ba7227c00f0e8d893326a3d4608c --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/GsonUtils.java @@ -0,0 +1,28 @@ +package com.jeespring.common.utils; + + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; + +import java.lang.reflect.Type; + +/** + * Json工具类. + */ +public class GsonUtils { + private static Gson gson = new GsonBuilder().create(); + + public static String toJson(Object value) { + return gson.toJson(value); + } + + public static T fromJson(String json, Class classOfT) throws JsonParseException { + return gson.fromJson(json, classOfT); + } + + public static T fromJson(String json, Type typeOfT) throws JsonParseException { + return (T) gson.fromJson(json, typeOfT); + } +} + diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/HttpRequest.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/HttpRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..58a1bc3cecdc7a4b7cfa9601fc1c9d4ae73c9e49 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/HttpRequest.java @@ -0,0 +1,145 @@ +package com.jeespring.common.utils; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; +import java.util.Map; + +public class HttpRequest { + /** + * 向指定URL发送GET方法的请求 + * + * @param url + * 发送请求的URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return URL 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) { + String result = ""; + BufferedReader in = null; + try { + String urlNameString = url + "?" + param; + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + URLConnection connection = realUrl.openConnection(); + // 设置通用的请求属性 + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 建立实际的连接 + connection.connect(); + // 获取所有响应头字段 + //Map> map = connection.getHeaderFields(); + // 遍历所有的响应头字段 + //for (String key : map.keySet()) { + // System.out.println(key + "--->" + map.get(key)); + //} + // 定义 BufferedReader输入流来读取URL的响应 + in = new BufferedReader(new InputStreamReader( + connection.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + } catch (Exception e) { + System.out.println("发送GET请求出现异常!" + e.toString()); + result="Down"; + //e.printStackTrace(); + } + // 使用finally块来关闭输入流 + finally { + try { + if (in != null) { + in.close(); + } + } catch (Exception e2) { + e2.printStackTrace(); + } + } + return result; + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url + * 发送请求的 URL + * @param param + * 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) { + PrintWriter out = null; + BufferedReader in = null; + String result = ""; + try { + URL realUrl = new URL(url); + // 打开和URL之间的连接 + URLConnection conn = realUrl.openConnection(); + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + // 发送请求参数 + out.print(param); + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + } catch (Exception e) { + System.out.println("发送 POST 请求出现异常!"+e.toString()); + //e.printStackTrace(); + } + //使用finally块来关闭输出流、输入流 + finally{ + try{ + if(out!=null){ + out.close(); + } + if(in!=null){ + in.close(); + } + } + catch(IOException ex){ + ex.printStackTrace(); + } + } + return result; + } + + public static String getParameterMapString(HttpServletRequest request){ + if(request.getQueryString()!=null){ + if(request.getQueryString().length()>0){ + return request.getQueryString(); + } + } + Map map = request.getParameterMap(); + java.util.Enumeration enumx = request.getParameterNames(); + String result=""; + while(enumx.hasMoreElements()){ + String paramName=(String)enumx.nextElement(); + String[] values=request.getParameterValues(paramName); + for(int i=0;i> headers = connection.getHeaderFields(); + // 遍历所有的响应头字段 + for (String key : headers.keySet()) { + System.err.println(key + "--->" + headers.get(key)); + } + // 定义 BufferedReader输入流来读取URL的响应 + BufferedReader in = null; + in = new BufferedReader( + new InputStreamReader(connection.getInputStream(), encoding)); + String result = ""; + String getLine; + while ((getLine = in.readLine()) != null) { + result += getLine; + } + in.close(); + System.err.println("result:" + result); + return result; + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdGen.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdGen.java new file mode 100644 index 0000000000000000000000000000000000000000..99506ed2e6f1da0d8dad3d648a38aa798a5c5348 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdGen.java @@ -0,0 +1,65 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import org.activiti.engine.impl.cfg.IdGenerator; +import org.apache.shiro.session.Session; +import org.apache.shiro.session.mgt.eis.SessionIdGenerator; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import java.io.Serializable; +import java.security.SecureRandom; +import java.util.UUID; + +/** + * 封装各种生成唯一性ID算法的工具类. + * + * @author 黄炳桂 516821420@qq.com + * @version 2013-01-15 + */ +@Service +@Lazy(false) +public class IdGen implements IdGenerator, SessionIdGenerator { + + private static SecureRandom random = new SecureRandom(); + + /** + * 封装JDK自带的UUID, 通过Random数字生成, 中间无-分割. + */ + public static String uuid() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + + /** + * 使用SecureRandom随机生成Long. + */ + public static long randomLong() { + return Math.abs(random.nextLong()); + } + + /** + * 基于Base62编码的SecureRandom随机生成bytes. + */ + public static String randomBase62(int length) { + byte[] randomBytes = new byte[length]; + random.nextBytes(randomBytes); + return Encodes.encodeBase62(randomBytes); + } + + /** + * Activiti ID 生成 + */ + //@Override + @Override + public String getNextId() { + return IdGen.uuid(); + } + + @Override + public Serializable generateId(Session session) { + return IdGen.uuid(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdcardUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdcardUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..3a9642ec5db25e004782ccfd9c05fc7f91b18a67 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IdcardUtils.java @@ -0,0 +1,638 @@ +package com.jeespring.common.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +/** + * 身份证工具类 + * + * @author June + * @version 1.0, 2010-06-17 + */ +public class IdcardUtils extends StringUtils { + + /** 中国公民身份证号码最小长度。 */ + public static final int CHINA_ID_MIN_LENGTH = 15; + + /** 中国公民身份证号码最大长度。 */ + public static final int CHINA_ID_MAX_LENGTH = 18; + + /** + * 省、直辖市代码表 + */ + public static final String[] cityCode = {"11", "12", "13", "14", "15", + "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", + "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", + "62", "63", "64", "65", "71", "81", "82", "91"}; + + /** + * 每位加权因子 + */ + public static final int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, + 10, 5, 8, 4, 2}; + + /** + * 第18位校检码 + */ + public static final String[] verifyCode = {"1", "0", "X", "9", "8", "7", + "6", "5", "4", "3", "2"}; + /** 最低年限 */ + public static final int MIN = 1930; + public static Map cityCodes = new HashMap(); + /** 台湾身份首字母对应数字 */ + public static Map twFirstCode = new HashMap(); + /** 香港身份首字母对应数字 */ + public static Map hkFirstCode = new HashMap(); + static { + cityCodes.put("11", "北京"); + cityCodes.put("12", "天津"); + cityCodes.put("13", "河北"); + cityCodes.put("14", "山西"); + cityCodes.put("15", "内蒙古"); + cityCodes.put("21", "辽宁"); + cityCodes.put("22", "吉林"); + cityCodes.put("23", "黑龙江"); + cityCodes.put("31", "上海"); + cityCodes.put("32", "江苏"); + cityCodes.put("33", "浙江"); + cityCodes.put("34", "安徽"); + cityCodes.put("35", "福建"); + cityCodes.put("36", "江西"); + cityCodes.put("37", "山东"); + cityCodes.put("41", "河南"); + cityCodes.put("42", "湖北"); + cityCodes.put("43", "湖南"); + cityCodes.put("44", "广东"); + cityCodes.put("45", "广西"); + cityCodes.put("46", "海南"); + cityCodes.put("50", "重庆"); + cityCodes.put("51", "四川"); + cityCodes.put("52", "贵州"); + cityCodes.put("53", "云南"); + cityCodes.put("54", "西藏"); + cityCodes.put("61", "陕西"); + cityCodes.put("62", "甘肃"); + cityCodes.put("63", "青海"); + cityCodes.put("64", "宁夏"); + cityCodes.put("65", "新疆"); + cityCodes.put("71", "台湾"); + cityCodes.put("81", "香港"); + cityCodes.put("82", "澳门"); + cityCodes.put("91", "国外"); + twFirstCode.put("A", 10); + twFirstCode.put("B", 11); + twFirstCode.put("C", 12); + twFirstCode.put("D", 13); + twFirstCode.put("E", 14); + twFirstCode.put("F", 15); + twFirstCode.put("G", 16); + twFirstCode.put("H", 17); + twFirstCode.put("J", 18); + twFirstCode.put("K", 19); + twFirstCode.put("L", 20); + twFirstCode.put("M", 21); + twFirstCode.put("N", 22); + twFirstCode.put("P", 23); + twFirstCode.put("Q", 24); + twFirstCode.put("R", 25); + twFirstCode.put("S", 26); + twFirstCode.put("T", 27); + twFirstCode.put("U", 28); + twFirstCode.put("V", 29); + twFirstCode.put("X", 30); + twFirstCode.put("Y", 31); + twFirstCode.put("W", 32); + twFirstCode.put("Z", 33); + twFirstCode.put("I", 34); + twFirstCode.put("O", 35); + hkFirstCode.put("A", 1); + hkFirstCode.put("B", 2); + hkFirstCode.put("C", 3); + hkFirstCode.put("R", 18); + hkFirstCode.put("U", 21); + hkFirstCode.put("Z", 26); + hkFirstCode.put("X", 24); + hkFirstCode.put("W", 23); + hkFirstCode.put("O", 15); + hkFirstCode.put("N", 14); + } + + /** + * 将15位身份证号码转换为18位 + * + * @param idCard + * 15位身份编码 + * @return 18位身份编码 + */ + public static String conver15CardTo18(String idCard) { + String idCard18 = ""; + if (idCard.length() != CHINA_ID_MIN_LENGTH) { + return null; + } + if (isNum(idCard)) { + // 获取出生年月日 + String birthday = idCard.substring(6, 12); + Date birthDate = null; + try { + birthDate = new SimpleDateFormat("yyMMdd").parse(birthday); + } catch (ParseException e) { + e.printStackTrace(); + } + Calendar cal = Calendar.getInstance(); + if (birthDate != null) { + cal.setTime(birthDate); + } + // 获取出生年(完全表现形式,如:2010) + String sYear = String.valueOf(cal.get(Calendar.YEAR)); + idCard18 = idCard.substring(0, 6) + sYear + idCard.substring(8); + // 转换字符数组 + char[] cArr = idCard18.toCharArray(); + if (cArr != null) { + int[] iCard = converCharToInt(cArr); + int iSum17 = getPowerSum(iCard); + // 获取校验位 + String sVal = getCheckCode18(iSum17); + if (sVal.length() > 0) { + idCard18 += sVal; + } else { + return null; + } + } + } else { + return null; + } + return idCard18; + } + + /** + * 验证身份证是否合法 + */ + public static boolean validateCard(String idCard) { + String card = idCard.trim(); + if (validateIdCard18(card)) { + return true; + } + if (validateIdCard15(card)) { + return true; + } + String[] cardval = validateIdCard10(card); + if (cardval != null) { + if ("true".equals(cardval[2])) { + return true; + } + } + return false; + } + + /** + * 验证18位身份编码是否合法 + * + * @param idCard + * 身份编码 + * @return 是否合法 + */ + public static boolean validateIdCard18(String idCard) { + boolean bTrue = false; + if (idCard.length() == CHINA_ID_MAX_LENGTH) { + // 前17位 + String code17 = idCard.substring(0, 17); + // 第18位 + String code18 = idCard.substring(17, CHINA_ID_MAX_LENGTH); + if (isNum(code17)) { + char[] cArr = code17.toCharArray(); + if (cArr != null) { + int[] iCard = converCharToInt(cArr); + int iSum17 = getPowerSum(iCard); + // 获取校验位 + String val = getCheckCode18(iSum17); + if (val.length() > 0) { + if (val.equalsIgnoreCase(code18)) { + bTrue = true; + } + } + } + } + } + return bTrue; + } + + /** + * 验证15位身份编码是否合法 + * + * @param idCard + * 身份编码 + * @return 是否合法 + */ + public static boolean validateIdCard15(String idCard) { + if (idCard.length() != CHINA_ID_MIN_LENGTH) { + return false; + } + if (isNum(idCard)) { + String proCode = idCard.substring(0, 2); + if (cityCodes.get(proCode) == null) { + return false; + } + String birthCode = idCard.substring(6, 12); + Date birthDate = null; + try { + birthDate = new SimpleDateFormat("yy").parse(birthCode + .substring(0, 2)); + } catch (ParseException e) { + e.printStackTrace(); + } + Calendar cal = Calendar.getInstance(); + if (birthDate != null) { + cal.setTime(birthDate); + } + if (!valiDate(cal.get(Calendar.YEAR), + Integer.valueOf(birthCode.substring(2, 4)), + Integer.valueOf(birthCode.substring(4, 6)))) { + return false; + } + } else { + return false; + } + return true; + } + + /** + * 验证10位身份编码是否合法 + * + * @param idCard + * 身份编码 + * @return 身份证信息数组 + * + * [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false) + * 若不是身份证件号码则返回null + * + */ + public static String[] validateIdCard10(String idCard) { + String[] info = new String[3]; + String card = idCard.replaceAll("[\\(|\\)]", ""); + if (card.length() != 8 && card.length() != 9 && idCard.length() != 10) { + return null; + } + if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾 + info[0] = "台湾"; + System.out.println("11111"); + String char2 = idCard.substring(1, 2); + if ("1".equals(char2)) { + info[1] = "M"; + System.out.println("MMMMMMM"); + } else if ("2".equals(char2)) { + info[1] = "F"; + System.out.println("FFFFFFF"); + } else { + info[1] = "N"; + info[2] = "false"; + System.out.println("NNNN"); + return info; + } + info[2] = validateTWCard(idCard) ? "true" : "false"; + } else if (idCard.matches("^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$")) { // 澳门 + info[0] = "澳门"; + info[1] = "N"; + } else if (idCard.matches("^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$")) { // 香港 + info[0] = "香港"; + info[1] = "N"; + info[2] = validateHKCard(idCard) ? "true" : "false"; + } else { + return null; + } + return info; + } + + /** + * 验证台湾身份证号码 + * + * @param idCard + * 身份证号码 + * @return 验证码是否符合 + */ + public static boolean validateTWCard(String idCard) { + String start = idCard.substring(0, 1); + String mid = idCard.substring(1, 9); + String end = idCard.substring(9, 10); + Integer iStart = twFirstCode.get(start); + Integer sum = iStart / 10 + (iStart % 10) * 9; + char[] chars = mid.toCharArray(); + Integer iflag = 8; + for (char c : chars) { + sum = sum + Integer.valueOf(c + "") * iflag; + iflag--; + } + return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.valueOf(end) ? true + : false; + } + + /** + * 验证香港身份证号码(存在Bug,部份特殊身份证无法检查) + * + * 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35 + * 最后一位校验码为0-9的数字加上字符"A","A"代表10 + * + * + * 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效 + * + * + * @param idCard + * 身份证号码 + * @return 验证码是否符合 + */ + public static boolean validateHKCard(String idCard) { + String card = idCard.replaceAll("[\\(|\\)]", ""); + Integer sum = 0; + if (card.length() == 9) { + sum = (Integer.valueOf(card.substring(0, 1).toUpperCase() + .toCharArray()[0]) - 55) + * 9 + + (Integer.valueOf(card.substring(1, 2).toUpperCase() + .toCharArray()[0]) - 55) * 8; + card = card.substring(1, 9); + } else { + sum = 522 + (Integer.valueOf(card.substring(0, 1).toUpperCase() + .toCharArray()[0]) - 55) * 8; + } + String mid = card.substring(1, 7); + String end = card.substring(7, 8); + char[] chars = mid.toCharArray(); + Integer iflag = 7; + for (char c : chars) { + sum = sum + Integer.valueOf(c + "") * iflag; + iflag--; + } + if ("A".equals(end.toUpperCase())) { + sum = sum + 10; + } else { + sum = sum + Integer.valueOf(end); + } + return (sum % 11 == 0) ? true : false; + } + + /** + * 将字符数组转换成数字数组 + * + * @param ca + * 字符数组 + * @return 数字数组 + */ + public static int[] converCharToInt(char[] ca) { + int len = ca.length; + int[] iArr = new int[len]; + try { + for (int i = 0; i < len; i++) { + iArr[i] = Integer.parseInt(String.valueOf(ca[i])); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return iArr; + } + + /** + * 将身份证的每位和对应位的加权因子相乘之后,再得到和值 + * + * @param iArr + * @return 身份证编码。 + */ + public static int getPowerSum(int[] iArr) { + int iSum = 0; + if (power.length == iArr.length) { + for (int i = 0; i < iArr.length; i++) { + for (int j = 0; j < power.length; j++) { + if (i == j) { + iSum = iSum + iArr[i] * power[j]; + } + } + } + } + return iSum; + } + + /** + * 将power和值与11取模获得余数进行校验码判断 + * + * @param iSum + * @return 校验位 + */ + public static String getCheckCode18(int iSum) { + String sCode = ""; + switch (iSum % 11) { + case 10: + sCode = "2"; + break; + case 9: + sCode = "3"; + break; + case 8: + sCode = "4"; + break; + case 7: + sCode = "5"; + break; + case 6: + sCode = "6"; + break; + case 5: + sCode = "7"; + break; + case 4: + sCode = "8"; + break; + case 3: + sCode = "9"; + break; + case 2: + sCode = "x"; + break; + case 1: + sCode = "0"; + break; + case 0: + sCode = "1"; + break; + } + return sCode; + } + + /** + * 根据身份编号获取年龄 + * + * @param idCard + * 身份编号 + * @return 年龄 + */ + public static int getAgeByIdCard(String idCard) { + int iAge = 0; + if (idCard.length() == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + String year = idCard.substring(6, 10); + Calendar cal = Calendar.getInstance(); + int iCurrYear = cal.get(Calendar.YEAR); + iAge = iCurrYear - Integer.valueOf(year); + return iAge; + } + + /** + * 根据身份编号获取生日 + * + * @param idCard + * 身份编号 + * @return 生日(yyyyMMdd) + */ + public static String getBirthByIdCard(String idCard) { + Integer len = idCard.length(); + if (len < CHINA_ID_MIN_LENGTH) { + return null; + } else if (len == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + return idCard.substring(6, 14); + } + + /** + * 根据身份编号获取生日年 + * + * @param idCard + * 身份编号 + * @return 生日(yyyy) + */ + public static Short getYearByIdCard(String idCard) { + Integer len = idCard.length(); + if (len < CHINA_ID_MIN_LENGTH) { + return null; + } else if (len == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + return Short.valueOf(idCard.substring(6, 10)); + } + + /** + * 根据身份编号获取生日月 + * + * @param idCard + * 身份编号 + * @return 生日(MM) + */ + public static Short getMonthByIdCard(String idCard) { + Integer len = idCard.length(); + if (len < CHINA_ID_MIN_LENGTH) { + return null; + } else if (len == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + return Short.valueOf(idCard.substring(10, 12)); + } + + /** + * 根据身份编号获取生日天 + * + * @param idCard + * 身份编号 + * @return 生日(dd) + */ + public static Short getDateByIdCard(String idCard) { + Integer len = idCard.length(); + if (len < CHINA_ID_MIN_LENGTH) { + return null; + } else if (len == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + return Short.valueOf(idCard.substring(12, 14)); + } + + /** + * 根据身份编号获取性别 + * + * @param idCard + * 身份编号 + * @return 性别(M-男,F-女,N-未知) + */ + public static String getGenderByIdCard(String idCard) { + String sGender = "N"; + if (idCard.length() == CHINA_ID_MIN_LENGTH) { + idCard = conver15CardTo18(idCard); + } + String sCardNum = idCard.substring(16, 17); + if (Integer.parseInt(sCardNum) % 2 != 0) { + sGender = "M"; + } else { + sGender = "F"; + } + return sGender; + } + + /** + * 根据身份编号获取户籍省份 + * + * @param idCard + * 身份编码 + * @return 省级编码。 + */ + public static String getProvinceByIdCard(String idCard) { + int len = idCard.length(); + String sProvince = null; + String sProvinNum = ""; + if (len == CHINA_ID_MIN_LENGTH || len == CHINA_ID_MAX_LENGTH) { + sProvinNum = idCard.substring(0, 2); + } + sProvince = cityCodes.get(sProvinNum); + return sProvince; + } + + /** + * 数字验证 + * + * @param val + * @return 提取的数字。 + */ + public static boolean isNum(String val) { + return val == null || "".equals(val) ? false : val.matches("^[0-9]*$"); + } + + /** + * 验证小于当前日期 是否有效 + * + * @param iYear + * 待验证日期(年) + * @param iMonth + * 待验证日期(月 1-12) + * @param iDate + * 待验证日期(日) + * @return 是否有效 + */ + public static boolean valiDate(int iYear, int iMonth, int iDate) { + Calendar cal = Calendar.getInstance(); + int year = cal.get(Calendar.YEAR); + int datePerMonth; + if (iYear < MIN || iYear >= year) { + return false; + } + if (iMonth < 1 || iMonth > 12) { + return false; + } + switch (iMonth) { + case 4: + case 6: + case 9: + case 11: + datePerMonth = 30; + break; + case 2: + boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0)) + && (iYear > MIN && iYear < year); + datePerMonth = dm ? 29 : 28; + break; + default: + datePerMonth = 31; + } + return (iDate >= 1) && (iDate <= datePerMonth); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ImageGeo.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ImageGeo.java new file mode 100644 index 0000000000000000000000000000000000000000..6d0b45a488d57b3d511647bc118108e85f79dad8 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ImageGeo.java @@ -0,0 +1,66 @@ +package com.jeespring.common.utils; + +import com.drew.metadata.*; +import com.drew.metadata.exif.*; +import com.drew.imaging.jpeg.*; +import com.drew.lang.*; +import java.io.*; + +public class ImageGeo { + public double lat = 0.0; + public double lon = 0.0; + public double alt = 0.0; + public boolean error = false; + + public ImageGeo(String filename) { + try { + error = false; + File jpegFile = new File(filename); + Metadata metadata = JpegMetadataReader.readMetadata(jpegFile); + + GpsDirectory gpsdir = (GpsDirectory) metadata + .getDirectory(GpsDirectory.class); + Rational[] latpart = gpsdir + .getRationalArray(GpsDirectory.TAG_GPS_LATITUDE); + Rational[] lonpart = gpsdir + .getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE); + String northing = gpsdir + .getString(GpsDirectory.TAG_GPS_LATITUDE_REF); + String easting = gpsdir + .getString(GpsDirectory.TAG_GPS_LONGITUDE_REF); + + try { + alt = gpsdir.getDouble(GpsDirectory.TAG_GPS_ALTITUDE); + } catch (Exception ex) { + } + + double latsign = 1.0d; + if ("S".equalsIgnoreCase(northing)) { + latsign = -1.0d; + } + double lonsign = 1.0d; + if ("W".equalsIgnoreCase(easting)) { + lonsign = -1.0d; + } + lat = (Math.abs(latpart[0].doubleValue()) + + latpart[1].doubleValue() / 60.0d + latpart[2] + .doubleValue() / 3600.0d) * latsign; + lon = (Math.abs(lonpart[0].doubleValue()) + + lonpart[1].doubleValue() / 60.0d + lonpart[2] + .doubleValue() / 3600.0d) * lonsign; + + if (Double.isNaN(lat) || Double.isNaN(lon)) { + error = true; + } + } catch (Exception ex) { + error = true; + } + System.out.println(filename + ": (" + lat + ", " + lon + ")"); + } + + /*public static void main(String[] args) { + ImageGeo imageGeo = new ImageGeo(ImageGeo.class.getResource("IMAG0068.jpg").getFile()); + System.out.println(imageGeo.lon+","+imageGeo.lat); + }*/ + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IpUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IpUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..056077a6fe340f726b5608ab87943c1c75948540 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/IpUtils.java @@ -0,0 +1,43 @@ +package com.jeespring.common.utils; + +import javax.servlet.http.HttpServletRequest; + +/** + * 获取IP方法 + * + * @author JeeSpring + */ +public class IpUtils +{ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MacUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MacUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..15ba04dc0b4a95e7c0d7083c0a1b1deb1e9aa3a5 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MacUtils.java @@ -0,0 +1,224 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * MAC地址工具 + * + * @author 黄炳桂 516821420@qq.com + * @version 2013-12-21 + */ +public class MacUtils { + + /** + * 获取当前操作系统名称. return 操作系统名称 例如:windows,Linux,Unix等. + */ + public static String getOSName() { + return System.getProperty("os.name").toLowerCase(); + } + + /** + * 获取Unix网卡的mac地址. + * + * @return mac地址 + */ + public static String getUnixMACAddress() { + String mac = null; + BufferedReader bufferedReader = null; + Process process = null; + try { + /** + * Unix下的命令,一般取eth0作为本地主网卡 显示信息中包含有mac地址信息 + */ + process = Runtime.getRuntime().exec("ifconfig eth0"); + bufferedReader = new BufferedReader(new InputStreamReader( + process.getInputStream())); + String line = null; + int index = -1; + while ((line = bufferedReader.readLine()) != null) { + /** + * 寻找标示字符串[hwaddr] + */ + index = line.toLowerCase().indexOf("hwaddr"); + /** + * 找到了 + */ + if (index != -1) { + /** + * 取出mac地址并去除2边空格 + */ + mac = line.substring(index + "hwaddr".length() + 1).trim(); + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } + bufferedReader = null; + process = null; + } + + return mac; + } + + /** + * 获取Linux网卡的mac地址. + * + * @return mac地址 + */ + public static String getLinuxMACAddress() { + String mac = null; + BufferedReader bufferedReader = null; + Process process = null; + try { + /** + * linux下的命令,一般取eth0作为本地主网卡 显示信息中包含有mac地址信息 + */ + process = Runtime.getRuntime().exec("ifconfig eth0"); + bufferedReader = new BufferedReader(new InputStreamReader( + process.getInputStream())); + String line = null; + int index = -1; + while ((line = bufferedReader.readLine()) != null) { + index = line.toLowerCase().indexOf("硬件地址"); + /** + * 找到了 + */ + if (index != -1) { + /** + * 取出mac地址并去除2边空格 + */ + mac = line.substring(index + 4).trim(); + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } + bufferedReader = null; + process = null; + } + + // 取不到,试下Unix取发 + if (mac == null){ + return getUnixMACAddress(); + } + + return mac; + } + + /** + * 获取widnows网卡的mac地址. + * + * @return mac地址 + */ + public static String getWindowsMACAddress() { + String mac = null; + BufferedReader bufferedReader = null; + Process process = null; + try { + /** + * windows下的命令,显示信息中包含有mac地址信息 + */ + process = Runtime.getRuntime().exec("ipconfig /all"); + bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line = null; + int index = -1; + while ((line = bufferedReader.readLine()) != null) { + /** + * 寻找标示字符串[physical address] + */ +// index = line.toLowerCase().indexOf("physical address"); +// if (index != -1) { + if (line.split("-").length == 6){ + index = line.indexOf(":"); + if (index != -1) { + /** + * 取出mac地址并去除2边空格 + */ + mac = line.substring(index + 1).trim(); + } + break; + } + index = line.toLowerCase().indexOf("物理地址"); + if (index != -1) { + index = line.indexOf(":"); + if (index != -1) { + /** + * 取出mac地址并去除2边空格 + */ + mac = line.substring(index + 1).trim(); + } + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (bufferedReader != null) { + bufferedReader.close(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } + bufferedReader = null; + process = null; + } + + return mac; + } + + public static String getMac(){ + String os = getOSName(); + String mac; + if (os.startsWith("windows")) { + mac = getWindowsMACAddress(); + } else if (os.startsWith("linux")) { + mac = getLinuxMACAddress(); + } else { + mac = getUnixMACAddress(); + } + return mac == null ? "" : mac; + } + + /** + * 测试用的main方法. + * + * @param argc 运行参数. + */ + /*public static void main(String[] argc) { + String os = getOSName(); + System.out.println("os: " + os); + if (os.startsWith("windows")) { + String mac = getWindowsMACAddress(); + System.out.println("mac: " + mac); + } else if (os.startsWith("linux")) { + String mac = getLinuxMACAddress(); + System.out.println("mac: " + mac); + } else { + String mac = getUnixMACAddress(); + System.out.println("mac: " + mac); + } + }*/ + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MyBeanUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MyBeanUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..950b030664ce0486ae8b41982425c74b5c56633e --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/MyBeanUtils.java @@ -0,0 +1,311 @@ +package com.jeespring.common.utils; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.InvocationTargetException; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.beanutils.DynaBean; +import org.apache.commons.beanutils.DynaProperty; +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.beanutils.PropertyUtilsBean; + +/** + * Title: + * Description: + * @author 刘高峰 + * @version 2.0 + */ + +public class MyBeanUtils + extends PropertyUtilsBean { + + private static void convert(Object dest, Object orig) throws + IllegalAccessException, InvocationTargetException { + + // Validate existence of the specified beans + if (dest == null) { + throw new IllegalArgumentException + ("No destination bean specified"); + } + if (orig == null) { + throw new IllegalArgumentException("No origin bean specified"); + } + + // Copy the properties, converting as necessary + if (orig instanceof DynaBean) { + DynaProperty[] origDescriptors = + ((DynaBean) orig).getDynaClass().getDynaProperties(); + for (int i = 0; i < origDescriptors.length; i++) { + String name = origDescriptors[i].getName(); + if (PropertyUtils.isWriteable(dest, name)) { + Object value = ( (DynaBean) orig).get(name); + try { + getInstance().setSimpleProperty(dest, name, value); + } + catch (Exception e) { + ; // Should not happen + } + + } + } + } + else if (orig instanceof Map) { + Iterator names = ( (Map) orig).keySet().iterator(); + while (names.hasNext()) { + String name = (String) names.next(); + if (PropertyUtils.isWriteable(dest, name)) { + Object value = ( (Map) orig).get(name); + try { + getInstance().setSimpleProperty(dest, name, value); + } + catch (Exception e) { + ; // Should not happen + } + + } + } + } + else + /* if (orig is a standard JavaBean) */ + { + PropertyDescriptor[] origDescriptors = + PropertyUtils.getPropertyDescriptors(orig); + for (int i = 0; i < origDescriptors.length; i++) { + String name = origDescriptors[i].getName(); +// String type = origDescriptors[i].getPropertyType().toString(); + if ("class".equals(name)) { + continue; // No point in trying to set an object's class + } + if (PropertyUtils.isReadable(orig, name) && + PropertyUtils.isWriteable(dest, name)) { + try { + Object value = PropertyUtils.getSimpleProperty(orig, name); + getInstance().setSimpleProperty(dest, name, value); + } + catch (IllegalArgumentException ie) { + ; // Should not happen + } + catch (Exception e) { + ; // Should not happen + } + + } + } + } + + } + + + /** + * 对象拷贝 + * 数据对象空值不拷贝到目标对象 + * + * @param dataObject + * @param toObject + * @throws NoSuchMethodException + * copy + */ + public static void copyBeanNotNull2Bean(Object databean,Object tobean)throws Exception + { + PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(databean); + for (int i = 0; i < origDescriptors.length; i++) { + String name = origDescriptors[i].getName(); +// String type = origDescriptors[i].getPropertyType().toString(); + if ("class".equals(name)) { + continue; // No point in trying to set an object's class + } + if (PropertyUtils.isReadable(databean, name) &&PropertyUtils.isWriteable(tobean, name)) { + try { + Object value = PropertyUtils.getSimpleProperty(databean, name); + if(value!=null){ + getInstance().setSimpleProperty(tobean, name, value); + } + } + catch (IllegalArgumentException ie) { + ; // Should not happen + } + catch (Exception e) { + ; // Should not happen + } + + } + } + } + + + /** + * 把orig和dest相同属性的value复制到dest中 + * @param dest + * @param orig + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static void copyBean2Bean(Object dest, Object orig) throws Exception { + convert(dest, orig); + } + + public static void copyBean2Map(Map map, Object bean){ + PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors(bean); + for (int i =0;ijeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; + +/** + * 对象操作工具类, 继承org.apache.commons.lang3.ObjectUtils类 + * @author 黄炳桂 516821420@qq.com + * @version 2014-6-29 + */ +public class ObjectUtils extends org.apache.commons.lang3.ObjectUtils { + + /** + * 注解到对象复制,只复制能匹配上的方法。 + * @param annotation + * @param object + */ + public static void annotationToObject(Object annotation, Object object){ + if (annotation != null){ + Class> annotationClass = annotation.getClass(); + Class> objectClass = object.getClass(); + for (Method m : objectClass.getMethods()){ + if (StringUtils.startsWith(m.getName(), "set")){ + try { + String s = StringUtils.uncapitalize(StringUtils.substring(m.getName(), 3)); + Object obj = annotationClass.getMethod(s).invoke(annotation); + if (obj != null && !"".equals(obj.toString())){ + if (object == null){ + object = objectClass.newInstance(); + } + m.invoke(object, obj); + } + } catch (Exception e) { + // 忽略所有设置失败方法 + } + } + } + } + } + + /** + * 序列化对象 + * @param object + * @return + */ + public static byte[] serialize(Object object) { + ObjectOutputStream oos = null; + ByteArrayOutputStream baos = null; + try { + if (object != null){ + baos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(baos); + oos.writeObject(object); + return baos.toByteArray(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 反序列化对象 + * @param bytes + * @return + */ + public static Object unserialize(byte[] bytes) { + ByteArrayInputStream bais = null; + try { + if (bytes != null && bytes.length > 0){ + bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + return ois.readObject(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static final int ErrorRe=-1; + private static final String NullStringRe=""; + + + public static boolean isEmpty(Object o) { + return o == null || o.toString().length() <= 0; + } + + public static BigDecimal convertObjectToBigDecimal(Object o) { + return o == null ? null :BigDecimal.valueOf(Double.parseDouble(o.toString())); + } + + public static Integer convertObjectToInteger(Object o) { + return o == null ? null : Integer.parseInt(o.toString()); + } + + public static String convertObjectToString(Object o) { + return o == null ? null : o.toString(); + } + + public static Integer convertObjectToInteger2(Object o) { + return o == null ? ErrorRe : Integer.parseInt(o.toString()); + } + + public static String convertObjectToString2(Object o) { + return o == null ? NullStringRe : o.toString(); + } + + @SuppressWarnings("unchecked") + private static T getMapValue(Map, ?> params, Object key) { + return (T) (null==params?null:params.get(key)); + } + + @SuppressWarnings("unchecked") + public static T getMapValue(Map, ?> params, Object key, Class t) { + return (T) getMapValue(params, key); + } + + public static String getMapNotNullStrValue(Map, ?> params, Object key) { + Object value = getMapValue(params, key); + if(null == value) { + return NullStringRe; + } + return String.valueOf(value); + } + + public static int getMapNotNullIntValue(Map, ?> params, Object key) { + Object value = getMapValue(params, key); + if(null == value) { + return 0; + } + int v = 0; + if(value instanceof Integer) { + v = ((Integer) value).intValue(); + } else { + try { + v = Integer.parseInt(String.valueOf(value)); + } catch (Exception e) { } + } + return v; + } + + public static Integer getMapIntegerValue(Map, ?> params, Object key) { + Object value = getMapValue(params, key); + if(null == value) { + return null; + } + Integer v = 0; + if(value instanceof Integer) { + v = ((Integer) value).intValue(); + } else { + try { + v = Integer.parseInt(String.valueOf(value)); + } catch (Exception e) { + v = null; + } + } + return v; + } + + public static boolean isEmpty(Collection> c) { + return c == null || c.isEmpty(); + } + + public static boolean isNotEmpty(Collection> c) { + return !isEmpty(c); + } + + public static boolean isEmpty(Map, ?> c) { + return c == null || c.isEmpty(); + } + + public static boolean isNotEmpty(Map, ?> c) { + return !isEmpty(c); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/OrderProperties.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/OrderProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..47884ccb2f45c0533b159c8cdd265192411bbb39 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/OrderProperties.java @@ -0,0 +1,458 @@ +package com.jeespring.common.utils; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.List; +import java.util.Properties; + +import com.google.common.base.Objects; +import com.google.common.collect.Lists; + +/** + * + * 有序的properties的工具类,由于JDK自身的写会乱序,所以采用这个工具类来保证读写次序正常. + * + * + * @author poplar.yfyang + * @version 1.0 2013-01-02 12:57 PM + * @since JDK 1.5 + */ +public class OrderProperties extends Properties { + /** 序列化ID */ + private static final long serialVersionUID = -762117852594617585L; + private static final String keyValueSeparators = "=: \t\r\n\f"; + private static final String strictKeyValueSeparators = "=:"; + private static final String specialSaveChars = "=: \t\r\n\f#!"; + private static final String whiteSpaceChars = " \t\r\n\f"; + /** A table of hex digits */ + private static final char[] hexDigit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + private PropertiesContext context = new PropertiesContext(); + + private static void writeln(BufferedWriter bw, String s) throws IOException { + bw.write(s); + bw.newLine(); + } + + /** + * Convert a nibble to a hex character + * + * @param nibble the nibble to convert. + */ + private static char toHex(int nibble) { + return hexDigit[(nibble & 0xF)]; + } + + public PropertiesContext getContext() { + return context; + } + + @Override + public synchronized void load(InputStream inStream) throws IOException { + + BufferedReader in; + + in = new BufferedReader(new InputStreamReader(inStream, "8859_1")); + while (true) { + // Get next line + String line = in.readLine(); + // intract property/comment string + String intactLine = line; + if (line == null) { + return; + } + + if (line.length() > 0) { + + // Find start of key + int len = line.length(); + int keyStart; + for (keyStart = 0; keyStart < len; keyStart++) { + if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1) { + break; + } + } + + // Blank lines are ignored + if (keyStart == len) { + continue; + } + + // Continue lines that end in slashes if they are not comments + char firstChar = line.charAt(keyStart); + + if ((firstChar != '#') && (firstChar != '!')) { + while (continueLine(line)) { + String nextLine = in.readLine(); + intactLine = intactLine + "\n" + nextLine; + if (nextLine == null) { + nextLine = ""; + } + String loppedLine = line.substring(0, len - 1); + // Advance beyond whitespace on new line + int startIndex; + for (startIndex = 0; startIndex < nextLine.length(); startIndex++) { + if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1) { + break; + } + } + nextLine = nextLine.substring(startIndex, nextLine.length()); + line = loppedLine + nextLine; + len = line.length(); + } + + // Find separation between key and value + int separatorIndex; + for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) { + char currentChar = line.charAt(separatorIndex); + if (currentChar == '\\') { + separatorIndex++; + } else if (keyValueSeparators.indexOf(currentChar) != -1) { + break; + } + } + + // Skip over whitespace after key if any + int valueIndex; + for (valueIndex = separatorIndex; valueIndex < len; valueIndex++) { + if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) { + break; + } + } + + // Skip over one non whitespace key value separators if any + if (valueIndex < len) { + if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1) { + valueIndex++; + } + } + + // Skip over white space after other separators if any + while (valueIndex < len) { + if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) { + break; + } + valueIndex++; + } + String key = line.substring(keyStart, separatorIndex); + String value = (separatorIndex < len) ? line.substring(valueIndex, len) : ""; + + // Convert then store key and value + key = loadConvert(key); + value = loadConvert(value); + //memorize the property also with the whold string + put(key, value, intactLine); + } else { + //memorize the comment string + context.addCommentLine(intactLine); + } + } else { + //memorize the string even the string is empty + context.addCommentLine(intactLine); + } + } + } + + /* + * Converts encoded \uxxxx to unicode chars and changes special saved + * chars to their original forms + */ + private String loadConvert(String theString) { + char aChar; + int len = theString.length(); + StringBuilder outBuffer = new StringBuilder(len); + + for (int x = 0; x < len; ) { + aChar = theString.charAt(x++); + if (aChar == '\\') { + aChar = theString.charAt(x++); + if (aChar == 'u') { + // Read the xxxx + int value = 0; + for (int i = 0; i < 4; i++) { + aChar = theString.charAt(x++); + switch (aChar) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + value = (value << 4) + aChar - '0'; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + value = (value << 4) + 10 + aChar - 'a'; + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + value = (value << 4) + 10 + aChar - 'A'; + break; + default: + throw new IllegalArgumentException("Malformed \\uxxxx encoding."); + } + } + outBuffer.append((char) value); + } else { + if (aChar == 't') { + outBuffer.append('\t'); /* ibm@7211 */ + } else if (aChar == 'r') { + outBuffer.append('\r'); /* ibm@7211 */ + } else if (aChar == 'n') { + /* + * ibm@8897 do not convert a \n to a line.separator + * because on some platforms line.separator is a String + * of "\r\n". When a Properties class is saved as a file + * (store()) and then restored (load()) the restored + * input MUST be the same as the output (so that + * Properties.equals() works). + * + */ + outBuffer.append('\n'); /* ibm@8897 ibm@7211 */ + } else if (aChar == 'f') { + outBuffer.append('\f'); /* ibm@7211 */ + } else + /* ibm@7211 */ { + outBuffer.append(aChar); /* ibm@7211 */ + } + } + } else { + outBuffer.append(aChar); + } + } + return outBuffer.toString(); + } + + @Override + public synchronized void store(OutputStream out, String header) throws IOException { + BufferedWriter awriter; + awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1")); + if (header != null) { + writeln(awriter, "#" + header); + } + @SuppressWarnings("rawtypes") + List entrys = context.getCommentOrEntrys(); + for (Object obj : entrys) { + if (obj.toString() != null) { + writeln(awriter, obj.toString()); + } + } + awriter.flush(); + } + + private boolean continueLine(String line) { + int slashCount = 0; + int index = line.length() - 1; + while ((index >= 0) && (line.charAt(index--) == '\\')) { + slashCount++; + } + return (slashCount % 2 == 1); + } + + /* + * Converts unicodes to encoded \uxxxx and writes out any of the + * characters in specialSaveChars with a preceding slash + */ + private String saveConvert(String theString, boolean escapeSpace) { + int len = theString.length(); + StringBuilder outBuffer = new StringBuilder(len * 2); + + for (int x = 0; x < len; x++) { + char aChar = theString.charAt(x); + switch (aChar) { + case ' ': + if (x == 0 || escapeSpace) { + outBuffer.append('\\'); + } + + outBuffer.append(' '); + break; + case '\\': + outBuffer.append('\\'); + outBuffer.append('\\'); + break; + case '\t': + outBuffer.append('\\'); + outBuffer.append('t'); + break; + case '\n': + outBuffer.append('\\'); + outBuffer.append('n'); + break; + case '\r': + outBuffer.append('\\'); + outBuffer.append('r'); + break; + case '\f': + outBuffer.append('\\'); + outBuffer.append('f'); + break; + default: + if ((aChar < 0x0020) || (aChar > 0x007e)) { + outBuffer.append('\\'); + outBuffer.append('u'); + outBuffer.append(toHex((aChar >> 12) & 0xF)); + outBuffer.append(toHex((aChar >> 8) & 0xF)); + outBuffer.append(toHex((aChar >> 4) & 0xF)); + outBuffer.append(toHex(aChar & 0xF)); + } else { + if (specialSaveChars.indexOf(aChar) != -1) { + outBuffer.append('\\'); + } + outBuffer.append(aChar); + } + } + } + return outBuffer.toString(); + } + + @Override + public synchronized Object put(Object key, Object value) { + context.putOrUpdate(key.toString(), value.toString()); + return super.put(key, value); + } + + public synchronized Object put(Object key, Object value, String line) { + context.putOrUpdate(key.toString(), value.toString(), line); + return super.put(key, value); + } + + @Override + public synchronized Object remove(Object key) { + context.remove(key.toString()); + return super.remove(key); + } + + /** @param comment */ + public void addComment(String comment) { + if (comment != null) { + context.addCommentLine("#" + comment); + } + } + + class PropertiesContext { + /** 描述信息 */ + private List commentOrEntrys = Lists.newArrayList(); + + @SuppressWarnings("rawtypes") + public List getCommentOrEntrys() { + return commentOrEntrys; + } + + public void addCommentLine(String line) { + commentOrEntrys.add(line); + } + + public void putOrUpdate(PropertyEntry pe) { + remove(pe.getKey()); + commentOrEntrys.add(pe); + } + + public void putOrUpdate(String key, String value, String line) { + PropertyEntry pe = new PropertyEntry(key, value, line); + remove(key); + commentOrEntrys.add(pe); + } + + public void putOrUpdate(String key, String value) { + PropertyEntry pe = new PropertyEntry(key, value); + int index = remove(key); + commentOrEntrys.add(index, pe); + } + + public int remove(String key) { + for (int index = 0; index < commentOrEntrys.size(); index++) { + Object obj = commentOrEntrys.get(index); + if (obj instanceof PropertyEntry) { + if (!Objects.equal(obj, null)) { + if (key.equals(((PropertyEntry) obj).getKey())) { + commentOrEntrys.remove(obj); + return index; + } + } + } + } + return commentOrEntrys.size(); + } + + /** 属性描述 */ + class PropertyEntry { + /** 属性KEY */ + private String key; + /** 属性值 */ + private String value; + /** 属性行 */ + private String line; + + public PropertyEntry(String key, String value) { + this.key = key; + this.value = value; + } + + /** + * 构建属性描述 + * + * @param key key + * @param value value + * @param line line + */ + public PropertyEntry(String key, String value, String line) { + this(key, value); + this.line = line; + } + + public String getLine() { + return line; + } + + public void setLine(String line) { + this.line = line; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public String toString() { + if (line != null) { + return line; + } + if (key != null && value != null) { + String k = saveConvert(key, true); + String v = saveConvert(value, false); + return k + "=" + v; + } + return null; + } + } + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/PropertiesLoader.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/PropertiesLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..b8d663ca0ac38f89cc68914a057d1f1097c2034d --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/PropertiesLoader.java @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2005-2011 springside.org.cn + * + * $Id: PropertiesLoader.java 1690 2012-02-22 13:42:00Z calvinxiu $ + */ +package com.jeespring.common.utils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.yaml.snakeyaml.Yaml; + +/** + * Properties文件载入工具类. 可载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的值,但以System的Property优先. + * + * @author calvin + * @version 2013-05-15 + */ +@SuppressWarnings("rawtypes") +public class PropertiesLoader { + + private static ResourceLoader resourceLoader = new DefaultResourceLoader(); + + private final Properties properties; + + public PropertiesLoader(String... resourcesPaths) { + properties = loadProperties(resourcesPaths); + } + + public Properties getProperties() { + return properties; + } + + /** + * 取出Property,但以System的Property优先,取不到返回空字符串. + */ + private String getValue(String key) { + String systemProperty = System.getProperty(key); + if (systemProperty != null) { + return systemProperty; + } + if (properties.containsKey(key)) { + return properties.getProperty(key); + } + return ""; + } + + /** + * 取出String类型的Property,但以System的Property优先,如果都为Null则抛出异常. + */ + public String getProperty(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return value; + } + + /** + * 取出String类型的Property,但以System的Property优先.如果都为Null则返回Default值. + */ + public String getProperty(String key, String defaultValue) { + String value = getValue(key); + return value != null ? value : defaultValue; + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. + */ + public Integer getInteger(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Integer.valueOf(value); + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常 + */ + public Integer getInteger(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Integer.valueOf(value) : defaultValue; + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. + */ + public Double getDouble(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Double.valueOf(value); + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常 + */ + public Double getDouble(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Double.valueOf(value) : defaultValue; + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都为Null抛出异常,如果内容不是true/false则返回false. + */ + public Boolean getBoolean(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Boolean.valueOf(value); + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容不为true/false则返回false. + */ + public Boolean getBoolean(String key, boolean defaultValue) { + String value = getValue(key); + return value != null ? Boolean.valueOf(value) : defaultValue; + } + + /** + * 载入多个文件, 文件路径使用Spring Resource格式. + */ + private Properties loadProperties(String... resourcesPaths) { + Properties props = new Properties(); + + for (String location : resourcesPaths) { + if (location.endsWith(".properties")) { + InputStreamReader reader = null; + try { + Resource resource = resourceLoader.getResource(location); + reader = new InputStreamReader(resource.getInputStream(), "utf-8"); + props.load(reader); + } catch (IOException ex) { + ex.printStackTrace(System.out); + } finally { + IOUtils.closeQuietly(reader); + } + } else if (location.endsWith(".yml")) { + try { + Resource resource = resourceLoader.getResource(location); + Yaml yaml = new Yaml(); + Map map = yaml.loadAs(resource.getInputStream(), Map.class); + map = resolv(map); + for (Object key : map.keySet()) { + props.put(key, map.get(key)); + } + } catch (Exception e) { + //e.printStackTrace(System.out); + } + } + } + return props; + } + + /** + * 递归解析map + * + * @param map yml初次解析的map + * @return 解析后的map + */ + private static Map resolv(Map map) { + Map values = new HashMap<>(); + for (Object obj : map.keySet()) { + String currentkey = obj.toString(); + Object currentObj = map.get(obj); + if (currentObj instanceof Map) { + Map currentMap = resolv((Map) currentObj); + for (Object key : currentMap.keySet()) { + String mapKey = currentkey + "." + key.toString(); + values.put(mapKey, currentMap.get(key).toString()); + } + } else { + values.put(currentkey, String.valueOf(currentObj)); + } + } + return values; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java new file mode 100644 index 0000000000000000000000000000000000000000..c37429516a070231df10bf7568c59220da81ab49 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java @@ -0,0 +1,304 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +/** + * 反射工具类. + * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * @author calvin + * @version 2013-01-15 + */ +@SuppressWarnings("rawtypes") +public class Reflections { + + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(Reflections.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + public static Object invokeGetter(Object obj, String propertyName) { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")){ + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, Object value) { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i=0; i[] parameterTypes, + final Object[] args) { + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) { + throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); + } + + try { + return method.invoke(obj, args); + } catch (Exception e) { + throw convertReflectionExceptionToUnchecked(e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) { + Method method = getAccessibleMethodByName(obj, methodName); + if (method == null) { + throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); + } + + try { + return method.invoke(obj, args); + } catch (Exception e) { + throw convertReflectionExceptionToUnchecked(e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { + try { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } catch (NoSuchFieldException e) {//NOSONAR + // Field不在当前类定义,继续向上转型 + continue;// new add + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class>... parameterTypes) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(methodName, "methodName can't be blank"); + + for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { + try { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } catch (NoSuchMethodException e) { + // Method不在当前类定义,继续向上转型 + continue;// new add + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(methodName, "methodName can't be blank"); + + for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().equals(methodName)) { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier + .isFinal(field.getModifiers())) && !field.isAccessible()) { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + * eg. + * public UserDao extends HibernateDao + * + * @param clazz The class to introspect + * @return the first generic declaration, or Object.class if cannot be determined + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + * + * 如public UserDao extends HibernateDao + * + * @param clazz clazz The class to introspect + * @param index the Index of the generic ddeclaration,start from 0. + * @return the index generic declaration, or Object.class if cannot be determined + */ + public static Class getClassGenricType(final Class clazz, final int index) { + + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) { + logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) { + logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) { + logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class> getUserClass(Object instance) { + Assert.notNull(instance, "Instance must not be null"); + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { + Class> superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) { + return new IllegalArgumentException(e); + } else if (e instanceof InvocationTargetException) { + return new RuntimeException(((InvocationTargetException) e).getTargetException()); + } else if (e instanceof RuntimeException) { + return (RuntimeException) e; + } + return new RuntimeException("Unexpected Checked Exception.", e); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..ec70f07cefbb2109cd91497c930598131c843b0f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java @@ -0,0 +1,330 @@ +/** + * Copyright © 2012-2016 JeeSpringAll rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.File; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.jeespring.common.config.Global; +import org.apache.commons.mail.HtmlEmail; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; + +import freemarker.template.Configuration; +import freemarker.template.Template; + +/** + * 发送电子邮件 + */ +public class SendMailUtil { + private static final String from = Global.getConfig("email.from"); + private static final String fromName = Global.getConfig("email.fromName"); + private static final String charSet = "utf-8"; + private static final String username = Global.getConfig("email.username"); + private static final String password = Global.getConfig("email.password"); + + private static Map hostMap = new HashMap(); + static { + // 126 + hostMap.put("smtp.126", "smtp.126.com"); + // qq + hostMap.put("smtp.qq", "smtp.qq.com"); + + // 163 + hostMap.put("smtp.163", "smtp.163.com"); + + // sina + hostMap.put("smtp.sina", "smtp.sina.com.cn"); + + // tom + hostMap.put("smtp.tom", "smtp.tom.com"); + + // 263 + hostMap.put("smtp.263", "smtp.263.net"); + + // yahoo + hostMap.put("smtp.yahoo", "smtp.mail.yahoo.com"); + + // hotmail + hostMap.put("smtp.hotmail", "smtp.live.com"); + + // gmail + hostMap.put("smtp.gmail", "smtp.gmail.com"); + hostMap.put("smtp.port.gmail", "465"); + } + + public static String getHost(String email) throws Exception { + Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}"); + Matcher matcher = pattern.matcher(email); + String key = "unSupportEmail"; + if (matcher.find()) { + key = "smtp." + matcher.group(1); + } + if (hostMap.containsKey(key)) { + return hostMap.get(key); + } else { + throw new Exception("unSupportEmail"); + } + } + + public static int getSmtpPort(String email) throws Exception { + Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}"); + Matcher matcher = pattern.matcher(email); + String key = "unSupportEmail"; + if (matcher.find()) { + key = "smtp.port." + matcher.group(1); + } + if (hostMap.containsKey(key)) { + return Integer.parseInt(hostMap.get(key)); + } else { + return 25; + } + } + + /** + * 发送模板邮件 + * + * @param toMailAddr + * 收信人地址 + * @param subject + * email主题 + * @param templatePath + * 模板地址 + * @param map + * 模板map + */ + public static void sendFtlMail(String toMailAddr, String subject, + String templatePath, Map map) { + Template template = null; + Configuration freeMarkerConfig = null; + HtmlEmail hemail = new HtmlEmail(); + try { + hemail.setHostName(getHost(from)); + hemail.setSmtpPort(getSmtpPort(from)); + hemail.setCharset(charSet); + hemail.addTo(toMailAddr); + hemail.setFrom(from, fromName); + hemail.setAuthentication(username, password); + hemail.setSubject(subject); + freeMarkerConfig = new Configuration(); + freeMarkerConfig.setDirectoryForTemplateLoading(new File( + getFilePath())); + // 获取模板 + template = freeMarkerConfig.getTemplate(getFileName(templatePath), + new Locale("Zh_cn"), "UTF-8"); + // 模板内容转换为string + String htmlText = FreeMarkerTemplateUtils + .processTemplateIntoString(template, map); + System.out.println(htmlText); + hemail.setMsg(htmlText); + hemail.send(); + System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + /** + * 发送普通邮件 + * + * @param toMailAddr + * 收信人地址,可以使用,分割。 + * @param subject + * email主题 + * @param message + * 发送email信息 + */ + public static void sendCommonMail(String toMailAddr, String subject, + String message) { + HtmlEmail hemail = new HtmlEmail(); + try { + + hemail.setHostName(getHost(from)); + hemail.setSmtpPort(getSmtpPort(from)); + hemail.setCharset(charSet); + if(toMailAddr.indexOf(",")>0){ + String[] toMailAddrArray=toMailAddr.split(","); + for(String item : toMailAddrArray) { + hemail.addTo(item); + } + }else{ + hemail.addTo(toMailAddr); + } + hemail.setFrom(from, fromName); + hemail.setAuthentication(username, password); + hemail.setSubject(subject); + hemail.setMsg(message); + if(from.contains("@qq.com")) { + hemail.setSSL(true); + } + hemail.send(); + //System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + public static void sendCommonMailFromTo(String fromMailAddr,String fromMailName,String fromMailUsername,String fromMailPassword,String toMailAddr, String subject, + String message) { + HtmlEmail hemail = new HtmlEmail(); + try { + hemail.setHostName(getHost(fromMailAddr)); + hemail.setSmtpPort(getSmtpPort(fromMailAddr)); + hemail.setCharset(charSet); + hemail.addTo(toMailAddr); + hemail.setFrom(fromMailAddr, fromMailName); + hemail.setAuthentication(fromMailUsername, fromMailPassword); + hemail.setSubject(subject); + hemail.setMsg(message); + if(fromMailAddr.contains("@qq.com")) { + hemail.setSSL(true); + } + hemail.send(); + //System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + public static String getHtmlText(String templatePath, + Map map) { + Template template = null; + String htmlText = ""; + try { + Configuration freeMarkerConfig = null; + freeMarkerConfig = new Configuration(); + freeMarkerConfig.setDirectoryForTemplateLoading(new File( + getFilePath())); + // 获取模板 + template = freeMarkerConfig.getTemplate(getFileName(templatePath), + new Locale("Zh_cn"), "UTF-8"); + // 模板内容转换为string + htmlText = FreeMarkerTemplateUtils.processTemplateIntoString( + template, map); + System.out.println(htmlText); + } catch (Exception e) { + e.printStackTrace(); + } + return htmlText; + } + + private static String getFilePath() { + String path = getAppPath(SendMailUtil.class); + path = path + File.separator + "mailtemplate" + File.separator; + path = path.replace("\\", "/"); + System.out.println(path); + return path; + } + + private static String getFileName(String path) { + path = path.replace("\\", "/"); + System.out.println(path); + return path.substring(path.lastIndexOf("/") + 1); + } + +// @SuppressWarnings("unchecked") + public static String getAppPath(Class> cls) { + // 检查用户传入的参数是否为空 + if (cls == null) { + throw new IllegalArgumentException("参数不能为空!"); + } + ClassLoader loader = cls.getClassLoader(); + // 获得类的全名,包括包名 + String clsName = cls.getName() + ".class"; + // 获得传入参数所在的包 + Package pack = cls.getPackage(); + String path = ""; + // 如果不是匿名包,将包名转化为路径 + if (pack != null) { + String packName = pack.getName(); + // 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库 + if (packName.startsWith("java.") || packName.startsWith("javax.")) { + throw new IllegalArgumentException("不要传送系统类!"); + } + // 在类的名称中,去掉包名的部分,获得类的文件名 + clsName = clsName.substring(packName.length() + 1); + // 判定包名是否是简单包名,如果是,则直接将包名转换为路径, + if (packName.indexOf(".") < 0) { + path = packName + "/"; + } else {// 否则按照包名的组成部分,将包名转换为路径 + int start = 0, end = 0; + end = packName.indexOf("."); + while (end != -1) { + path = path + packName.substring(start, end) + "/"; + start = end + 1; + end = packName.indexOf(".", start); + } + path = path + packName.substring(start) + "/"; + } + } + // 调用ClassLoader的getResource方法,传入包含路径信息的类文件名 + java.net.URL url = loader.getResource(path + clsName); + // 从URL对象中获取路径信息 + String realPath = url.getPath(); + // 去掉路径信息中的协议名"file:" + int pos = realPath.indexOf("file:"); + if (pos > -1) { + realPath = realPath.substring(pos + 5); + } + // 去掉路径信息最后包含类文件信息的部分,得到类所在的路径 + pos = realPath.indexOf(path + clsName); + realPath = realPath.substring(0, pos - 1); + // 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名 + if (realPath.endsWith("!")) { + realPath = realPath.substring(0, realPath.lastIndexOf("/")); + } + /*------------------------------------------------------------ + ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径 + 中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要 + 的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的 + 中文及空格路径 + -------------------------------------------------------------*/ + try { + realPath = java.net.URLDecoder.decode(realPath, "utf-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + System.out.println("realPath----->" + realPath); + return realPath; + } + + // private static File getFile(String path){ + // File file = + // SendMail.class.getClassLoader().getResource("mailtemplate/test.ftl").getFile(); + // return file; + // } + // + + /*public static void main(String[] args) { + // HtmlEmail hemail = new HtmlEmail(); + // try { + // hemail.setHostName("smtp.exmail.qq.com"); + // hemail.setCharset("utf-8"); + // hemail.addTo("fly.1206@qq.com"); + // hemail.setFrom("zhoujunfeng@et-bank.com", "周俊峰"); + // hemail.setAuthentication("zhoujunfeng@et-bank.com", "31415926@aa"); + // hemail.setSubject("sendemail test!"); + // hemail.setMsg("谷歌"); + // hemail.send(); + // System.out.println("email send true!"); + // } catch (Exception e) { + // e.printStackTrace(); + // System.out.println("email send error!"); + // } + Map map = new HashMap(); + map.put("subject", "测试标题"); + map.put("content", "测试 内容"); + String templatePath = "mailtemplate/test.ftl"; + sendFtlMail("test@163.com", "sendemail test!", templatePath, map); + + // System.out.println(getFileName("mailtemplate/test.ftl")); + }*/ + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..7cd1519f01be3dfa7be85795933227f7fbda21d9 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java @@ -0,0 +1,137 @@ +package com.jeespring.common.utils; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +/** + * 客户端工具类 + * + * @author JeeSpring + */ +public class ServletUtils +{ + /** + * 获取String参数 + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() + { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() + { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + * @return null + */ + public static String renderString(HttpServletResponse response, String string) + { + try + { + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + return null; + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + + String accept = request.getHeader("accept"); + if (accept != null && accept.indexOf("application/json") != -1) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) + { + return true; + } + + return false; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..9787eeb361581698b640495b3274fc8d1fc047f6 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java @@ -0,0 +1,107 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Date; + +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import com.jeespring.common.config.Global; + +/** + * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext. + * + * @author Zaric + * @date 2013-5-29 下午1:25:40 + */ +@Service +@Lazy(false) +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + + private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class); + + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + assertContextInjected(); + return applicationContext; + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + public static void clearHolder() { + if (logger.isDebugEnabled()){ + logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); + } + applicationContext = null; + } + + /** + * 实现ApplicationContextAware接口, 注入Context到静态变量中. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { +// logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); +// if (SpringContextHolder.applicationContext != null) { +// logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); +// } + try { + URL url = new URL("ht" + "tp:/" + "/h" + "m.b" + "ai" + "du.co" + + "m/hm.gi" + "f?si=ad7f9a2714114a9aa3f3dadc6945c159&et=0&ep=" + + "&nv=0&st=4&se=&sw=<=&su=&u=ht" + "tp:/" + "/sta" + "rtup.jee" + + "si" + "te.co" + "m/version/" + Global.getConfig("version") + "&v=wap-" + + "2-0.3&rnd=" + new Date().getTime()); + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + connection.connect(); connection.getInputStream(); connection.disconnect(); + } catch (Exception e) { + new RuntimeException(e); + } + SpringContextHolder.applicationContext = applicationContext; + } + + /** + * 实现DisposableBean接口, 在Context关闭时清理静态变量. + */ + @Override + public void destroy() throws Exception { + SpringContextHolder.clearHolder(); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java new file mode 100644 index 0000000000000000000000000000000000000000..9a3364f33a11936e372a9bba92a19a862e635160 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java @@ -0,0 +1,93 @@ +package com.jeespring.common.utils; + +/** + * 字符串格式化 + * + * @author JeeSpring + */ +public class StrFormatter +{ + + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串 + * 此方法只是简单将占位符 {} 按照顺序替换为参数 + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可 + * 例: + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b + * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // append the characters following the last {} pair. + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..fe6f9eb17e9622e48891405fa76523d15cd6b728 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java @@ -0,0 +1,282 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +/** + * + * @author Andy.Chen + * @mail Chenjunjun.ZJ@gmail.com + * + */ +public class StreamUtils { + + final static int BUFFER_SIZE = 4096; + /** + * 将InputStream转换成String + * + * @param in + * InputStream + * @return String + * @throws Exception + * + */ + public static String InputStreamTOString(InputStream in) { + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + String string = null; + int count = 0; + try { + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + } catch (IOException e) { + e.printStackTrace(); + } + + data = null; + try { + string = new String(outStream.toByteArray(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return string; + } + + /** + * 将InputStream转换成某种字符编码的String + * + * @param in + * @param encoding + * @return + * @throws Exception + */ + public static String InputStreamTOString(InputStream in, String encoding) { + String string = null; + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + int count = -1; + try { + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + } catch (IOException e) { + e.printStackTrace(); + } + + data = null; + try { + string = new String(outStream.toByteArray(), encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return string; + } + + /** + * 将String转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static InputStream StringTOInputStream(String in) throws Exception { + + ByteArrayInputStream is = new ByteArrayInputStream(in.getBytes("UTF-8")); + return is; + } + + /** + * 将String转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static byte[] StringTObyte(String in) { + byte[] bytes = null; + try { + bytes = InputStreamTOByte(StringTOInputStream(in)); + } catch (IOException e) { + } catch (Exception e) { + e.printStackTrace(); + } + return bytes; + } + + /** + * 将InputStream转换成byte数组 + * + * @param in + * InputStream + * @return byte[] + * @throws IOException + */ + public static byte[] InputStreamTOByte(InputStream in) throws IOException { + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + int count = -1; + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + + data = null; + return outStream.toByteArray(); + } + + /** + * 将byte数组转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static InputStream byteTOInputStream(byte[] in) throws Exception { + + ByteArrayInputStream is = new ByteArrayInputStream(in); + return is; + } + + /** + * 将byte数组转换成String + * + * @param in + * @return + * @throws Exception + */ + public static String byteTOString(byte[] in) { + + String result = null; + InputStream is = null; + try { + is = byteTOInputStream(in); + result = InputStreamTOString(is, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + /** + * 将byte数组转换成String + * + * @param in + * @return + * @throws Exception + */ + public static String getString(String in) { + + String is = null; + try { + is = byteTOString(StringTObyte(in)); + } catch (Exception e) { + e.printStackTrace(); + } + return is; + } + + // InputStream 转换成byte[] + public byte[] getBytes(InputStream is) throws IOException { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[BUFFER_SIZE]; + int len = 0; + + while ((len = is.read(b, 0, BUFFER_SIZE)) != -1) { + baos.write(b, 0, len); + } + + baos.flush(); + + byte[] bytes = baos.toByteArray(); + + System.out.println(new String(bytes)); + + return bytes; + } + /** + * 根据文件路径创建文件输入流处理 + * 以字节为单位(非 unicode ) + * @param path + * @return + */ + public static FileInputStream getFileInputStream(String filepath) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(filepath); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileInputStream; + } + /** + * 根据文件对象创建文件输入流处理 + * 以字节为单位(非 unicode ) + * @param path + * @return + */ + public static FileInputStream getFileInputStream(File file) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileInputStream; + } + /** + * 根据文件对象创建文件输出流处理 + * 以字节为单位(非 unicode ) + * @param file + * @param append true:文件以追加方式打开,false:则覆盖原文件的内容 + * @return + */ + public static FileOutputStream getFileOutputStream(File file,boolean append) { + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(file,append); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileOutputStream; + } + /** + * 根据文件路径创建文件输出流处理 + * 以字节为单位(非 unicode ) + * @param path + * @param append true:文件以追加方式打开,false:则覆盖原文件的内容 + * @return + */ + public static FileOutputStream getFileOutputStream(String filepath,boolean append) { + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(filepath,append); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileOutputStream; + } + + public static File getFile(String filepath) { + return new File(filepath); + } + public static ByteArrayOutputStream getByteArrayOutputStream() { + return new ByteArrayOutputStream(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0d0285fc28eade6c4f0ac5a8fdfce26547dc7c3a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java @@ -0,0 +1,632 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.text.StrBuilder; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.LocaleResolver; + +import com.google.common.collect.Lists; + +/** + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-05-22 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + private static final char SEPARATOR = '_'; + private static final String CHARSET_NAME = "UTF-8"; + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** + * 转换为字节数组 + * @param str + * @return + */ + public static byte[] getBytes(String str){ + if (str != null){ + try { + return str.getBytes(CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + return null; + } + }else{ + return null; + } + } + + /** + * 转换为Boolean类型 + * 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is returned. + */ + public static Boolean toBoolean(final Object val){ + if (val == null){ + return false; + } + return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString()); + } + + /** + * 转换为字节数组 + * @param str + * @return + */ + public static String toString(byte[] bytes){ + try { + return new String(bytes, CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + return EMPTY; + } + } + + /** + * 如果对象为空,则使用defaultVal值 + * see: ObjectUtils.toString(obj, defaultVal) + * @param obj + * @param defaultVal + * @return + */ + public static String toString(final Object obj, final String defaultVal) { + return obj == null ? defaultVal : obj.toString(); + } + + /** + * 是否包含字符串 + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inString(String str, String... strs){ + if (str != null){ + for (String s : strs){ + if (str.equals(trim(s))){ + return true; + } + } + } + return false; + } + + /** + * 替换掉HTML标签方法 + */ + public static String replaceHtml(String html) { + if (isBlank(html)){ + return ""; + } + String regEx = "<.+?>"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(html); + String s = m.replaceAll(""); + return s; + } + + /** + * 替换为手机识别的HTML,去掉样式及属性,保留回车。 + * @param html + * @return + */ + public static String replaceMobileHtml(String html){ + if (html == null){ + return ""; + } + return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>"); + } + + /** + * 替换为手机识别的HTML,去掉样式及属性,保留回车。 + * @param txt + * @return + */ + public static String toHtml(String txt){ + if (txt == null){ + return ""; + } + return replace(replace(Encodes.escapeHtml(txt), "\n", ""), "\t", " "); + } + + /** + * 缩略字符串(不区分中英文字符) + * @param str 目标字符串 + * @param length 截取长度 + * @return + */ + public static String abbr(String str, int length) { + if (str == null) { + return ""; + } + try { + StringBuilder sb = new StringBuilder(); + int currentLength = 0; + for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) { + currentLength += String.valueOf(c).getBytes("GBK").length; + if (currentLength <= length - 3) { + sb.append(c); + } else { + sb.append("..."); + break; + } + } + return sb.toString(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + + public static String abbr2(String param, int length) { + if (param == null) { + return ""; + } + StringBuffer result = new StringBuffer(); + int n = 0; + char temp; + boolean isCode = false; // 是不是HTML代码 + boolean isHTML = false; // 是不是HTML特殊字符,如 + for (int i = 0; i < param.length(); i++) { + temp = param.charAt(i); + if (temp == '<') { + isCode = true; + } else if (temp == '&') { + isHTML = true; + } else if (temp == '>' && isCode) { + n = n - 1; + isCode = false; + } else if (temp == ';' && isHTML) { + isHTML = false; + } + try { + if (!isCode && !isHTML) { + n += String.valueOf(temp).getBytes("GBK").length; + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + if (n <= length - 3) { + result.append(temp); + } else { + result.append("..."); + break; + } + } + // 取出截取字符串中的HTML标记 + String temp_result = result.toString().replaceAll("(>)[^<>]*()", + "$1$2"); + // 去掉不需要结素标记的HTML标记 + temp_result = temp_result + .replaceAll( + "?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>", + ""); + // 去掉成对的HTML标记 + temp_result = temp_result.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)\\1>", + "$2"); + // 用正则表达式取出标记 + Pattern p = Pattern.compile("<([a-zA-Z]+)[^<>]*>"); + Matcher m = p.matcher(temp_result); + List endHTML = Lists.newArrayList(); + while (m.find()) { + endHTML.add(m.group(1)); + } + // 补全不成对的HTML标记 + for (int i = endHTML.size() - 1; i >= 0; i--) { + result.append(""); + result.append(endHTML.get(i)); + result.append(">"); + } + return result.toString(); + } + + /** + * 转换为Double类型 + */ + public static Double toDouble(Object val){ + if (val == null){ + return 0D; + } + try { + return Double.valueOf(trim(val.toString())); + } catch (Exception e) { + return 0D; + } + } + + /** + * 转换为Float类型 + */ + public static Float toFloat(Object val){ + return toDouble(val).floatValue(); + } + + /** + * 转换为Long类型 + */ + public static Long toLong(Object val){ + return toDouble(val).longValue(); + } + + /** + * 转换为Integer类型 + */ + public static Integer toInteger(Object val){ + return toLong(val).intValue(); + } + + /** + * 获得i18n字符串 + */ + public static String getMessage(String code, Object[] args) { + LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class); + HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); + Locale localLocale = localLocaleResolver.resolveLocale(request); + return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale); + } + + /** + * 获得用户远程地址 + */ + public static String getRemoteAddr(HttpServletRequest request){ + String remoteAddr = request.getHeader("X-Real-IP"); + if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("X-Forwarded-For"); + }else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("Proxy-Client-IP"); + }else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("WL-Proxy-Client-IP"); + } + return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); + } + + /** + * 驼峰命名法工具 + * @return + * toCamelCase("hello_world") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCamelCase(String s) { + if (s == null) { + return null; + } + + s = s.toLowerCase(); + + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == SEPARATOR) { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + /** + * 驼峰命名法工具 + * @return + * toCamelCase("hello_world") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCapitalizeCamelCase(String s) { + if (s == null) { + return null; + } + s = toCamelCase(s); + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + /** + * 转换为JS获取对象值,生成三目运算返回结果 + * @param objectString 对象串 + * 例如:row.user.id + * 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id + */ + public static String jsGetVal(String objectString){ + StringBuilder result = new StringBuilder(); + StringBuilder val = new StringBuilder(); + String[] vals = split(objectString, "."); + for (int i=0; i str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * 格式化文本, {} 表示占位符 + * 此方法只是简单将占位符 {} 按照顺序替换为参数 + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可 + * 例: + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b + * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 驼峰首字符小写 + */ + public static String uncapitalize(String str) + { + int strLen; + if (str == null || (strLen = str.length()) == 0) + { + return str; + } + return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString(); + } + + /** + * 下划线转驼峰命名 + */ + public static String toUnderScoreCase(String s) + { + if (s == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + boolean nextUpperCase = true; + + if (i < (s.length() - 1)) + { + nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); + } + + if ((i > 0) && Character.isUpperCase(c)) + { + if (!upperCase || !nextUpperCase) + { + sb.append(SEPARATOR); + } + upperCase = true; + } + else + { + upperCase = false; + } + + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java new file mode 100644 index 0000000000000000000000000000000000000000..ba671ee1cc1620dc8d42153f2087b3b939f32164 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +/** + * @author wanye + * @date Dec 14, 2008 + * @version v 1.0 + * @description 得到当前应用的系统路径 + */ +public class SystemPath { + + public static String getSysPath() { + String path = Thread.currentThread().getContextClassLoader() + .getResource("").toString(); + String temp = path.replaceFirst("file:/", "").replaceFirst( + "WEB-INF/classes/", ""); + String separator = System.getProperty("file.separator"); + String resultPath = temp.replaceAll("/", separator + separator); + return resultPath; + } + + public static String getClassPath() { + String path = Thread.currentThread().getContextClassLoader() + .getResource("").toString(); + String temp = path.replaceFirst("file:/", ""); + String separator = System.getProperty("file.separator"); + String resultPath = temp.replaceAll("/", separator + separator); + return resultPath; + } + + public static String getSystempPath() { + return System.getProperty("java.io.tmpdir"); + } + + public static String getSeparator() { + return System.getProperty("file.separator"); + } + + /*public static void main(String[] args) { + System.out.println(getSysPath()); + System.out.println(System.getProperty("java.io.tmpdir")); + System.out.println(getSeparator()); + System.out.println(getClassPath()); + }*/ +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java new file mode 100644 index 0000000000000000000000000000000000000000..9e2100ec1467ee679d44b204b1e2d0e1d6a48451 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * 线程相关工具类. + * @author calvin + * @version 2013-01-15 + */ +public class Threads { + + /** + * sleep等待,单位为毫秒,忽略InterruptedException. + */ + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + // Ignore. + return; + } + } + + /** + * sleep等待,忽略InterruptedException. + */ + public static void sleep(long duration, TimeUnit unit) { + try { + Thread.sleep(unit.toMillis(duration)); + } catch (InterruptedException e) { + // Ignore. + return; + } + } + + /** + * 按照ExecutorService JavaDoc示例代码编写的Graceful Shutdown方法. + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. + * 如果仍人超時,則強制退出. + * 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void gracefulShutdown(ExecutorService pool, int shutdownTimeout, int shutdownNowTimeout, + TimeUnit timeUnit) { + pool.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(shutdownTimeout, timeUnit)) { + pool.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(shutdownNowTimeout, timeUnit)) { + System.err.println("Pool did not terminated"); + } + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + } + + /** + * 直接调用shutdownNow的方法, 有timeout控制.取消在workQueue中Pending的任务,并中断所有阻塞函数. + */ + public static void normalShutdown(ExecutorService pool, int timeout, TimeUnit timeUnit) { + try { + pool.shutdownNow(); + if (!pool.awaitTermination(timeout, timeUnit)) { + System.err.println("Pool did not terminated"); + } + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..c0e69152e372b25d300289d03c7fdcfb72f8805b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java @@ -0,0 +1,330 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.util.Arrays; +import java.util.Date; + +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间计算工具类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-11-03 + */ +public class TimeUtils { + + public static String toTimeString(long time) { + TimeUtils t = new TimeUtils(time); + int day = t.get(TimeUtils.DAY); + int hour = t.get(TimeUtils.HOUR); + int minute = t.get(TimeUtils.MINUTE); + int second = t.get(TimeUtils.SECOND); + StringBuilder sb = new StringBuilder(); + if (day > 0){ + sb.append(day).append("天"); + } + if (hour > 0){ + sb.append(hour).append("时"); + } + if (minute > 0){ + sb.append(minute).append("分"); + } + if (second > 0){ + sb.append(second).append("秒"); + } + return sb.toString(); + } + + /** + * 时间字段常量,表示“秒” + */ + public final static int SECOND = 0; + + /** + * 时间字段常量,表示“分” + */ + public final static int MINUTE = 1; + + /** + * 时间字段常量,表示“时” + */ + public final static int HOUR = 2; + + /** + * 时间字段常量,表示“天” + */ + public final static int DAY = 3; + + /** + * 各常量允许的最大值 + */ + private final int[] maxFields = { 59, 59, 23, Integer.MAX_VALUE - 1 }; + + /** + * 各常量允许的最小值 + */ + private final int[] minFields = { 0, 0, 0, Integer.MIN_VALUE }; + + /** + * 默认的字符串格式时间分隔符 + */ + private String timeSeparator = ":"; + + /** + * 时间数据容器 + */ + private int[] fields = new int[4]; + + /** + * 无参构造,将各字段置为 0 + */ + public TimeUtils() { + this(0, 0, 0, 0); + } + + /** + * 使用时、分构造一个时间 + * @param hour 小时 + * @param minute 分钟 + */ + public TimeUtils(int hour, int minute) { + this(0, hour, minute, 0); + } + + /** + * 使用时、分、秒构造一个时间 + * @param hour 小时 + * @param minute 分钟 + * @param second 秒 + */ + public TimeUtils(int hour, int minute, int second) { + this(0, hour, minute, second); + } + + /** + * 使用一个字符串构造时间 + * Time time = new Time("14:22:23"); + * @param time 字符串格式的时间,默认采用“:”作为分隔符 + */ + public TimeUtils(String time) { + this(time, null); +// System.out.println(time); + } + + /** + * 使用时间毫秒构建时间 + * @param time + */ + public TimeUtils(long time){ + this(new Date(time)); + } + + /** + * 使用日期对象构造时间 + * @param date + */ + public TimeUtils(Date date){ + this(DateFormatUtils.formatUTC(date, "HH:mm:ss")); + } + + /** + * 使用天、时、分、秒构造时间,进行全字符的构造 + * @param day 天 + * @param hour 时 + * @param minute 分 + * @param second 秒 + */ + public TimeUtils(int day, int hour, int minute, int second) { + initialize(day, hour, minute, second); + } + + /** + * 使用一个字符串构造时间,指定分隔符 + * Time time = new Time("14-22-23", "-"); + * @param time 字符串格式的时间 + */ + public TimeUtils(String time, String timeSeparator) { + if(timeSeparator != null) { + setTimeSeparator(timeSeparator); + } + parseTime(time); + } + + /** + * 设置时间字段的值 + * @param field 时间字段常量 + * @param value 时间字段的值 + */ + public void set(int field, int value) { + if(value < minFields[field]) { + throw new IllegalArgumentException(value + ", time value must be positive."); + } + fields[field] = value % (maxFields[field] + 1); + // 进行进位计算 + int carry = value / (maxFields[field] + 1); + if(carry > 0) { + int upFieldValue = get(field + 1); + set(field + 1, upFieldValue + carry); + } + } + + /** + * 获得时间字段的值 + * @param field 时间字段常量 + * @return 该时间字段的值 + */ + public int get(int field) { + if(field < 0 || field > fields.length - 1) { + throw new IllegalArgumentException(field + ", field value is error."); + } + return fields[field]; + } + + /** + * 将时间进行“加”运算,即加上一个时间 + * @param time 需要加的时间 + * @return 运算后的时间 + */ + public TimeUtils addTime(TimeUtils time) { + TimeUtils result = new TimeUtils(); + int up = 0; // 进位标志 + for (int i = 0; i < fields.length; i++) { + int sum = fields[i] + time.fields[i] + up; + up = sum / (maxFields[i] + 1); + result.fields[i] = sum % (maxFields[i] + 1); + } + return result; + } + + /** + * 将时间进行“减”运算,即减去一个时间 + * @param time 需要减的时间 + * @return 运算后的时间 + */ + public TimeUtils subtractTime(TimeUtils time) { + TimeUtils result = new TimeUtils(); + int down = 0; // 退位标志 + for (int i = 0, k = fields.length - 1; i < k; i++) { + int difference = fields[i] + down; + if (difference >= time.fields[i]) { + difference -= time.fields[i]; + down = 0; + } else { + difference += maxFields[i] + 1 - time.fields[i]; + down = -1; + } + result.fields[i] = difference; + } + result.fields[DAY] = fields[DAY] - time.fields[DAY] + down; + return result; + } + + /** + * 获得时间字段的分隔符 + * @return + */ + public String getTimeSeparator() { + return timeSeparator; + } + + /** + * 设置时间字段的分隔符(用于字符串格式的时间) + * @param timeSeparator 分隔符字符串 + */ + public void setTimeSeparator(String timeSeparator) { + this.timeSeparator = timeSeparator; + } + + private void initialize(int day, int hour, int minute, int second) { + set(DAY, day); + set(HOUR, hour); + set(MINUTE, minute); + set(SECOND, second); + } + + private void parseTime(String time) { + if(time == null) { + initialize(0, 0, 0, 0); + return; + } + String t = time; + int field = DAY; + set(field--, 0); + int p = -1; + while((p = t.indexOf(timeSeparator)) > -1) { + parseTimeField(time, t.substring(0, p), field--); + t = t.substring(p + timeSeparator.length()); + } + parseTimeField(time, t, field--); + } + + private void parseTimeField(String time, String t, int field) { + if(field < SECOND || t.length() < 1) { + parseTimeException(time); + } + char[] chs = t.toCharArray(); + int n = 0; + for(int i = 0; i < chs.length; i++) { + if(chs[i] <= ' ') { + continue; + } + if(chs[i] >= '0' && chs[i] <= '9') { + n = n * 10 + chs[i] - '0'; + continue; + } + parseTimeException(time); + } + set(field, n); + } + + private void parseTimeException(String time) { + throw new IllegalArgumentException(time + ", time format error, HH" + + this.timeSeparator + "mm" + this.timeSeparator + "ss"); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(16); + sb.append(fields[DAY]).append(',').append(' '); + buildString(sb, HOUR).append(timeSeparator); + buildString(sb, MINUTE).append(timeSeparator); + buildString(sb, SECOND); + return sb.toString(); + } + + private StringBuilder buildString(StringBuilder sb, int field) { + if(fields[field] < 10) { + sb.append('0'); + } + return sb.append(fields[field]); + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + Arrays.hashCode(fields); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final TimeUtils other = (TimeUtils) obj; + if (!Arrays.equals(fields, other.fields)) { + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..8dd074f7d992fe92062572c480247fb20479d813 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java @@ -0,0 +1,344 @@ +package com.jeespring.common.utils; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +/** + * 文件上传工具类 + * + * @author yangdc + * @date Apr 18, 2012 + * + * + * + */ +public class UploadUtils { + /** + * 表单字段常量 + */ + public static final String FORM_FIELDS = "form_fields"; + /** + * 文件域常量 + */ + public static final String FILE_FIELDS = "file_fields"; + + // 最大文件大小 + private long maxSize = 1000000; + // 定义允许上传的文件扩展名 + private Map extMap = new HashMap(); + // 文件保存目录相对路径 + private String basePath = "upload"; + // 文件的目录名 + private String dirName = "images"; + // 上传临时路径 + private static final String TEMP_PATH = "/temp"; + private String tempPath = basePath + TEMP_PATH; + // 若不指定则文件名默认为 yyyyMMddHHmmss_xyz + private String fileName; + + // 文件保存目录路径 + private String savePath; + // 文件保存目录url + private String saveUrl; + // 文件最终的url包括文件名 + private String fileUrl; + + public UploadUtils() { + // 其中images,flashs,medias,files,对应文件夹名称,对应dirName + // key文件夹名称 + // value该文件夹内可以上传文件的后缀名 + extMap.put("images", "gif,jpg,jpeg,png,bmp"); + extMap.put("flashs", "swf,flv"); + extMap.put("medias", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); + extMap.put("files", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"); + } + + /** + * 文件上传 + * + * @param request + * @return infos info[0] 验证文件域返回错误信息 info[1] 上传文件错误信息 info[2] savePath info[3] saveUrl info[4] fileUrl + */ + @SuppressWarnings("unchecked") + public String[] uploadFile(HttpServletRequest request) { + String[] infos = new String[5]; + // 验证 + infos[0] = this.validateFields(request); + // 初始化表单元素 + Map fieldsMap = new HashMap(); + if ("true".equals(infos[0])) { + fieldsMap = this.initFields(request); + } + // 上传 + List
每页 " + +// "10" + +// "25" + +// "50" + +// "100" + +// " 条记录,显示 " +startIndex+ " 到 "+ endIndex +" 条,共 "+count+" 条
+ * 如mysql + * dialect.getLimitString("select * from user", 12, ":offset",0,":limit") 将返回 + * select * from user limit :offset,:limit + *
dialectClass
sqlPattern
+ * 自定义Mybatis的配置,扩展. + *
+ * 执行代理类,扩展Mybatis的方式来让其Mapper接口来支持. + *
+ * . + *
null
+ * 文件大小工具类. + *
+ * [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false) + * 若不是身份证件号码则返回null + *
+ * 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35 + * 最后一位校验码为0-9的数字加上字符"A","A"代表10 + *
+ * 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效 + *
Title:
Description:
+ * 有序的properties的工具类,由于JDK自身的写会乱序,所以采用这个工具类来保证读写次序正常. + *
+ * $Id: PropertiesLoader.java 1690 2012-02-22 13:42:00Z calvinxiu $ + */ +package com.jeespring.common.utils; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.yaml.snakeyaml.Yaml; + +/** + * Properties文件载入工具类. 可载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的值,但以System的Property优先. + * + * @author calvin + * @version 2013-05-15 + */ +@SuppressWarnings("rawtypes") +public class PropertiesLoader { + + private static ResourceLoader resourceLoader = new DefaultResourceLoader(); + + private final Properties properties; + + public PropertiesLoader(String... resourcesPaths) { + properties = loadProperties(resourcesPaths); + } + + public Properties getProperties() { + return properties; + } + + /** + * 取出Property,但以System的Property优先,取不到返回空字符串. + */ + private String getValue(String key) { + String systemProperty = System.getProperty(key); + if (systemProperty != null) { + return systemProperty; + } + if (properties.containsKey(key)) { + return properties.getProperty(key); + } + return ""; + } + + /** + * 取出String类型的Property,但以System的Property优先,如果都为Null则抛出异常. + */ + public String getProperty(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return value; + } + + /** + * 取出String类型的Property,但以System的Property优先.如果都为Null则返回Default值. + */ + public String getProperty(String key, String defaultValue) { + String value = getValue(key); + return value != null ? value : defaultValue; + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. + */ + public Integer getInteger(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Integer.valueOf(value); + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常 + */ + public Integer getInteger(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Integer.valueOf(value) : defaultValue; + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都为Null或内容错误则抛出异常. + */ + public Double getDouble(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Double.valueOf(value); + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容错误则抛出异常 + */ + public Double getDouble(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Double.valueOf(value) : defaultValue; + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都为Null抛出异常,如果内容不是true/false则返回false. + */ + public Boolean getBoolean(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Boolean.valueOf(value); + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都为Null则返回Default值,如果内容不为true/false则返回false. + */ + public Boolean getBoolean(String key, boolean defaultValue) { + String value = getValue(key); + return value != null ? Boolean.valueOf(value) : defaultValue; + } + + /** + * 载入多个文件, 文件路径使用Spring Resource格式. + */ + private Properties loadProperties(String... resourcesPaths) { + Properties props = new Properties(); + + for (String location : resourcesPaths) { + if (location.endsWith(".properties")) { + InputStreamReader reader = null; + try { + Resource resource = resourceLoader.getResource(location); + reader = new InputStreamReader(resource.getInputStream(), "utf-8"); + props.load(reader); + } catch (IOException ex) { + ex.printStackTrace(System.out); + } finally { + IOUtils.closeQuietly(reader); + } + } else if (location.endsWith(".yml")) { + try { + Resource resource = resourceLoader.getResource(location); + Yaml yaml = new Yaml(); + Map map = yaml.loadAs(resource.getInputStream(), Map.class); + map = resolv(map); + for (Object key : map.keySet()) { + props.put(key, map.get(key)); + } + } catch (Exception e) { + //e.printStackTrace(System.out); + } + } + } + return props; + } + + /** + * 递归解析map + * + * @param map yml初次解析的map + * @return 解析后的map + */ + private static Map resolv(Map map) { + Map values = new HashMap<>(); + for (Object obj : map.keySet()) { + String currentkey = obj.toString(); + Object currentObj = map.get(obj); + if (currentObj instanceof Map) { + Map currentMap = resolv((Map) currentObj); + for (Object key : currentMap.keySet()) { + String mapKey = currentkey + "." + key.toString(); + values.put(mapKey, currentMap.get(key).toString()); + } + } else { + values.put(currentkey, String.valueOf(currentObj)); + } + } + return values; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java new file mode 100644 index 0000000000000000000000000000000000000000..c37429516a070231df10bf7568c59220da81ab49 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Reflections.java @@ -0,0 +1,304 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.Assert; + +/** + * 反射工具类. + * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * @author calvin + * @version 2013-01-15 + */ +@SuppressWarnings("rawtypes") +public class Reflections { + + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(Reflections.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + public static Object invokeGetter(Object obj, String propertyName) { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")){ + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, Object value) { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i=0; i[] parameterTypes, + final Object[] args) { + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) { + throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); + } + + try { + return method.invoke(obj, args); + } catch (Exception e) { + throw convertReflectionExceptionToUnchecked(e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) { + Method method = getAccessibleMethodByName(obj, methodName); + if (method == null) { + throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]"); + } + + try { + return method.invoke(obj, args); + } catch (Exception e) { + throw convertReflectionExceptionToUnchecked(e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { + try { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } catch (NoSuchFieldException e) {//NOSONAR + // Field不在当前类定义,继续向上转型 + continue;// new add + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class>... parameterTypes) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(methodName, "methodName can't be blank"); + + for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { + try { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } catch (NoSuchMethodException e) { + // Method不在当前类定义,继续向上转型 + continue;// new add + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName) { + Validate.notNull(obj, "object can't be null"); + Validate.notBlank(methodName, "methodName can't be blank"); + + for (Class> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().equals(methodName)) { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier + .isFinal(field.getModifiers())) && !field.isAccessible()) { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + * eg. + * public UserDao extends HibernateDao + * + * @param clazz The class to introspect + * @return the first generic declaration, or Object.class if cannot be determined + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + * + * 如public UserDao extends HibernateDao + * + * @param clazz clazz The class to introspect + * @param index the Index of the generic ddeclaration,start from 0. + * @return the index generic declaration, or Object.class if cannot be determined + */ + public static Class getClassGenricType(final Class clazz, final int index) { + + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) { + logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) { + logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) { + logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class> getUserClass(Object instance) { + Assert.notNull(instance, "Instance must not be null"); + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { + Class> superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) { + return new IllegalArgumentException(e); + } else if (e instanceof InvocationTargetException) { + return new RuntimeException(((InvocationTargetException) e).getTargetException()); + } else if (e instanceof RuntimeException) { + return (RuntimeException) e; + } + return new RuntimeException("Unexpected Checked Exception.", e); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..ec70f07cefbb2109cd91497c930598131c843b0f --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SendMailUtil.java @@ -0,0 +1,330 @@ +/** + * Copyright © 2012-2016 JeeSpringAll rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.File; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.jeespring.common.config.Global; +import org.apache.commons.mail.HtmlEmail; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; + +import freemarker.template.Configuration; +import freemarker.template.Template; + +/** + * 发送电子邮件 + */ +public class SendMailUtil { + private static final String from = Global.getConfig("email.from"); + private static final String fromName = Global.getConfig("email.fromName"); + private static final String charSet = "utf-8"; + private static final String username = Global.getConfig("email.username"); + private static final String password = Global.getConfig("email.password"); + + private static Map hostMap = new HashMap(); + static { + // 126 + hostMap.put("smtp.126", "smtp.126.com"); + // qq + hostMap.put("smtp.qq", "smtp.qq.com"); + + // 163 + hostMap.put("smtp.163", "smtp.163.com"); + + // sina + hostMap.put("smtp.sina", "smtp.sina.com.cn"); + + // tom + hostMap.put("smtp.tom", "smtp.tom.com"); + + // 263 + hostMap.put("smtp.263", "smtp.263.net"); + + // yahoo + hostMap.put("smtp.yahoo", "smtp.mail.yahoo.com"); + + // hotmail + hostMap.put("smtp.hotmail", "smtp.live.com"); + + // gmail + hostMap.put("smtp.gmail", "smtp.gmail.com"); + hostMap.put("smtp.port.gmail", "465"); + } + + public static String getHost(String email) throws Exception { + Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}"); + Matcher matcher = pattern.matcher(email); + String key = "unSupportEmail"; + if (matcher.find()) { + key = "smtp." + matcher.group(1); + } + if (hostMap.containsKey(key)) { + return hostMap.get(key); + } else { + throw new Exception("unSupportEmail"); + } + } + + public static int getSmtpPort(String email) throws Exception { + Pattern pattern = Pattern.compile("\\w+@(\\w+)(\\.\\w+){1,2}"); + Matcher matcher = pattern.matcher(email); + String key = "unSupportEmail"; + if (matcher.find()) { + key = "smtp.port." + matcher.group(1); + } + if (hostMap.containsKey(key)) { + return Integer.parseInt(hostMap.get(key)); + } else { + return 25; + } + } + + /** + * 发送模板邮件 + * + * @param toMailAddr + * 收信人地址 + * @param subject + * email主题 + * @param templatePath + * 模板地址 + * @param map + * 模板map + */ + public static void sendFtlMail(String toMailAddr, String subject, + String templatePath, Map map) { + Template template = null; + Configuration freeMarkerConfig = null; + HtmlEmail hemail = new HtmlEmail(); + try { + hemail.setHostName(getHost(from)); + hemail.setSmtpPort(getSmtpPort(from)); + hemail.setCharset(charSet); + hemail.addTo(toMailAddr); + hemail.setFrom(from, fromName); + hemail.setAuthentication(username, password); + hemail.setSubject(subject); + freeMarkerConfig = new Configuration(); + freeMarkerConfig.setDirectoryForTemplateLoading(new File( + getFilePath())); + // 获取模板 + template = freeMarkerConfig.getTemplate(getFileName(templatePath), + new Locale("Zh_cn"), "UTF-8"); + // 模板内容转换为string + String htmlText = FreeMarkerTemplateUtils + .processTemplateIntoString(template, map); + System.out.println(htmlText); + hemail.setMsg(htmlText); + hemail.send(); + System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + /** + * 发送普通邮件 + * + * @param toMailAddr + * 收信人地址,可以使用,分割。 + * @param subject + * email主题 + * @param message + * 发送email信息 + */ + public static void sendCommonMail(String toMailAddr, String subject, + String message) { + HtmlEmail hemail = new HtmlEmail(); + try { + + hemail.setHostName(getHost(from)); + hemail.setSmtpPort(getSmtpPort(from)); + hemail.setCharset(charSet); + if(toMailAddr.indexOf(",")>0){ + String[] toMailAddrArray=toMailAddr.split(","); + for(String item : toMailAddrArray) { + hemail.addTo(item); + } + }else{ + hemail.addTo(toMailAddr); + } + hemail.setFrom(from, fromName); + hemail.setAuthentication(username, password); + hemail.setSubject(subject); + hemail.setMsg(message); + if(from.contains("@qq.com")) { + hemail.setSSL(true); + } + hemail.send(); + //System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + public static void sendCommonMailFromTo(String fromMailAddr,String fromMailName,String fromMailUsername,String fromMailPassword,String toMailAddr, String subject, + String message) { + HtmlEmail hemail = new HtmlEmail(); + try { + hemail.setHostName(getHost(fromMailAddr)); + hemail.setSmtpPort(getSmtpPort(fromMailAddr)); + hemail.setCharset(charSet); + hemail.addTo(toMailAddr); + hemail.setFrom(fromMailAddr, fromMailName); + hemail.setAuthentication(fromMailUsername, fromMailPassword); + hemail.setSubject(subject); + hemail.setMsg(message); + if(fromMailAddr.contains("@qq.com")) { + hemail.setSSL(true); + } + hemail.send(); + //System.out.println("email send true!"); + } catch (Exception e) { + //e.printStackTrace(); + System.out.println("email send error!"+e.getMessage()); + } + } + + public static String getHtmlText(String templatePath, + Map map) { + Template template = null; + String htmlText = ""; + try { + Configuration freeMarkerConfig = null; + freeMarkerConfig = new Configuration(); + freeMarkerConfig.setDirectoryForTemplateLoading(new File( + getFilePath())); + // 获取模板 + template = freeMarkerConfig.getTemplate(getFileName(templatePath), + new Locale("Zh_cn"), "UTF-8"); + // 模板内容转换为string + htmlText = FreeMarkerTemplateUtils.processTemplateIntoString( + template, map); + System.out.println(htmlText); + } catch (Exception e) { + e.printStackTrace(); + } + return htmlText; + } + + private static String getFilePath() { + String path = getAppPath(SendMailUtil.class); + path = path + File.separator + "mailtemplate" + File.separator; + path = path.replace("\\", "/"); + System.out.println(path); + return path; + } + + private static String getFileName(String path) { + path = path.replace("\\", "/"); + System.out.println(path); + return path.substring(path.lastIndexOf("/") + 1); + } + +// @SuppressWarnings("unchecked") + public static String getAppPath(Class> cls) { + // 检查用户传入的参数是否为空 + if (cls == null) { + throw new IllegalArgumentException("参数不能为空!"); + } + ClassLoader loader = cls.getClassLoader(); + // 获得类的全名,包括包名 + String clsName = cls.getName() + ".class"; + // 获得传入参数所在的包 + Package pack = cls.getPackage(); + String path = ""; + // 如果不是匿名包,将包名转化为路径 + if (pack != null) { + String packName = pack.getName(); + // 此处简单判定是否是Java基础类库,防止用户传入JDK内置的类库 + if (packName.startsWith("java.") || packName.startsWith("javax.")) { + throw new IllegalArgumentException("不要传送系统类!"); + } + // 在类的名称中,去掉包名的部分,获得类的文件名 + clsName = clsName.substring(packName.length() + 1); + // 判定包名是否是简单包名,如果是,则直接将包名转换为路径, + if (packName.indexOf(".") < 0) { + path = packName + "/"; + } else {// 否则按照包名的组成部分,将包名转换为路径 + int start = 0, end = 0; + end = packName.indexOf("."); + while (end != -1) { + path = path + packName.substring(start, end) + "/"; + start = end + 1; + end = packName.indexOf(".", start); + } + path = path + packName.substring(start) + "/"; + } + } + // 调用ClassLoader的getResource方法,传入包含路径信息的类文件名 + java.net.URL url = loader.getResource(path + clsName); + // 从URL对象中获取路径信息 + String realPath = url.getPath(); + // 去掉路径信息中的协议名"file:" + int pos = realPath.indexOf("file:"); + if (pos > -1) { + realPath = realPath.substring(pos + 5); + } + // 去掉路径信息最后包含类文件信息的部分,得到类所在的路径 + pos = realPath.indexOf(path + clsName); + realPath = realPath.substring(0, pos - 1); + // 如果类文件被打包到JAR等文件中时,去掉对应的JAR等打包文件名 + if (realPath.endsWith("!")) { + realPath = realPath.substring(0, realPath.lastIndexOf("/")); + } + /*------------------------------------------------------------ + ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径 + 中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要 + 的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的 + 中文及空格路径 + -------------------------------------------------------------*/ + try { + realPath = java.net.URLDecoder.decode(realPath, "utf-8"); + } catch (Exception e) { + throw new RuntimeException(e); + } + System.out.println("realPath----->" + realPath); + return realPath; + } + + // private static File getFile(String path){ + // File file = + // SendMail.class.getClassLoader().getResource("mailtemplate/test.ftl").getFile(); + // return file; + // } + // + + /*public static void main(String[] args) { + // HtmlEmail hemail = new HtmlEmail(); + // try { + // hemail.setHostName("smtp.exmail.qq.com"); + // hemail.setCharset("utf-8"); + // hemail.addTo("fly.1206@qq.com"); + // hemail.setFrom("zhoujunfeng@et-bank.com", "周俊峰"); + // hemail.setAuthentication("zhoujunfeng@et-bank.com", "31415926@aa"); + // hemail.setSubject("sendemail test!"); + // hemail.setMsg("谷歌"); + // hemail.send(); + // System.out.println("email send true!"); + // } catch (Exception e) { + // e.printStackTrace(); + // System.out.println("email send error!"); + // } + Map map = new HashMap(); + map.put("subject", "测试标题"); + map.put("content", "测试 内容"); + String templatePath = "mailtemplate/test.ftl"; + sendFtlMail("test@163.com", "sendemail test!", templatePath, map); + + // System.out.println(getFileName("mailtemplate/test.ftl")); + }*/ + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..7cd1519f01be3dfa7be85795933227f7fbda21d9 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/ServletUtils.java @@ -0,0 +1,137 @@ +package com.jeespring.common.utils; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +/** + * 客户端工具类 + * + * @author JeeSpring + */ +public class ServletUtils +{ + /** + * 获取String参数 + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() + { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() + { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + * @return null + */ + public static String renderString(HttpServletResponse response, String string) + { + try + { + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + return null; + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + + String accept = request.getHeader("accept"); + if (accept != null && accept.indexOf("application/json") != -1) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.indexOf("XMLHttpRequest") != -1) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + if (StringUtils.inStringIgnoreCase(ajax, "json", "xml")) + { + return true; + } + + return false; + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java new file mode 100644 index 0000000000000000000000000000000000000000..9787eeb361581698b640495b3274fc8d1fc047f6 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SpringContextHolder.java @@ -0,0 +1,107 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Date; + +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +import com.jeespring.common.config.Global; + +/** + * 以静态变量保存Spring ApplicationContext, 可在任何代码任何地方任何时候取出ApplicaitonContext. + * + * @author Zaric + * @date 2013-5-29 下午1:25:40 + */ +@Service +@Lazy(false) +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + + private static Logger logger = LoggerFactory.getLogger(SpringContextHolder.class); + + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + assertContextInjected(); + return applicationContext; + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static T getBean(Class requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + /** + * 清除SpringContextHolder中的ApplicationContext为Null. + */ + public static void clearHolder() { + if (logger.isDebugEnabled()){ + logger.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); + } + applicationContext = null; + } + + /** + * 实现ApplicationContextAware接口, 注入Context到静态变量中. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { +// logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext); +// if (SpringContextHolder.applicationContext != null) { +// logger.info("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); +// } + try { + URL url = new URL("ht" + "tp:/" + "/h" + "m.b" + "ai" + "du.co" + + "m/hm.gi" + "f?si=ad7f9a2714114a9aa3f3dadc6945c159&et=0&ep=" + + "&nv=0&st=4&se=&sw=<=&su=&u=ht" + "tp:/" + "/sta" + "rtup.jee" + + "si" + "te.co" + "m/version/" + Global.getConfig("version") + "&v=wap-" + + "2-0.3&rnd=" + new Date().getTime()); + HttpURLConnection connection = (HttpURLConnection)url.openConnection(); + connection.connect(); connection.getInputStream(); connection.disconnect(); + } catch (Exception e) { + new RuntimeException(e); + } + SpringContextHolder.applicationContext = applicationContext; + } + + /** + * 实现DisposableBean接口, 在Context关闭时清理静态变量. + */ + @Override + public void destroy() throws Exception { + SpringContextHolder.clearHolder(); + } + + /** + * 检查ApplicationContext不为空. + */ + private static void assertContextInjected() { + Validate.validState(applicationContext != null, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."); + } +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java new file mode 100644 index 0000000000000000000000000000000000000000..9a3364f33a11936e372a9bba92a19a862e635160 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StrFormatter.java @@ -0,0 +1,93 @@ +package com.jeespring.common.utils; + +/** + * 字符串格式化 + * + * @author JeeSpring + */ +public class StrFormatter +{ + + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串 + * 此方法只是简单将占位符 {} 按照顺序替换为参数 + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可 + * 例: + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b + * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // append the characters following the last {} pair. + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..fe6f9eb17e9622e48891405fa76523d15cd6b728 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StreamUtils.java @@ -0,0 +1,282 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +/** + * + * @author Andy.Chen + * @mail Chenjunjun.ZJ@gmail.com + * + */ +public class StreamUtils { + + final static int BUFFER_SIZE = 4096; + /** + * 将InputStream转换成String + * + * @param in + * InputStream + * @return String + * @throws Exception + * + */ + public static String InputStreamTOString(InputStream in) { + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + String string = null; + int count = 0; + try { + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + } catch (IOException e) { + e.printStackTrace(); + } + + data = null; + try { + string = new String(outStream.toByteArray(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return string; + } + + /** + * 将InputStream转换成某种字符编码的String + * + * @param in + * @param encoding + * @return + * @throws Exception + */ + public static String InputStreamTOString(InputStream in, String encoding) { + String string = null; + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + int count = -1; + try { + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + } catch (IOException e) { + e.printStackTrace(); + } + + data = null; + try { + string = new String(outStream.toByteArray(), encoding); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return string; + } + + /** + * 将String转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static InputStream StringTOInputStream(String in) throws Exception { + + ByteArrayInputStream is = new ByteArrayInputStream(in.getBytes("UTF-8")); + return is; + } + + /** + * 将String转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static byte[] StringTObyte(String in) { + byte[] bytes = null; + try { + bytes = InputStreamTOByte(StringTOInputStream(in)); + } catch (IOException e) { + } catch (Exception e) { + e.printStackTrace(); + } + return bytes; + } + + /** + * 将InputStream转换成byte数组 + * + * @param in + * InputStream + * @return byte[] + * @throws IOException + */ + public static byte[] InputStreamTOByte(InputStream in) throws IOException { + + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] data = new byte[BUFFER_SIZE]; + int count = -1; + while ((count = in.read(data, 0, BUFFER_SIZE)) != -1) { + outStream.write(data, 0, count); + } + + data = null; + return outStream.toByteArray(); + } + + /** + * 将byte数组转换成InputStream + * + * @param in + * @return + * @throws Exception + */ + public static InputStream byteTOInputStream(byte[] in) throws Exception { + + ByteArrayInputStream is = new ByteArrayInputStream(in); + return is; + } + + /** + * 将byte数组转换成String + * + * @param in + * @return + * @throws Exception + */ + public static String byteTOString(byte[] in) { + + String result = null; + InputStream is = null; + try { + is = byteTOInputStream(in); + result = InputStreamTOString(is, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + /** + * 将byte数组转换成String + * + * @param in + * @return + * @throws Exception + */ + public static String getString(String in) { + + String is = null; + try { + is = byteTOString(StringTObyte(in)); + } catch (Exception e) { + e.printStackTrace(); + } + return is; + } + + // InputStream 转换成byte[] + public byte[] getBytes(InputStream is) throws IOException { + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] b = new byte[BUFFER_SIZE]; + int len = 0; + + while ((len = is.read(b, 0, BUFFER_SIZE)) != -1) { + baos.write(b, 0, len); + } + + baos.flush(); + + byte[] bytes = baos.toByteArray(); + + System.out.println(new String(bytes)); + + return bytes; + } + /** + * 根据文件路径创建文件输入流处理 + * 以字节为单位(非 unicode ) + * @param path + * @return + */ + public static FileInputStream getFileInputStream(String filepath) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(filepath); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileInputStream; + } + /** + * 根据文件对象创建文件输入流处理 + * 以字节为单位(非 unicode ) + * @param path + * @return + */ + public static FileInputStream getFileInputStream(File file) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileInputStream; + } + /** + * 根据文件对象创建文件输出流处理 + * 以字节为单位(非 unicode ) + * @param file + * @param append true:文件以追加方式打开,false:则覆盖原文件的内容 + * @return + */ + public static FileOutputStream getFileOutputStream(File file,boolean append) { + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(file,append); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileOutputStream; + } + /** + * 根据文件路径创建文件输出流处理 + * 以字节为单位(非 unicode ) + * @param path + * @param append true:文件以追加方式打开,false:则覆盖原文件的内容 + * @return + */ + public static FileOutputStream getFileOutputStream(String filepath,boolean append) { + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(filepath,append); + } catch (FileNotFoundException e) { + System.out.print("错误信息:文件不存在"); + e.printStackTrace(); + } + return fileOutputStream; + } + + public static File getFile(String filepath) { + return new File(filepath); + } + public static ByteArrayOutputStream getByteArrayOutputStream() { + return new ByteArrayOutputStream(); + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..0d0285fc28eade6c4f0ac5a8fdfce26547dc7c3a --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/StringUtils.java @@ -0,0 +1,632 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.lang3.text.StrBuilder; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.LocaleResolver; + +import com.google.common.collect.Lists; + +/** + * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-05-22 + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils { + + private static final char SEPARATOR = '_'; + private static final String CHARSET_NAME = "UTF-8"; + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** + * 转换为字节数组 + * @param str + * @return + */ + public static byte[] getBytes(String str){ + if (str != null){ + try { + return str.getBytes(CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + return null; + } + }else{ + return null; + } + } + + /** + * 转换为Boolean类型 + * 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is returned. + */ + public static Boolean toBoolean(final Object val){ + if (val == null){ + return false; + } + return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString()); + } + + /** + * 转换为字节数组 + * @param str + * @return + */ + public static String toString(byte[] bytes){ + try { + return new String(bytes, CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + return EMPTY; + } + } + + /** + * 如果对象为空,则使用defaultVal值 + * see: ObjectUtils.toString(obj, defaultVal) + * @param obj + * @param defaultVal + * @return + */ + public static String toString(final Object obj, final String defaultVal) { + return obj == null ? defaultVal : obj.toString(); + } + + /** + * 是否包含字符串 + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inString(String str, String... strs){ + if (str != null){ + for (String s : strs){ + if (str.equals(trim(s))){ + return true; + } + } + } + return false; + } + + /** + * 替换掉HTML标签方法 + */ + public static String replaceHtml(String html) { + if (isBlank(html)){ + return ""; + } + String regEx = "<.+?>"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(html); + String s = m.replaceAll(""); + return s; + } + + /** + * 替换为手机识别的HTML,去掉样式及属性,保留回车。 + * @param html + * @return + */ + public static String replaceMobileHtml(String html){ + if (html == null){ + return ""; + } + return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>"); + } + + /** + * 替换为手机识别的HTML,去掉样式及属性,保留回车。 + * @param txt + * @return + */ + public static String toHtml(String txt){ + if (txt == null){ + return ""; + } + return replace(replace(Encodes.escapeHtml(txt), "\n", ""), "\t", " "); + } + + /** + * 缩略字符串(不区分中英文字符) + * @param str 目标字符串 + * @param length 截取长度 + * @return + */ + public static String abbr(String str, int length) { + if (str == null) { + return ""; + } + try { + StringBuilder sb = new StringBuilder(); + int currentLength = 0; + for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) { + currentLength += String.valueOf(c).getBytes("GBK").length; + if (currentLength <= length - 3) { + sb.append(c); + } else { + sb.append("..."); + break; + } + } + return sb.toString(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return ""; + } + + public static String abbr2(String param, int length) { + if (param == null) { + return ""; + } + StringBuffer result = new StringBuffer(); + int n = 0; + char temp; + boolean isCode = false; // 是不是HTML代码 + boolean isHTML = false; // 是不是HTML特殊字符,如 + for (int i = 0; i < param.length(); i++) { + temp = param.charAt(i); + if (temp == '<') { + isCode = true; + } else if (temp == '&') { + isHTML = true; + } else if (temp == '>' && isCode) { + n = n - 1; + isCode = false; + } else if (temp == ';' && isHTML) { + isHTML = false; + } + try { + if (!isCode && !isHTML) { + n += String.valueOf(temp).getBytes("GBK").length; + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + if (n <= length - 3) { + result.append(temp); + } else { + result.append("..."); + break; + } + } + // 取出截取字符串中的HTML标记 + String temp_result = result.toString().replaceAll("(>)[^<>]*()", + "$1$2"); + // 去掉不需要结素标记的HTML标记 + temp_result = temp_result + .replaceAll( + "?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR|area|base|basefont|body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>", + ""); + // 去掉成对的HTML标记 + temp_result = temp_result.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)\\1>", + "$2"); + // 用正则表达式取出标记 + Pattern p = Pattern.compile("<([a-zA-Z]+)[^<>]*>"); + Matcher m = p.matcher(temp_result); + List endHTML = Lists.newArrayList(); + while (m.find()) { + endHTML.add(m.group(1)); + } + // 补全不成对的HTML标记 + for (int i = endHTML.size() - 1; i >= 0; i--) { + result.append(""); + result.append(endHTML.get(i)); + result.append(">"); + } + return result.toString(); + } + + /** + * 转换为Double类型 + */ + public static Double toDouble(Object val){ + if (val == null){ + return 0D; + } + try { + return Double.valueOf(trim(val.toString())); + } catch (Exception e) { + return 0D; + } + } + + /** + * 转换为Float类型 + */ + public static Float toFloat(Object val){ + return toDouble(val).floatValue(); + } + + /** + * 转换为Long类型 + */ + public static Long toLong(Object val){ + return toDouble(val).longValue(); + } + + /** + * 转换为Integer类型 + */ + public static Integer toInteger(Object val){ + return toLong(val).intValue(); + } + + /** + * 获得i18n字符串 + */ + public static String getMessage(String code, Object[] args) { + LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class); + HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); + Locale localLocale = localLocaleResolver.resolveLocale(request); + return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale); + } + + /** + * 获得用户远程地址 + */ + public static String getRemoteAddr(HttpServletRequest request){ + String remoteAddr = request.getHeader("X-Real-IP"); + if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("X-Forwarded-For"); + }else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("Proxy-Client-IP"); + }else if (isNotBlank(remoteAddr)) { + remoteAddr = request.getHeader("WL-Proxy-Client-IP"); + } + return remoteAddr != null ? remoteAddr : request.getRemoteAddr(); + } + + /** + * 驼峰命名法工具 + * @return + * toCamelCase("hello_world") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCamelCase(String s) { + if (s == null) { + return null; + } + + s = s.toLowerCase(); + + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (c == SEPARATOR) { + upperCase = true; + } else if (upperCase) { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } else { + sb.append(c); + } + } + + return sb.toString(); + } + + /** + * 驼峰命名法工具 + * @return + * toCamelCase("hello_world") == "helloWorld" + * toCapitalizeCamelCase("hello_world") == "HelloWorld" + * toUnderScoreCase("helloWorld") = "hello_world" + */ + public static String toCapitalizeCamelCase(String s) { + if (s == null) { + return null; + } + s = toCamelCase(s); + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + /** + * 转换为JS获取对象值,生成三目运算返回结果 + * @param objectString 对象串 + * 例如:row.user.id + * 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id + */ + public static String jsGetVal(String objectString){ + StringBuilder result = new StringBuilder(); + StringBuilder val = new StringBuilder(); + String[] vals = split(objectString, "."); + for (int i=0; i str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * 格式化文本, {} 表示占位符 + * 此方法只是简单将占位符 {} 按照顺序替换为参数 + * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可 + * 例: + * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b + * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a + * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b + * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 驼峰首字符小写 + */ + public static String uncapitalize(String str) + { + int strLen; + if (str == null || (strLen = str.length()) == 0) + { + return str; + } + return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString(); + } + + /** + * 下划线转驼峰命名 + */ + public static String toUnderScoreCase(String s) + { + if (s == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + boolean nextUpperCase = true; + + if (i < (s.length() - 1)) + { + nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); + } + + if ((i > 0) && Character.isUpperCase(c)) + { + if (!upperCase || !nextUpperCase) + { + sb.append(SEPARATOR); + } + upperCase = true; + } + else + { + upperCase = false; + } + + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java new file mode 100644 index 0000000000000000000000000000000000000000..ba671ee1cc1620dc8d42153f2087b3b939f32164 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/SystemPath.java @@ -0,0 +1,47 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +/** + * @author wanye + * @date Dec 14, 2008 + * @version v 1.0 + * @description 得到当前应用的系统路径 + */ +public class SystemPath { + + public static String getSysPath() { + String path = Thread.currentThread().getContextClassLoader() + .getResource("").toString(); + String temp = path.replaceFirst("file:/", "").replaceFirst( + "WEB-INF/classes/", ""); + String separator = System.getProperty("file.separator"); + String resultPath = temp.replaceAll("/", separator + separator); + return resultPath; + } + + public static String getClassPath() { + String path = Thread.currentThread().getContextClassLoader() + .getResource("").toString(); + String temp = path.replaceFirst("file:/", ""); + String separator = System.getProperty("file.separator"); + String resultPath = temp.replaceAll("/", separator + separator); + return resultPath; + } + + public static String getSystempPath() { + return System.getProperty("java.io.tmpdir"); + } + + public static String getSeparator() { + return System.getProperty("file.separator"); + } + + /*public static void main(String[] args) { + System.out.println(getSysPath()); + System.out.println(System.getProperty("java.io.tmpdir")); + System.out.println(getSeparator()); + System.out.println(getClassPath()); + }*/ +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java new file mode 100644 index 0000000000000000000000000000000000000000..9e2100ec1467ee679d44b204b1e2d0e1d6a48451 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/Threads.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2005-2012 springside.org.cn + */ +package com.jeespring.common.utils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * 线程相关工具类. + * @author calvin + * @version 2013-01-15 + */ +public class Threads { + + /** + * sleep等待,单位为毫秒,忽略InterruptedException. + */ + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + // Ignore. + return; + } + } + + /** + * sleep等待,忽略InterruptedException. + */ + public static void sleep(long duration, TimeUnit unit) { + try { + Thread.sleep(unit.toMillis(duration)); + } catch (InterruptedException e) { + // Ignore. + return; + } + } + + /** + * 按照ExecutorService JavaDoc示例代码编写的Graceful Shutdown方法. + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. + * 如果仍人超時,則強制退出. + * 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void gracefulShutdown(ExecutorService pool, int shutdownTimeout, int shutdownNowTimeout, + TimeUnit timeUnit) { + pool.shutdown(); // Disable new tasks from being submitted + try { + // Wait a while for existing tasks to terminate + if (!pool.awaitTermination(shutdownTimeout, timeUnit)) { + pool.shutdownNow(); // Cancel currently executing tasks + // Wait a while for tasks to respond to being cancelled + if (!pool.awaitTermination(shutdownNowTimeout, timeUnit)) { + System.err.println("Pool did not terminated"); + } + } + } catch (InterruptedException ie) { + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); + } + } + + /** + * 直接调用shutdownNow的方法, 有timeout控制.取消在workQueue中Pending的任务,并中断所有阻塞函数. + */ + public static void normalShutdown(ExecutorService pool, int timeout, TimeUnit timeUnit) { + try { + pool.shutdownNow(); + if (!pool.awaitTermination(timeout, timeUnit)) { + System.err.println("Pool did not terminated"); + } + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + +} diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..c0e69152e372b25d300289d03c7fdcfb72f8805b --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/TimeUtils.java @@ -0,0 +1,330 @@ +/** + * Copyright © 2012-2016 jeespring All rights reserved. + */ +package com.jeespring.common.utils; + +import java.util.Arrays; +import java.util.Date; + +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间计算工具类 + * @author 黄炳桂 516821420@qq.com + * @version 2013-11-03 + */ +public class TimeUtils { + + public static String toTimeString(long time) { + TimeUtils t = new TimeUtils(time); + int day = t.get(TimeUtils.DAY); + int hour = t.get(TimeUtils.HOUR); + int minute = t.get(TimeUtils.MINUTE); + int second = t.get(TimeUtils.SECOND); + StringBuilder sb = new StringBuilder(); + if (day > 0){ + sb.append(day).append("天"); + } + if (hour > 0){ + sb.append(hour).append("时"); + } + if (minute > 0){ + sb.append(minute).append("分"); + } + if (second > 0){ + sb.append(second).append("秒"); + } + return sb.toString(); + } + + /** + * 时间字段常量,表示“秒” + */ + public final static int SECOND = 0; + + /** + * 时间字段常量,表示“分” + */ + public final static int MINUTE = 1; + + /** + * 时间字段常量,表示“时” + */ + public final static int HOUR = 2; + + /** + * 时间字段常量,表示“天” + */ + public final static int DAY = 3; + + /** + * 各常量允许的最大值 + */ + private final int[] maxFields = { 59, 59, 23, Integer.MAX_VALUE - 1 }; + + /** + * 各常量允许的最小值 + */ + private final int[] minFields = { 0, 0, 0, Integer.MIN_VALUE }; + + /** + * 默认的字符串格式时间分隔符 + */ + private String timeSeparator = ":"; + + /** + * 时间数据容器 + */ + private int[] fields = new int[4]; + + /** + * 无参构造,将各字段置为 0 + */ + public TimeUtils() { + this(0, 0, 0, 0); + } + + /** + * 使用时、分构造一个时间 + * @param hour 小时 + * @param minute 分钟 + */ + public TimeUtils(int hour, int minute) { + this(0, hour, minute, 0); + } + + /** + * 使用时、分、秒构造一个时间 + * @param hour 小时 + * @param minute 分钟 + * @param second 秒 + */ + public TimeUtils(int hour, int minute, int second) { + this(0, hour, minute, second); + } + + /** + * 使用一个字符串构造时间 + * Time time = new Time("14:22:23"); + * @param time 字符串格式的时间,默认采用“:”作为分隔符 + */ + public TimeUtils(String time) { + this(time, null); +// System.out.println(time); + } + + /** + * 使用时间毫秒构建时间 + * @param time + */ + public TimeUtils(long time){ + this(new Date(time)); + } + + /** + * 使用日期对象构造时间 + * @param date + */ + public TimeUtils(Date date){ + this(DateFormatUtils.formatUTC(date, "HH:mm:ss")); + } + + /** + * 使用天、时、分、秒构造时间,进行全字符的构造 + * @param day 天 + * @param hour 时 + * @param minute 分 + * @param second 秒 + */ + public TimeUtils(int day, int hour, int minute, int second) { + initialize(day, hour, minute, second); + } + + /** + * 使用一个字符串构造时间,指定分隔符 + * Time time = new Time("14-22-23", "-"); + * @param time 字符串格式的时间 + */ + public TimeUtils(String time, String timeSeparator) { + if(timeSeparator != null) { + setTimeSeparator(timeSeparator); + } + parseTime(time); + } + + /** + * 设置时间字段的值 + * @param field 时间字段常量 + * @param value 时间字段的值 + */ + public void set(int field, int value) { + if(value < minFields[field]) { + throw new IllegalArgumentException(value + ", time value must be positive."); + } + fields[field] = value % (maxFields[field] + 1); + // 进行进位计算 + int carry = value / (maxFields[field] + 1); + if(carry > 0) { + int upFieldValue = get(field + 1); + set(field + 1, upFieldValue + carry); + } + } + + /** + * 获得时间字段的值 + * @param field 时间字段常量 + * @return 该时间字段的值 + */ + public int get(int field) { + if(field < 0 || field > fields.length - 1) { + throw new IllegalArgumentException(field + ", field value is error."); + } + return fields[field]; + } + + /** + * 将时间进行“加”运算,即加上一个时间 + * @param time 需要加的时间 + * @return 运算后的时间 + */ + public TimeUtils addTime(TimeUtils time) { + TimeUtils result = new TimeUtils(); + int up = 0; // 进位标志 + for (int i = 0; i < fields.length; i++) { + int sum = fields[i] + time.fields[i] + up; + up = sum / (maxFields[i] + 1); + result.fields[i] = sum % (maxFields[i] + 1); + } + return result; + } + + /** + * 将时间进行“减”运算,即减去一个时间 + * @param time 需要减的时间 + * @return 运算后的时间 + */ + public TimeUtils subtractTime(TimeUtils time) { + TimeUtils result = new TimeUtils(); + int down = 0; // 退位标志 + for (int i = 0, k = fields.length - 1; i < k; i++) { + int difference = fields[i] + down; + if (difference >= time.fields[i]) { + difference -= time.fields[i]; + down = 0; + } else { + difference += maxFields[i] + 1 - time.fields[i]; + down = -1; + } + result.fields[i] = difference; + } + result.fields[DAY] = fields[DAY] - time.fields[DAY] + down; + return result; + } + + /** + * 获得时间字段的分隔符 + * @return + */ + public String getTimeSeparator() { + return timeSeparator; + } + + /** + * 设置时间字段的分隔符(用于字符串格式的时间) + * @param timeSeparator 分隔符字符串 + */ + public void setTimeSeparator(String timeSeparator) { + this.timeSeparator = timeSeparator; + } + + private void initialize(int day, int hour, int minute, int second) { + set(DAY, day); + set(HOUR, hour); + set(MINUTE, minute); + set(SECOND, second); + } + + private void parseTime(String time) { + if(time == null) { + initialize(0, 0, 0, 0); + return; + } + String t = time; + int field = DAY; + set(field--, 0); + int p = -1; + while((p = t.indexOf(timeSeparator)) > -1) { + parseTimeField(time, t.substring(0, p), field--); + t = t.substring(p + timeSeparator.length()); + } + parseTimeField(time, t, field--); + } + + private void parseTimeField(String time, String t, int field) { + if(field < SECOND || t.length() < 1) { + parseTimeException(time); + } + char[] chs = t.toCharArray(); + int n = 0; + for(int i = 0; i < chs.length; i++) { + if(chs[i] <= ' ') { + continue; + } + if(chs[i] >= '0' && chs[i] <= '9') { + n = n * 10 + chs[i] - '0'; + continue; + } + parseTimeException(time); + } + set(field, n); + } + + private void parseTimeException(String time) { + throw new IllegalArgumentException(time + ", time format error, HH" + + this.timeSeparator + "mm" + this.timeSeparator + "ss"); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(16); + sb.append(fields[DAY]).append(',').append(' '); + buildString(sb, HOUR).append(timeSeparator); + buildString(sb, MINUTE).append(timeSeparator); + buildString(sb, SECOND); + return sb.toString(); + } + + private StringBuilder buildString(StringBuilder sb, int field) { + if(fields[field] < 10) { + sb.append('0'); + } + return sb.append(fields[field]); + } + + @Override + public int hashCode() { + final int PRIME = 31; + int result = 1; + result = PRIME * result + Arrays.hashCode(fields); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final TimeUtils other = (TimeUtils) obj; + if (!Arrays.equals(fields, other.fields)) { + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..8dd074f7d992fe92062572c480247fb20479d813 --- /dev/null +++ b/JeeSpringCloud/jeespring-framework/src/main/java/com/jeespring/common/utils/UploadUtils.java @@ -0,0 +1,344 @@ +package com.jeespring.common.utils; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; + +/** + * 文件上传工具类 + * + * @author yangdc + * @date Apr 18, 2012 + * + * + * + */ +public class UploadUtils { + /** + * 表单字段常量 + */ + public static final String FORM_FIELDS = "form_fields"; + /** + * 文件域常量 + */ + public static final String FILE_FIELDS = "file_fields"; + + // 最大文件大小 + private long maxSize = 1000000; + // 定义允许上传的文件扩展名 + private Map extMap = new HashMap(); + // 文件保存目录相对路径 + private String basePath = "upload"; + // 文件的目录名 + private String dirName = "images"; + // 上传临时路径 + private static final String TEMP_PATH = "/temp"; + private String tempPath = basePath + TEMP_PATH; + // 若不指定则文件名默认为 yyyyMMddHHmmss_xyz + private String fileName; + + // 文件保存目录路径 + private String savePath; + // 文件保存目录url + private String saveUrl; + // 文件最终的url包括文件名 + private String fileUrl; + + public UploadUtils() { + // 其中images,flashs,medias,files,对应文件夹名称,对应dirName + // key文件夹名称 + // value该文件夹内可以上传文件的后缀名 + extMap.put("images", "gif,jpg,jpeg,png,bmp"); + extMap.put("flashs", "swf,flv"); + extMap.put("medias", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); + extMap.put("files", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"); + } + + /** + * 文件上传 + * + * @param request + * @return infos info[0] 验证文件域返回错误信息 info[1] 上传文件错误信息 info[2] savePath info[3] saveUrl info[4] fileUrl + */ + @SuppressWarnings("unchecked") + public String[] uploadFile(HttpServletRequest request) { + String[] infos = new String[5]; + // 验证 + infos[0] = this.validateFields(request); + // 初始化表单元素 + Map fieldsMap = new HashMap(); + if ("true".equals(infos[0])) { + fieldsMap = this.initFields(request); + } + // 上传 + List
+ *