ssm其它

ssm其它

日志组件

1. 日志是什么

  • 日志是软件应用必备的组件,是程序debug,或是数据收集管理的重要依据,方便我们监测生产环境的变量值变化以及代码运行轨迹。本课程主要用来学习实际开发中常用的日志组件。
  • 主要是为了方便我们监测生产环境的变量值变化以及代码运行轨迹等。
  • 这些记录会被输出到我们指定的位置形成文件,帮助我们分析错误以及用户请求轨迹。

2. 常用日志组件

2.1 Log4j与log4j2.x

​ Log4j有8种不同的log级别,按照等级从低到高依次为:ALL>TRACE>DEBUG>INFO>WARN>ERROR>FATAL>OFF。如果配置为OFF级别,表示关闭log。

​ Log4j目前两个版本,log4j与log4j2。Log4j2的前身是log4j,它吸收了logback的设计,重新推出的一款新组件,且使用.xml/.json文件来替换了之前.properties来配置。Log4j2采用异步日志器,基于LMAX Disruptor库,相比较log4j高出10倍吞吐量。

​ Log4j支持两种格式的配置文件:properties和xml。包含三个主要的组件:Logger、appender、Layout。

2.2. 日志门面
2.2.1. Common-logging

​ Common-logging简称JCL,Common-logging是Apache提供的一个通用日志API,可以让应用程序不再依赖于具体的日志实现工具。该日志接口对其它一些日志工具,包括Log4J、Avalon LogKit、JUL等,进行了简单的包装,可以让应用程序在运行时,直接将日志适配到对应的日志实现工具中。

​ Common-logging通过动态查找的机制,在程序运行时自动找出真正使用的日志库。这一点与slf4j不同,slf4j是在编译时静态绑定真正的Log实现库。

2.2.2. Slf4j

​ SLF4J全称The Simple Logging Facade for Java,简单日志门面,这个不是具体的日志解决方案,而是通过门面模式提供一些Java Logging API,类似于JCL。

​ 使用SLF4J日志门面时,如果需要使用某一种日志实现,则需要选择正确的SLF4J的jar包(称为日志桥接)。SLF4J提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统。

3. 使用

Log4j

1.导包

在这里插入图片描述

##log4j.properties

############ERROR	WARM	INFO	DEBUG#####################
##rootLogger=全局日志级别定义,输出位置1,输出位置2
log4j.rootLogger=INFO,CONSOLE,logfile,errfile,MAIL
############### CONSOLE OutPut ###############
#ConsoleAppender	FileAppender	DailyRollingFileAppender	RollingFileAppender	WriterAppender
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
#HTMLLayout		PatternLayout	SimpleLayout	TTCCLayout
##输出位置格式PatternLayout
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
##定义PatternLayout格式样式 
log4j.appender.CONSOLE.layout.ConversionPattern=%d %p [%c] - %m%n
############### Default Log Output #################
log4j.logger.logfile=INFO,logfile
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.Append=true
log4j.appender.logfile.Threshold=INFO
log4j.appender.logfile.File=D:/log/myweb.log
log4j.appender.logfile.MaxFileSize=51200KB
log4j.appender.logfile.MaxBackupIndex=5
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n

############### Custom Err Output #################
log4j.logger.errfile=ERROR,errfile
log4j.appender.errfile=org.apache.log4j.RollingFileAppender
log4j.appender.errfile.Append=true
log4j.appender.errfile.Threshold=ERROR
log4j.appender.errfile.File=${ssm.root}/WEB-INF/log/error.log
log4j.appender.errfile.MaxFileSize=51200KB
log4j.appender.errfile.MaxBackupIndex=5
log4j.appender.errfile.layout=org.apache.log4j.PatternLayout
log4j.appender.errfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n

############### MAIL Output #################
#log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
#log4j.appender.MAIL.Threshold=ERROR
#log4j.appender.MAIL.BufferSize=1
##smtp server addr
#log4j.appender.MAIL.SMTPHost=smtp.exmail.qq.com
##email title
#log4j.appender.MAIL.Subject=InterfaceErrorMessage
##email user from
#log4j.appender.MAIL.From=f@f.com
##email user noticegroup a@a.com,b@b.com
#log4j.appender.MAIL.To=a@a.com,b@b.com
##username
#log4j.appender.MAIL.SMTPUsername=f@f.com
##password
#log4j.appender.MAIL.SMTPPassword=Password
#log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
#log4j.appender.MAIL.layout.ConversionPattern=[InterfaceErrorMessage] [%p] [%d{yyyy-MM-dd HH:mm:ss}]  [ Class = %C | Method = %M | Line = %L ] | %m%n

 ############### Log4j SQL Output #################
##对某个包下定义日志级别 
log4j.logger.com.javasm=INFO
log4j.logger.org.springframework=INFO

#log4j.logger.com.ibatis = DEBUG,CONSOLE
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG

#log4j.logger.java.sql=DEBUG,CONSOLE
#log4j.logger.java.sql.Connection=DEBUG
#log4j.logger.java.sql.Statement=DEBUG
#log4j.logger.java.sql.PreparedStatement=DEBUG
#log4j.logger.java.sql.ResultSet=DEBUG

#log4j.logger.org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl=DEBUG

在这里插入图片描述

private Logger l = LogManager.getLogger(SysuserHandler.class);
l.debug("---debug信息--");
l.info("---info信息--");
l.warn("---warn信息--");
l.error("---error信息--");
Log4j2

1.导包

在这里插入图片描述

2.xml配置

<!-- log4j2.xml  直接放resource文件夹里就可以 -->

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
	<appenders>
		<!-- 控制台输出 -->
		<console name="Console" target="SYSTEM_OUT">
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %class %L %M -- %msg%n" />
		</console>

		<!-- fileName:输出路径 filePattern:命名规则 -->
		<RollingFile name="RollingFileDebug"
			fileName="D:/logs/debug.log"
			filePattern="D:/logs/$${date:yyyy-MM-dd}/debug-%d{yyyy-MM-dd}-%i.log">
			<Filters>
				<ThresholdFilter level="DEBUG" />
				<ThresholdFilter level="INFO" onMatch="DENY"
					onMismatch="NEUTRAL" />
			</Filters>
			<!-- 输出格式 -->
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %class{36} %L %M - %msg%n" />
			<Policies>
				<!-- 单个日志文件的大小限制 -->
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<!-- 最多保留20个日志文件 -->
			<DefaultRolloverStrategy max="20" />
		</RollingFile>

		<RollingFile name="RollingFileInfo"
			fileName="D:/logs/info.log"
			filePattern="D:/logs/$${date:yyyy-MM-dd}/info-%d{yyyy-MM-dd}-%i.log">
			<Filters>
				<ThresholdFilter level="INFO" />
				<ThresholdFilter level="WARN" onMatch="DENY"
					onMismatch="NEUTRAL" />
			</Filters>
			<!-- 输出格式 -->
			<PatternLayout
				pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n" />
			<Policies>
				<!-- SizeBasedTriggeringPolicy单个文件的大小限制 -->
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<!-- DefaultRolloverStrategy同一个文件下的最大文件数 -->
			<DefaultRolloverStrategy max="20" />
		</RollingFile>

		<RollingFile name="RollingFileWarn"
			fileName="D:/logs/warn.log"
			filePattern="D:/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
			<Filters>
				<ThresholdFilter level="WARN" />
				<ThresholdFilter level="ERROR" onMatch="DENY"
					onMismatch="NEUTRAL" />
			</Filters>
			<PatternLayout
				pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
			<Policies>
				<!--<TimeBasedTriggeringPolicy modulate="true" interval="1"/> -->
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<!--最多保留20个日志文件 -->
			<DefaultRolloverStrategy max="20" min="0" />
		</RollingFile>

		<RollingFile name="RollingFileError"
			fileName="D:/logs/error.log"
			filePattern="D:/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
			<Filters>
				<ThresholdFilter level="ERROR" />
				<ThresholdFilter level="FATAL" onMatch="DENY"
					onMismatch="NEUTRAL" />
			</Filters>
			<PatternLayout
				pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n" />
			<Policies>
				<!--<TimeBasedTriggeringPolicy modulate="true" interval="1"/> -->
				<SizeBasedTriggeringPolicy size="100 MB" />
			</Policies>
			<!--最多保留20个日志文件 -->
			<DefaultRolloverStrategy max="20" min="0" />
		</RollingFile>
	</appenders>

	<loggers>
	<!-- 程序员看的日志一般是异步日志,运营日志一般是同步日志 -->
		<!-- 异步日志 -->
		<!--过滤掉spring和mybatis的一些无用的debug信息 -->
		<!--<AsyncLogger name="org.springframework" level="error" includeLocation="true">-->
			<!--<AppenderRef ref="RollingFileError"></AppenderRef>-->
		<!--</AsyncLogger>-->
		<!--<AsyncLogger name="org.mybatis" level="error" includeLocation="true">-->
			<!--<AppenderRef ref="RollingFileError"></AppenderRef>-->
		<!--</AsyncLogger>-->
		<!--<AsyncLogger name="com.alibaba.druid" level="error"  includeLocation="true">-->
			<!--<AppenderRef ref="RollingFileError"></AppenderRef>-->
		<!--</AsyncLogger>-->
		<!---->
		<!--<AsyncLogger level="debug"  includeLocation="true">-->
			<!--<AppenderRef ref="RollingFileDebug"></AppenderRef>-->
			<!--<appender-ref ref="RollingFileWarn"/>-->
            <!--<appender-ref ref="RollingFileError"/>-->
            <!--<appender-ref ref="RollingFileFatal"/>-->
		<!--</AsyncLogger>-->

 		<!--<AsyncRoot level="info">-->
 			<!--<appender-ref ref="Console"/>-->
            <!--<appender-ref ref="RollingFileInfo"/>-->
        <!--</AsyncRoot>-->

		<!-- 同步日志 -->
		<!-- logger 局部日志控制 -->
		<logger name="org.springframework" level="error"></logger>
        <logger name="org.mybatis" level="error"></logger>
		<logger name="org.apache" level="error"></logger>

		<!-- root 全局日志控制 -->
        <root level="all">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileDebug"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
	</loggers>
</configuration>

3.使用

在这里插入图片描述

private Logger l = LogManager.getLogger(SysuserHandler.class);
l.debug("---debug信息--");
l.info("---info信息--");
l.warn("---warn信息--");
l.error("---error信息--");
Slf4j

1.导包(到时候换日志组件的时候 把所需换的jar包换掉就可以继续使用了)

在这里插入图片描述

2.使用

private  Logger l = LoggerFactory.getLogger(SysuserHandler.class);
l.debug("---debug信息--");
l.info("---info信息--");
l.warn("---warn信息--");
l.error("---error信息--");

redis缓存数据库

1.了解nosql起源

nosql:非关系型数据库,解决关系型数据库的数据存取瓶颈,大数据量的存储,频繁的查询行为。

NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

没有统一的标准,做不到学了一个nosql,其他的都可以会。

nosql数据大多数基于内存,但是因为内存不可靠,一般都会提供持久化机制,在启动服务端的时候,把持久化数据再次加载到内存。

2.nosql的几种常用的数据库.

KV数据库:key-value键值对数据库,ehcache与项目耦合,memcache独立部署服务器,redis

文档数据库:存的是bson对象数据,mongodb,能够取代mysql,基于内存,数据字段可扩展。尤其适合于数据分析行业。

列式数据库:HBase,大数据平台。尤其适合于超大数据量的存储。

图形数据库:数据关系拓扑图,适合于社交平台,论文系统。

3. Redis介绍

  • Redis介绍

Redis是一个key-value存储系统。

Redis是一种面向“键/值”对类型数据的分布式NoSQL数据库系统。

它支持存储的类型包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。

  • Redis特点

高性能,持久存储,适应高并发的应用场景。

相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。

Redis数据库完全在内存中,使用磁盘仅用于持久性。

Redis可以将数据复制到任意数量的从服务器

4. redis的使用场景以及带来的相关问题:

使用场景:解决分布式场景下数据共享问题(HttpSession共享);存储临时数据(验证码,文件下载数,用户积分,购物车);存储系统中常用数据缓存(系统用户信息,用户权限列表信息,字典项数据);消息队列(发短信,发邮件等耗时间的操作统统都可以放消息队列进行异步操作)

常用数据的缓存带来的问题:多数据源数据同步问题

​ 方案1:(增删改操作mysql数据库,清理缓存对应的数据;查询操作先查缓存,缓存没有,则查询数据库,把查询结果放缓存)

​ 方案2:(增删改操作mysql数据;查询操作先查缓存,缓存没有,则查询数据库,把查询结果放缓存,放缓存的时候给缓存数据设置有效期)

5.redis的环境搭建

  • 服务端:

    redis-server.exe:加载redis-windows.conf启动redis服务端

    redis-server.exe redis.windows.conf
    
    //可建一个6379.bat 里面放redis-server.exe redis.windows.conf 双击这个即可启动redis服务端
    

    redis-cli.exe:命令行客户端程序,用来连接服务端,执行指令

    redis-cli.exe -h ip地址 -p port端口 -a password密码
    //下面设置好的
    

    redis-check-aof.exe:检测aof持久化文件,修复该文件

    check-check-aof.exe --fix aop文件名
    

    redis-check-dump.exe:检测dump持久化文件,修改该文件

    redis-check-dump.exe --fix dump文件名
    

    redis-windows.conf:核心配置文件,配置端口,密码等信息。

    端口号(41):
    port 6379  
    
    默认数据库个数(113):
    databases 16
    
    RDB持久化策略(137):
    (900秒内有一个数据发生改变做一次持久化 300秒内有10个数据发生改变做一次持久化 ....)
    save 900 1
    save 300 10
    save 60 10000
    
    RDB持久化文件的名称和目录(172 182):
    dbfilename dump.rdb
    dir ./
    
    启动连接密码(386):
    requirepass foobared
    
    开启aof持久化(521):
    appendonly yes
    
    aop持久化文件的名称(524):
    appendfilename "appendonly.aof"
    
    aop文件的重写策略(590):
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    
  • 桌面可视化客户端程序:

    redis-desktop-manager

//补
redis的持久化策略
RDB持久化:存的是kv数据,按照策略保存,风险更大。
AOF持久化:存的是指令,每秒保存一次

6.redis的常用操作指令

redis的针对value的5种数据类型:

key:String

value:(1.string字符串 2.List列表 3.Hash哈希 4.Set集合 5.zSet排序集合),使用频率最多的就是String,Hash

相关指令:string

string:set/get/incr/decr/incrby/decrby/setex/setnx(分布式锁)/getset(复合指令)

1	SET key value  
设置指定 key 的值
2	GET key        
获取指定 key 的值。
3	INCR key
将 key 中储存的数字值增一。
4	INCRBY key increment
将 key 所储存的值加上给定的增量值(increment) 。
5	DECR key
将 key 中储存的数字值减一。
6	DECRBY key decrement
key 所储存的值减去给定的减量值(decrement) 。
7	SETEX key seconds value
将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)8	SETNX key value
只有在 key 不存在时设置 key 的值。
9   GETSET key value
将给定 key 的值设为 value ,并返回 key 的旧值(old value)
相关指令:list

适合存储列表性数据,消息队列,红包列表(特征:数据不改变只获取)

​ lpush/lpop/lrange/llen/lindex

1.  LPUSH key value1 [value2]           lpush e 1 2 3 4 5
将一个或多个值插入到列表头部
2	LPOP key
移出并获取列表的第一个元素
3	LRANGE key start stop
获取列表指定范围内的元素
4	LLEN key
获取列表长度
5	LINDEX key index
通过索引获取列表中的元素
相关指令:hash

适合于存储集合,系统用户集合(手机号做key,用户详情作为value)

​ hset/hget/hdel/hexists/hgetall/hkeys/hvals/hlen/hsetnx

0	HMSET key field1 value1 [field2 value2 ] 
//hmset h 0 "user:xiaoming,pass:0" 1 "user:xiaoming,pass:1"
同时将多个 field-value (-)对设置到哈希表 key 中。
1	HSET key field value            //hset g 1111 user:xiaoming,pass:1111
将哈希表 key 中的字段 field 的值设为 value 。
2	HGET key field
获取存储在哈希表中指定字段的值。
3	HDEL key field1 [field2]
删除一个或多个哈希表字段
4	HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。
5	HGETALL key
获取在哈希表中指定 key 的所有字段和值
6	HKEYS key
获取所有哈希表中的字段
7	HVALS key
获取哈希表中所有值。
8	HLEN key
获取哈希表中字段的数量
9	HSETNX key field value
只有在字段 field 不存在时,设置哈希表字段的值。
set无序集合

相对于list来说,数据无序,适合于做集合的交并差

​ sadd/spop/sdiff(差集)/sunion(并集)/sinter(交集)/smembers

1	SADD key member1 [member2]
向集合添加一个或多个成员
2	SPOP key
移除并返回集合中的一个随机元素
3	SDIFF key1 [key2]
返回第一个集合与其他集合之间的差异。
4	SUNION key1 [key2]
返回所有给定集合的并集
5	SINTER key1 [key2]
返回给定所有集合的交集
6	SMEMBERS key
返回集合中的所有成员
zset(sortedSet):

适合于数据需要按照指定的字段进行排序的场景。(排名榜单)

​ zadd

​ zscore:取得成绩

​ zrank:升序排序后的排名

​ zrevrank:降序排序后的排名

​ zcount:获取成绩区间的成员个数

​ zrange:获取升序排名区间的成员

​ zrevrange:获取降序排名区间的成员

​ zrangebyscore:获取成绩区间的成员

1	ZADD key score1 member1 [score2 member2]
//zadd scores 81 a 75 b 64 c 99 d 55 e 11 f
向有序集合添加一个或多个成员,或者更新已存在成员的分数
2	ZSCORE key member
返回有序集中,成员的分数值
3	ZRANK key member
返回有序集合中指定成员的索引
4	ZREVRANK key member
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
5	ZCOUNT key min max
计算在有序集合中指定区间分数的成员数
6	ZRANGE key start stop [WITHSCORES]
通过索引区间返回有序集合指定区间内的成员
7	ZREVRANGE key start stop [WITHSCORES]
返回有序集中指定区间内的成员,通过索引,分数从高到低
8	ZREVRANGEBYSCORE key max min [WITHSCORES]
返回有序集中指定分数区间内的成员,分数从高到低排序
相关指令:key

对key的操作:del/type/keys/ttl/expire/exists

1	DEL key
该命令用于在 key 存在时删除 key。
2	TYPE key
返回 key 所储存的值的类型。
3	KEYS pattern
查找所有符合给定模式( pattern)的 key 。
4	TTL key
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
5	EXPIRE key seconds
为给定 key 设置过期时间,以秒计。
6	EXISTS key
检查给定 key 是否存在。

7.redis的javaApi:

jedis:客户端组件

  • Jedis是Java连接Redis的驱动包,具备操作Redis的所有API,而且使用简单。
  • 引入jar包:
    • jedis-2.7.2.jar
    • commons-pool2-2.3.jar
  • jedis单机使用
    • 运行代码
public class TestJedis {
    public static void main(String[] args) {
        Jedis j = new Jedis("127.0.0.1",6379);
        j.auth("root");
        //key使用:分割,进行便于分组显示
        for(int i=0;i<1000;i++){
            j.set("users:"+i,i+"");  //"users:" 生成了一个users文件夹放users0,users0......
        }
        j.close();
    }
}
  • jedis多机使用
    • 多redis实例启动
      • 拷贝redis.windows.conf,修改新的端口为6380,启动第二个redis实例。
    • 运行代码
public class TestSharedJedis {
    public static void main(String[] args) {
        //维护多台redis服务器的连接信息
        JedisPoolConfig poolConfig  = new JedisPoolConfig();
        poolConfig.setMinIdle(5);           //最小空闲连接数

        List<JedisShardInfo> infos = new ArrayList<>();
        JedisShardInfo info1 =new JedisShardInfo("redis://xxx:root@127.0.0.1:6379/0");
        infos.add(info1);
        JedisShardInfo info2 = new JedisShardInfo("redis://xxx:root@127.0.0.1:6380/0");
        infos.add(info2);

        ShardedJedisPool pool  = new ShardedJedisPool(poolConfig,infos);//分片连接池
        //保存数据的时候,通过分片算法,把数据分到不同的服务器中进行存储。
        ShardedJedis jedis = pool.getResource();
        for(int i=0;i<1000;i++){
            jedis.set("key:"+i,i+"");//
        }
        pool.close();
    }
}

8.redis的集群搭建:

  • 客户端的分片集群方案

    服务端启动的多个redis服务之间没有任何关系,是独立的reids服务。

    代码调用者,通过维护多台redis服务的连接。

    缺点:服务器无法横向扩展(代码中维护服务器连接信息;当扩展了新服务器后,原服务器中的数据迁移难)

  • 服务端哨兵集群方案,第四阶段,可以横线扩展

    哨兵服务器(管理其他服务器)

    服务端启动的多个redis服务,服务器之间有数据交互通道。

  • 服务端cluster集群方案。

9. 客户端的分片集群方案简单应用

//redis.properties

jedis.minIdle=5
jedis.url1=redis://xxx:root@127.0.0.1:6379/0
jedis.url2=redis://xxx:root@127.0.0.1:6380/0
<!--redis.xml-->

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:comtext="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

 <!--ignore-unresolvable="true" 忽略不能识别的单词  另一个引入property文件的xml也要写这个-->
    <comtext:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"></comtext:property-placeholder>

    <!--生成 new JedisPoolConfig() bean对象  并注入参数 minIdle=5-->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="minIdle" value="${jedis.minIdle}"></property>
    </bean>

    <!--生成分片连接池对象  并注入参数(构造器注入)-->
    <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
        <!--注入第一个参数-->
        <constructor-arg index="0" ref="poolConfig"></constructor-arg>
        <!--注入第二个参数 -->
        <constructor-arg index="1">
            <list>
                <bean class="redis.clients.jedis.JedisShardInfo">
                    <constructor-arg index="0" value="${jedis.url1}"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.JedisShardInfo">
                    <constructor-arg index="0" value="${jedis.url2}"></constructor-arg>
                </bean>
            </list>
        </constructor-arg>
    </bean>

</beans>



<!--spring.mvc 要引入redis.xml-->
 <import resource="classpath:redis.xml"></import>
@Controller
@RequestMapping("user")
public class SysuserHandler {
    private Logger l = LoggerFactory.getLogger(SysuserHandler.class);

    @Resource
    private ISysuserService us;

    @PostMapping("login")
    public ResponseEntity login(@RequestBody Map<String,String> map, HttpSession session){
        String uphone = map.get("uphone");
        String valicode = map.get("valicode");
        //1. 校验验证按
        boolean isok = us.checkValicode(uphone,valicode);
        if(!isok){
           throw new MvcException(StatusEnum.VALICODE_ERROR);
        }
        
        //2.根据手机号取获取用户对象
        Sysuser loginuser = us.login(uphone);
        
        if(loginuser!=null){
            session.setAttribute("LOGIN_USER",loginuser);
            loginuser.setUpwd("");
            return ResponseEntity.ok(new ResponseBean(StatusEnum.LOGIN_SUC,loginuser));
        }
        throw new MvcException(StatusEnum.LOGIN_ERROR);
    }
}
@Service
public class SysuserServiceImpl implements ISysuserService {
    
   @Resource
    private SysuserMapper sm;

    @Resource
    private RedisService redisService;

    @Override
    //1. 校验验证码  RedisKey.VALI_CODE枚举类redis的数据key词头
    public boolean checkValicode(String uphone, String valicode) {
        //通过key从缓存取数据
        String serverCode = redisService.get(RedisKey.VALI_CODE + uphone);
        //为空返回false
        if(serverCode==null){
           return false;
        }
        //判断传来的验证码是否跟缓存里的验证码相同
        boolean isok = serverCode.equals(valicode);
        if(isok){
            //相同删除缓存里的验证码 保障安全性
            redisService.del(RedisKey.VALI_CODE+uphone);
            return true;
        }
        return false;
    }

    @Override
    public Sysuser login(String uphone) {
        Sysuser loginuser = null;
        //先查询缓存,查不到再查数据库,查到放缓存;
        /**
         * 要把用户集合保存hash
         * redisService.hset(RedisKey.USERS_HASH,uphone,JSON.toJsonString(Sysuser))
         */
        String userinfo = redisService.hget(RedisKey.USERS_HASH, uphone);
        if(userinfo==null){
            loginuser = sm.selectUserByPhone(uphone);
            if(loginuser==null)
            {
                //该手机号未注册
                loginuser = new Sysuser();
                loginuser.setUphone(uphone);
                loginuser.setUname("小哥哥");
                loginuser.setNewUser(1);
                loginuser.setUpwd("1111");
                loginuser.setRid(11);
                sm.addUserAndGetUserId(loginuser);
            }
            redisService.hset(RedisKey.USERS_HASH,uphone, JSON.toJSONString(loginuser));
        }else {
            //已有对象情况下
            //把json字符串转成对象
            //fastjson工具
            Sysuser sysuser = JSON.parseObject(userinfo,Sysuser.class);

            //Gson工具
            Gson g = new Gson();
            loginuser = g.fromJson(userinfo,Sysuser.class);
        }
        return loginuser;
    }
}


//补充
//1.json字符串转单个对象
//将json字符串转JSONObject对象
JSONObject jsonObject = JSON.parseObject(userinfo);
//将json字符串转具体对象
Sysuser sysuser = JSON.parseObject(userinfo,Sysuser.class);

//2.json集合字符串转集合对象
//fastjson工具转集合对象
List<Sysuser> list = JSON.parseArray(userinfo,Sysuser.class);
//Gson工具字符串转集合对象
Gson g = new Gson();
String s =  g.toJson(userinfo);
//老师写的一个RedisService服务类 收藏好 

package com.javasm.common.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.jedis.SortingParams;
import redis.clients.jedis.Tuple;

/**
 * Redis基类
 */
@Service
public class RedisService {
	private static final Logger log = LogManager.getLogger(RedisService.class);

	@Resource
	private ShardedJedisPool shardedJedisPool;

	/**
	 * 
	 * @Title: set @Description: 设置单个值 @param @param key @param @param
	 *         value @param @return @return String @throws
	 */
	public String set(String key, String value) {
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		String result = null;
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.set(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: get @Description: 获取单个值 @param @param key @param @return @return
	 *         String @throws
	 */
	public String get(String key) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.get(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: exists @Description: 确认一个key是否存在 @param @param
	 *         key @param @return @return Boolean @throws
	 */
	public Boolean exists(String key) {
		Boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.exists(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: type @Description: 返回值的类型 @param @param key @param @return @return
	 *         String @throws
	 */
	public String type(String key) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.type(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: expire @Description: 设定一个key的活动时间(s) @param @param key @param @param
	 *         seconds @param @return @return Long @throws
	 */
	public Long expire(String key, int seconds) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.expire(key, seconds);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: expireAt @Description: 在某个时间点失效 @param @param key @param @param
	 *         unixTime @param @return @return Long @throws
	 */
	public Long expireAt(String key, long unixTime) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.expireAt(key, unixTime);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: ttl @Description: 获得一个key的活动时间 @param @param
	 *         key @param @return @return Long @throws
	 */
	public Long ttl(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.ttl(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public boolean setbit(String key, long offset, boolean value) {

		boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setbit(key, offset, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public boolean getbit(String key, long offset) {

		boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getbit(key, offset);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public long setrange(String key, long offset, String value) {

		long result = 0;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setrange(key, offset, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String getrange(String key, long startOffset, long endOffset) {

		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getrange(key, startOffset, endOffset);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String getSet(String key, String value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getSet(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long setnx(String key, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setnx(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String setex(String key, int seconds, String value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setex(key, seconds, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long decrBy(String key, long integer) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.decrBy(key, integer);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long decr(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.decr(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long incrBy(String key, long integer) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.incrBy(key, integer);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long incr(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.incr(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long append(String key, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.append(key, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String substr(String key, int start, int end) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.substr(key, start, end);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hset(String key, String field, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hset(key, field, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String hget(String key, String field) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hget(key, field);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hsetnx(String key, String field, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hsetnx(key, field, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String hmset(String key, Map<String, String> hash) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hmset(key, hash);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<String> hmget(String key, String... fields) {
		List<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hmget(key, fields);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hincrBy(String key, String field, long value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hincrBy(key, field, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Boolean hexists(String key, String field) {
		Boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hexists(key, field);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long del(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.del(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hdel(String key, String field) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hdel(key, field);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hlen(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hlen(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> hkeys(String key) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hkeys(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<String> hvals(String key) {
		List<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hvals(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Map<String, String> hgetAll(String key) {
		Map<String, String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hgetAll(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	// ================list ====== l表示 list或 left, r表示right====================
	/**
	 * 
	 * @Title: rpush @Description: 在指定Key所关联的List
	 *         Value的尾部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的尾部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。 @param @param
	 *         key @param @param string @param @return @return Long @throws
	 */
	public Long rpush(String key, String string) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.rpush(key, string);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/**
	 * 
	 * @Title: lpush @Description: 在指定Key所关联的List
	 *         Value的头部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的头部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。 @param @param
	 *         key @param @param string @param @return @return Long @throws
	 */
	public Long lpush(String key, String string) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lpush(key, string);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long lpushx(String key, String string) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lpushx(key, string);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long llen(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.llen(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<String> lrange(String key, long start, long end) {
		List<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lrange(key, start, end);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String ltrim(String key, long start, long end) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.ltrim(key, start, end);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String lindex(String key, long index) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lindex(key, index);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String lset(String key, long index, String value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lset(key, index, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long lrem(String key, long count, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lrem(key, count, value);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String lpop(String key) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lpop(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String rpop(String key) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.rpop(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	// return 1 add a not exist value ,
	// return 0 add a exist value
	public Long sadd(String key, String member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sadd(key, member);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> smembers(String key) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.smembers(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long srem(String key, String member) {

		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.srem(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String spop(String key) {

		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.spop(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long scard(String key) {

		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.scard(key);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Boolean sismember(String key, String member) {

		Boolean result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sismember(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String srandmember(String key) {

		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.srandmember(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zadd(String key, double score, String member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zadd(key, score, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrange(String key, int start, int end) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrange(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrem(String key, String member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrem(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Double zincrby(String key, double score, String member) {
		Double result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zincrby(key, score, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrank(String key, String member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrank(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrevrank(String key, String member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrank(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrevrange(String key, int start, int end) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {

			result = shardedJedis.zrevrange(key, start, end);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeWithScores(String key, int start, int end) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeWithScores(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeWithScores(String key, int start, int end) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeWithScores(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zcard(String key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zcard(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Double zscore(String key, String member) {
		Double result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zscore(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<String> sort(String key) {
		List<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sort(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<String> sort(String key, SortingParams sortingParameters) {
		List<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sort(key, sortingParameters);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zcount(String key, double min, double max) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zcount(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrangeByScore(String key, double min, double max) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScore(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrevrangeByScore(String key, double max, double min) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScore(key, max, min);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrangeByScore(String key, double min, double max, int offset, int count) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScore(key, min, max, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<String> zrevrangeByScore(String key, double max, double min, int offset, int count) {
		Set<String> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScore(key, max, min, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScoreWithScores(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScoreWithScores(key, max, min);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, int offset, int count) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScoreWithScores(key, min, max, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, int offset, int count) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zremrangeByRank(String key, int start, int end) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zremrangeByRank(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zremrangeByScore(String key, double start, double end) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zremrangeByScore(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long linsert(String key, LIST_POSITION where, String pivot, String value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.linsert(key, where, pivot, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String set(byte[] key, byte[] value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.set(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] get(byte[] key) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.get(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Boolean exists(byte[] key) {
		Boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.exists(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String type(byte[] key) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.type(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long expire(byte[] key, int seconds) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.expire(key, seconds);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long expireAt(byte[] key, long unixTime) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.expireAt(key, unixTime);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long ttl(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.ttl(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] getSet(byte[] key, byte[] value) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getSet(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long setnx(byte[] key, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setnx(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String setex(byte[] key, int seconds, byte[] value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.setex(key, seconds, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long decrBy(byte[] key, long integer) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.decrBy(key, integer);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long decr(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.decr(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long incrBy(byte[] key, long integer) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.incrBy(key, integer);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long incr(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.incr(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long append(byte[] key, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.append(key, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] substr(byte[] key, int start, int end) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {

			result = shardedJedis.substr(key, start, end);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hset(byte[] key, byte[] field, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hset(key, field, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] hget(byte[] key, byte[] field) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hget(key, field);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hsetnx(byte[] key, byte[] field, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hsetnx(key, field, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String hmset(byte[] key, Map<byte[], byte[]> hash) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hmset(key, hash);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<byte[]> hmget(byte[] key, byte[]... fields) {
		List<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hmget(key, fields);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hincrBy(byte[] key, byte[] field, long value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hincrBy(key, field, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Boolean hexists(byte[] key, byte[] field) {
		Boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hexists(key, field);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hdel(byte[] key, byte[] field) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hdel(key, field);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long hlen(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hlen(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> hkeys(byte[] key) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hkeys(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Collection<byte[]> hvals(byte[] key) {
		Collection<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hvals(key);
		} catch (Exception e) {

			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Map<byte[], byte[]> hgetAll(byte[] key) {
		Map<byte[], byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.hgetAll(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long rpush(byte[] key, byte[] string) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.rpush(key, string);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long lpush(byte[] key, byte[] string) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lpush(key, string);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long llen(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.llen(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<byte[]> lrange(byte[] key, int start, int end) {
		List<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lrange(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String ltrim(byte[] key, int start, int end) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.ltrim(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] lindex(byte[] key, int index) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lindex(key, index);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String lset(byte[] key, int index, byte[] value) {
		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();

		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lset(key, index, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long lrem(byte[] key, int count, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lrem(key, count, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] lpop(byte[] key) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.lpop(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] rpop(byte[] key) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.rpop(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long sadd(byte[] key, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sadd(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> smembers(byte[] key) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.smembers(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long srem(byte[] key, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.srem(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] spop(byte[] key) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.spop(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long scard(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.scard(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Boolean sismember(byte[] key, byte[] member) {
		Boolean result = false;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sismember(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public byte[] srandmember(byte[] key) {
		byte[] result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.srandmember(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zadd(byte[] key, double score, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zadd(key, score, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrange(byte[] key, int start, int end) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrange(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrem(byte[] key, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrem(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Double zincrby(byte[] key, double score, byte[] member) {
		Double result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zincrby(key, score, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrank(byte[] key, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrank(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zrevrank(byte[] key, byte[] member) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrank(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrevrange(byte[] key, int start, int end) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrange(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeWithScores(byte[] key, int start, int end) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeWithScores(key, start, end);
		} catch (Exception e) {

			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeWithScores(byte[] key, int start, int end) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeWithScores(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zcard(byte[] key) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zcard(key);
		} catch (Exception e) {

			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Double zscore(byte[] key, byte[] member) {
		Double result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zscore(key, member);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<byte[]> sort(byte[] key) {
		List<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sort(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public List<byte[]> sort(byte[] key, SortingParams sortingParameters) {
		List<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.sort(key, sortingParameters);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zcount(byte[] key, double min, double max) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zcount(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrangeByScore(byte[] key, double min, double max) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScore(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrangeByScore(byte[] key, double min, double max, int offset, int count) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScore(key, min, max, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScoreWithScores(key, min, max);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrangeByScoreWithScores(byte[] key, double min, double max, int offset, int count) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrangeByScoreWithScores(key, min, max, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrevrangeByScore(byte[] key, double max, double min) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScore(key, max, min);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<byte[]> zrevrangeByScore(byte[] key, double max, double min, int offset, int count) {
		Set<byte[]> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScore(key, max, min, offset, count);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScoreWithScores(key, max, min);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Set<Tuple> zrevrangeByScoreWithScores(byte[] key, double max, double min, int offset, int count) {
		Set<Tuple> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zrevrangeByScoreWithScores(key, max, min, offset, count);
		} catch (Exception e) {

			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zremrangeByRank(byte[] key, int start, int end) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {

			result = shardedJedis.zremrangeByRank(key, start, end);

		} catch (Exception e) {

			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long zremrangeByScore(byte[] key, double start, double end) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.zremrangeByScore(key, start, end);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Long linsert(byte[] key, LIST_POSITION where, byte[] pivot, byte[] value) {
		Long result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.linsert(key, where, pivot, value);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	/*
	 * public List<Object> pipelined(ShardedJedisPipeline shardedJedisPipeline) {
	 * List<Object> result = null; if (shardedJedis == null) { return result; }
	 * boolean broken = false; try { result =
	 * shardedJedis.pipelined(shardedJedisPipeline); } catch (Exception e) {
	 * log.error(e.getMessage(), e); broken = true; } finally {
	 * redisDataSource.returnResource(shardedJedis, broken); } return result; }
	 */

	public Jedis getShard(byte[] key) {

		Jedis result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getShard(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Jedis getShard(String key) {

		Jedis result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getShard(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public JedisShardInfo getShardInfo(byte[] key) {

		JedisShardInfo result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getShardInfo(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public JedisShardInfo getShardInfo(String key) {

		JedisShardInfo result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getShardInfo(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public String getKeyTag(String key) {

		String result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getKeyTag(key);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Collection<JedisShardInfo> getAllShardInfo() {

		Collection<JedisShardInfo> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getAllShardInfo();

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}

	public Collection<Jedis> getAllShards() {

		Collection<Jedis> result = null;
		ShardedJedis shardedJedis = shardedJedisPool.getResource();
		if (shardedJedis == null) {
			return result;
		}
		try {
			result = shardedJedis.getAllShards();
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		} finally {
			shardedJedis.close();
		}
		return result;
	}
}

远程接口调用

在服务端去调用第三方远程的接口。

apache的HttpClient组件

  • 加httpClient的jar包

在这里插入图片描述

public class HttpClientUtil {
    public static String doGet(String path) throws Exception {
        String result = null;
        //http客户端,类似于postMan,浏览器
        CloseableHttpClient client = HttpClients.createDefault();
        //请求对象
        HttpGet request = new HttpGet(path);
        //添加请求头,当客户端关闭时,通知服务端该连接可释放
        request.setHeader("Connection","close");
        //发送请求,返回响应对象
        HttpResponse response = client.execute(request);
        //响应的状态行
        StatusLine statusLine = response.getStatusLine();
        HttpEntity respEntity = null;
        if(statusLine.getStatusCode()==HttpStatus.SC_OK){
            respEntity = response.getEntity();//响应体
            //读取响应体对象中的数据
            result= EntityUtils.toString(respEntity,"UTF-8");
        }
        //客户端释放资源,断开连接,通知服务端连接已断开
        if(respEntity!=null){
            EntityUtils.consume(respEntity);
        }
        if(response!=null){
            ((CloseableHttpResponse) response).close();
        }
        if(request!=null){
            request.abort();
        }
        if(client!=null){
            client.close();
        }
        return result;
    }

    public static String doPost(String path,Map<String,String> map) throws Exception {
        String result = null;
        //http客户端,类似于postMan,浏览器
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost request = new HttpPost(path);//请求对象
        //添加请求头,当客户端关闭时,通知服务端该连接可释放
        request.setHeader("Connection","close");

        //StringEntity,传递json字符串数据
        //UrlEncodedFormEntity,传递key=value数据
        HttpEntity requestEntity= new StringEntity(JSON.toJSONString(map),"UTF-8");
        request.setEntity(requestEntity);
        request.setHeader("Content-type","application/json");

        //发送请求,返回响应对象
        HttpResponse response = client.execute(request);
        //响应的状态行
        StatusLine statusLine = response.getStatusLine();
        HttpEntity respEntity = null;
        if(statusLine.getStatusCode()==HttpStatus.SC_OK){
            respEntity = response.getEntity();//响应体
            //读取响应体对象中的数据
            result= EntityUtils.toString(respEntity,"UTF-8");
        }
        //客户端释放资源,断开连接,通知服务端连接已断开
        if(respEntity!=null){
            EntityUtils.consume(respEntity);
        }
        if(response!=null){
            ((CloseableHttpResponse) response).close();
        }
        if(requestEntity!=null)
            EntityUtils.consume(requestEntity);
        if(request!=null){
            request.abort();
        }
        if(client!=null){
            client.close();
        }
        return result;
    }
}

--------------------------------------------------------------------------------
   //doPut  方法名字改掉  请求对象改  其他跟post一样
   public static String doPut(String path,Map<String,String> map) throws Exception {}
   HttpPut request = new HttpPut(path);//请求对象
   //doDel  方法名字改掉  请求对象改  其他跟post一样
   public static String doDel(String path) throws Exception {}
   HttpDelete request = new HttpDelete(path);//请求对象
public class TestHttpClient {
    public static void main(String[] args) throws Exception {
//        String path = "http://api.tianapi.com/txapi/tianqi/index?key=db3d22eebbff236d1b3b424ea12c3dd6&city=郑州";
//        String result = HttpClientUtil.doGet(path);
//        System.out.println(result);

        String path = "http://localhost:8080/user/login";
        Map<String,String> map = new HashMap<>();
        map.put("uphone","545555");
        map.put("valicode","22343");

        //执行path请求,同时把map中的数据转json放在请求体
        String s = HttpClientUtil.doPost(path, map);
        System.out.println(s);
    }
}

spring的RestTemplate工具类

//get接口
String path ="http://t.weather.sojson.com/api/weather/city/101030100";
RestTemplate t = new RestTemplate();
String result= t.getForObject(path, String.class);
System.out.println(result);
后端接口的处理器方法:
@PostMapping("/addEmployee")
public Employee postRequest(@RequestBody Employee e){
    System.out.println("post请求");
    return e;
}

//post接口
String uri = "http://localhost:8080/1011sm/addEmployee";
Employee newEmploy = new Employee("javasm", "28", "javasm@email.com");
RestTemplate restTemplate = new RestTemplate();
Employee result = restTemplate.postForObject(uri, newEmploy, Employee.class);
System.out.println(result);

定时任务

jdk的TimerTask

必须会,在程序运行期间动态的启动定时任务。比如30分钟后废除订单

1.从TimerTask类派生任务类,重写run方法
2.实例化Timer对象,schedule方法调度任务。
//实例化Timer对象,schedule方法调度任务。
//延时执行的方法
public class GetDataTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("获取接口数据");

    }
}

//延时执行操作
public class TimerTaskTest {
    public static void main(String[] args) throws ParseException {
        Timer timer = new Timer();
        // 延迟5秒执行,同时每隔5秒执行一次
        timer.schedule(new GetDataTask(),5000,5000);

        // 指定时间执行
        String time = "2020-08-10 18:38:20";
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = format.parse(time);
        timer.schedule(new GetDataTask(),date);
    }
}

spring-task

必须会,在程序启东时,预先定义好了一些定时任务执行。比如每天的8,12,18,22去获取天气数据保存

1.添加spring-context-support.jar
2.开启@Scheduled注解识别<task:annotation-driven>    
3.编写任务类,在任务方法上加@Scheduled(cron="秒 分 时 日 月 周"

在这里插入图片描述

<!--spring.xml-->

<!--@Scheduler定时任务注解识别开关-->
<task:annotation-driven></task:annotation-driven>
@Component
public class GetWeatherTask {

    @Resource
    private RedisService rs;
    // cron表达式,星期和日必有一个是问号
    //cron表达式:秒 分 时 日 月 周 年(可省)
    @Scheduled(cron = "0 * 12 ? * *")
    public void invokeWeatherInterface(){
        String path = "http://api.tianapi.com/txapi/tianqi/index?key=db3d22eebbff236d1b3b424ea12c3dd6&city=郑州";
        RestTemplate t = new RestTemplate();
        String forObject = t.getForObject(path, String.class);
        JSONObject jsonObject = JSON.parseObject(forObject);
        //取jsonObject里的newslist
        JSONArray newslist = jsonObject.getJSONArray("newslist");
        JSONObject currentDay = newslist.getJSONObject(0);
        //newslist的从1-结尾
        List<Object> objects = newslist.subList(1, newslist.size() - 1);
        currentDay.put("futureDays",objects);
        String area = currentDay.getString("area");
        String date = currentDay.getString("date");
        //保存String或hash都可以,都可以做到根据日期获取数据
        String key = RedisKey.WEATHER_KEY+area;
        //放缓存里
        rs.hset(key,date,JSON.toJSONString(currentDay));
    }
}

excel操作

依赖

在这里插入图片描述

读与写

//读

public class TestReadExcel {

    public static void main(String[] args) throws Exception {
        //读取excel中数据。
        String path ="D:/员工表.xlsx";

        InputStream in  = new FileInputStream(path);
        Workbook workbook = WorkbookFactory.create(in);//工作册对象
        Sheet sheet = workbook.getSheetAt(0);//工作簿对象
        Row firstRow = sheet.getRow(0);//第一行
        int cellNums = firstRow.getPhysicalNumberOfCells();//列数
        //遍历第一行数据
        for(int i=0;i<cellNums;i++){
            Cell cell = firstRow.getCell(i);
            String value = cell.getStringCellValue();
            System.out.print(value+"\t");
        }
        System.out.println();
        int rowNums = sheet.getPhysicalNumberOfRows();//行数
        for(int i=1;i<rowNums;i++){
            Row row = sheet.getRow(i);
            for(int j=0;j<cellNums;j++){
                Cell cell = row.getCell(j);
                int cellType = cell.getCellType();
                Object value=null;
                // 判断cell数据类型是否是string
                if(cellType==Cell.CELL_TYPE_STRING){
                    value = cell.getStringCellValue();
                // 判断cell数据类型是否是date
                }else if(cellType==Cell.CELL_TYPE_NUMERIC){
                    if(DateUtil.isCellDateFormatted(cell)){
                        Date dateCellValue = cell.getDateCellValue();
                        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                        value=df.format(dateCellValue);
                    }else{
                        // 判断cell数据类型是否是double
                        double t=cell.getNumericCellValue();
                        if((long)t==t){
                            value=(long)t;
                        }else{
                            value=String.valueOf(t);
                        }
                    }
                }
                System.out.print(value+"\t");
            }
            System.out.println();
        }
    }
}

//写

public class TestWriteExcel {

    public static void createExcel(List<Map<String,String>> datas, String[] header , OutputStream out) throws Exception {
        Workbook workbook = new XSSFWorkbook();//工作册
        //填数据
        Sheet sheet = workbook.createSheet();
        // 表头信息
        Row row = sheet.createRow(0);
        for(int i=0;i<header.length;i++){
            Cell cell = row.createCell(i);
            cell.setCellValue(header[i]);
        }
        // 数据行
        for(int rowNum=0;rowNum<datas.size();rowNum++){
            Map<String, String> data = datas.get(rowNum);
            Row r = sheet.createRow(rowNum+1);
            for(int colNum=0;colNum<header.length;colNum++){
                Cell cell = r.createCell(colNum);
                cell.setCellValue(data.get(header[colNum]));
            }
        }
        //写文件
        workbook.write(out);
    }

    public static void main(String[] args) throws Exception {
        List<Map<String,String>> datas = new ArrayList<>();
        Map<String,String> one = new HashMap<>();
        one.put("uname","张三");
        one.put("uphone","1231231231");
        one.put("uemail","aaa@163.com");
        one.put("ubirthday","2000-11-11");
        one.put("salary","5555.5");
        datas.add(one);

        one = new HashMap<>();
        one.put("uname","张三2");
        one.put("uphone","1231231232");
        one.put("uemail","aaa@164.com");
        one.put("ubirthday","2000-11-12");
        one.put("salary","5556.5");
        datas.add(one);

        one = new HashMap<>();
        one.put("uname","张三3");
        one.put("uphone","1231231233");
        one.put("uemail","aaa@162.com");
        one.put("ubirthday","2000-11-13");
        one.put("salary","5556.7");
        datas.add(one);

        String target = "D:/新用户.xlsx";
        String[] header = {"uname","uphone","uemail","ubirthday","salary"};
        createExcel(datas,header,new FileOutputStream(target));
    }
}

word操作

基于freemaker模板引擎来生成word

依赖

在这里插入图片描述

编辑word模板

另存为xml(表格数据需要手动修改xml文件)

在这里插入图片描述

在这里插入图片描述

<#list jl in jls>  放在结束的</w:tr>后面 回车
</#list>           最后xxx</w:tr>后面 回车
同时3个xxx分别替换为  {jl.xxm}  {jl.ks}  {jl.js}

将模板放入项目里

在这里插入图片描述

public class TestCreateDocx {
    public static void main(String[] args) throws Exception {
        //输出文件位置
        OutputStream out = new FileOutputStream("D:/入职合同.docx");
        //转字符流
        Writer w = new OutputStreamWriter(out);

        Configuration c = new Configuration();
        c.setDefaultEncoding("UTF-8");
        //指定模板文件路径
        c.setClassForTemplateLoading(TestCreateDocx.class,"/com/javasm/word");
        //指定模板名
        Template template = c.getTemplate("入职合同.xml");
        Map<String,Object> datas = new HashMap<>();
        datas.put("yf","唐家三少");
        datas.put("sfzh","4123123123123123123");
        datas.put("dy","3333.3");
        datas.put("rzrq","2011-11-11");
        datas.put("htrq","2020-09-23");
        // 创建放入表格数据的对应List
        List<StudyInfo> jls = new ArrayList<>();
        jls.add(new StudyInfo("郑州大学","2004-11-11","2008-1-1"));
        jls.add(new StudyInfo("北京大学","2008-11-11","2011-1-1"));
        datas.put("jls",jls);

        //实体或map或集合  datas-map(一般)
        //模板中传入数据
        template.process(datas,w);
    }
}



//表格对象
public class StudyInfo {
    private String xxm;
    private String ks;
    private String js;

    public StudyInfo(String xxm, String ks, String js) {
        this.xxm = xxm;
        this.ks = ks;
        this.js = js;
    }

    public String getXxm() {
        return xxm;
    }

    public void setXxm(String xxm) {
        this.xxm = xxm;
    }

    public String getKs() {
        return ks;
    }

    public void setKs(String ks) {
        this.ks = ks;
    }

    public String getJs() {
        return js;
    }

    public void setJs(String js) {
        this.js = js;
    }
}

如何发短信

  • 使用阿里云接口(具体参考现在的阿里云接口文档案例)

  • 充钱

  • 申请签名和模板(等待)

  • 快速入门,测试短信

  • 申请ak(accessKeyId,accessSecret)

  • 使用api,添加jar包(aliyun-java-sdk.core;gson;opentracing)

    package com.javasm.sms;
    
    import com.aliyuncs.CommonRequest;
    import com.aliyuncs.CommonResponse;
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.IAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.exceptions.ServerException;
    import com.aliyuncs.http.MethodType;
    import com.aliyuncs.profile.DefaultProfile;
    
    public class SendSms {
        private static  DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "AccessKey ID", "AccessKey Secret");
        public static void main(String[] args) {
    //        sendValicode("手机号","123123");
            String s = querySendDetails("15516197241", "20200924", "10", "1");
            System.out.println(s);
        }
    
        //查询发送详情
        public static String querySendDetails(String phone,String date,String pageSize,String pageNum){
            IAcsClient client = new DefaultAcsClient(profile);
            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain("dysmsapi.aliyuncs.com");
            request.setSysVersion("2017-05-25");
            request.setSysAction("QuerySendDetails");
            request.putQueryParameter("RegionId", "cn-hangzhou");
            request.putQueryParameter("PhoneNumber", phone);
            request.putQueryParameter("SendDate", date);
            request.putQueryParameter("PageSize", pageSize);
            request.putQueryParameter("CurrentPage", pageNum);
            try {
                CommonResponse response = client.getCommonResponse(request);
                return response.getData();
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        //发送
        
        public static String sendValicode(String phone,String code){
            IAcsClient client = new DefaultAcsClient(profile);
            CommonRequest request = new CommonRequest();
            request.setSysMethod(MethodType.POST);
            request.setSysDomain("dysmsapi.aliyuncs.com");
            request.setSysVersion("2017-05-25");
            request.setSysAction("SendSms");
            request.putQueryParameter("RegionId", "cn-hangzhou");
            request.putQueryParameter("PhoneNumbers", phone);
            request.putQueryParameter("SignName", "禾十六美肌整骨社");
            request.putQueryParameter("TemplateCode", "SMS_172738690");
            request.putQueryParameter("TemplateParam", "{\"code\":"+code+"}");
            try {
                CommonResponse response = client.getCommonResponse(request);
               return response.getData();
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
    }
    
    

如何发邮件

1.手写测试发送
  • 依赖:mail.jar
  • 发信邮箱需开启POP3/SMTP服务,并获得授权码。
public class SendEmail {
    public static void main(String[] args) throws Exception {
        //发邮件的账号的主机名和端口
        Properties properties = new Properties();
        properties.put("mail.transport.protocol", "smtp");// 连接协议
        properties.put("mail.smtp.host", "smtp.qq.com");// 主机名 smtp.163.com
        properties.put("mail.smtp.port", 465);// 默认端口号
        properties.put("mail.smtp.auth", "true");//服务端认证。
        // 设置是否使用ssl安全连接 ---一般都使用
        properties.put("mail.smtp.ssl.enable", "true");
        // 设置是否显示debug信息 true 会在控制台显示相关信息
        properties.put("mail.debug", "true");
        
        Session session = Session.getDefaultInstance(properties);//会话对象
        String uname = "358151539@qq.com";
        String upwd = "lhcdnstrtisdbhdc";
        Address from = new InternetAddress(uname);
        Address[] tos = new InternetAddress[]{
            new InternetAddress("2539543695@qq.com"),
            new InternetAddress("389956743@qq.com")
        };

        Message msg = new MimeMessage(session);//邮件主体内容部分
        msg.setFrom(from);                     //谁发
        msg.setRecipients(Message.RecipientType.TO,tos);   //setRecipients可发送多人
        msg.setSubject("测试邮件");                        //邮件标题
        msg.setText("邮件内容。。。。");

        Transport transport = session.getTransport();//邮差对象
        transport.connect(uname,upwd);//登录
        transport.sendMessage(msg,msg.getAllRecipients());//邮件的内容,收邮件的地址
    }
}
2.使用封装的工具类发送
/**
 * ClassName: EmailTest 
 * @Description: 发送邮件
 * @author Mr.Wang
 * @date 2018年4月20日
 */
public class EmailTest {
	
	public static void main(String[] args) throws Exception
	{
		try
		{
			MailSender mail = new MailSender();
			
			mail.setHost("smtp.qq.com");			// 设置 SMTP 主机
			mail.setFrom("358151539@qq.com");			// 设置发送者地址xxx@163.com
			mail.addTo("fythnu@163.com");				// 添加发送目标地址xxx@xx.com
			mail.addTo("2539543695@qq.com");				// 添加发送目标地址xxx@xx.com
			//mail.addCc("抄送的邮箱地址");				// 添加抄送目标地址xxx@xx.com
			mail.addFileAcc("D:/入职合同.docx");			// 添加文件附件
			mail.addFileAcc("D:/新用户.xlsx");			// 添加文件附件
			// 从 byte[] 中读取数据并添加为附件(这个功能有时非常有用)
			mail.addByteAcc("我是大怪兽".getBytes(), MailSender.DEFAULT_CONTENT_TYPE, "我是谁.txt");
			//mail.addReplyTo(mail.getFrom());		// 添加回复地址
			mail.setAuth(true);						// 设置验证模式
			mail.setNeedReceipt(false);				// 设置是否需要回执
			mail.setUser("358151539@qq.com");			// 设置邮箱登录名
			mail.setPassword("lhcdnstrtisdbhdc");			// 设置邮箱登录密码
			mail.setSubject("ssss");				// 设置邮件主题
			mail.setText("测试邮件<br>这是一封java发出的邮件");// 设置邮件文本内容
			mail.setCharset("UTF-8");				// 设置邮件文本内容编码
			mail.setContentType("text/html");		// 设置邮件文本内容格式
			mail.send();							// 发送邮件
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}

}

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import javax.activation.DataSource;



/** Byte Array 数据源,发送字节数组附件时用到 */
class ByteArrayDataSource implements DataSource
{
	public static final String DEFAULT_ENCODING	= GeneralHelper.DEFAULT_ENCODING;
	
	private ByteArrayOutputStream	baos		= null;
	private String					type		= "application/octet-stream";
	private String					name		= "ByteArrayDataSource";
	
	private void init(String type, String name)
	{
		if(type != null)
			this.type = type;
		if(name != null)
			this.name = name;		
	}

	public ByteArrayDataSource(byte[] data, String type, String name) throws IOException
	{
		ByteArrayInputStream Bis = null;

		try
		{
			Bis = new ByteArrayInputStream(data);
			this.byteArrayDataSource(Bis, type, name);
		}
		catch (IOException ioex)
		{
			throw ioex;
		}
		finally
		{
			try
			{
				if (Bis != null)
				{
					Bis.close();
				}
			}
			catch (IOException ignored)
			{
			}
		}

	}

	public ByteArrayDataSource(InputStream aIs, String type, String name) throws IOException
	{
		this.byteArrayDataSource(aIs, type, name);
	}

	private void byteArrayDataSource(InputStream aIs, String type, String name) throws IOException
	{
		init(type, name);
		
		BufferedInputStream bis		= null;
		BufferedOutputStream bos	= null;
		
		try
		{
			int length = 0;
			byte[] buffer = new byte[4096];

			bis		= new BufferedInputStream(aIs);
			baos	= new ByteArrayOutputStream();
			bos		= new BufferedOutputStream(baos);

			while ((length = bis.read(buffer)) != -1)
			{
				bos.write(buffer, 0, length);
			}		
		}
		catch (IOException ioex)
		{
			throw ioex;
		}
		finally
		{
			try
			{
				if (bis != null)
				{
					bis.close();
				}
				if (baos != null)
				{
					baos.close();
				}
				if (bos != null)
				{
					bos.close();
				}
			}
			catch (IOException ignored)
			{
			}
		}
	}

	public ByteArrayDataSource(String data, String type, String name) throws IOException
	{
		this(data, DEFAULT_ENCODING, type, name);
	}

	public ByteArrayDataSource(String data, String encoding, String type, String name) throws IOException
	{
		init(type, name);

		try
		{
			baos = new ByteArrayOutputStream();

			baos.write(data.getBytes(encoding));
		}
		catch (UnsupportedEncodingException uex)
		{
			// Do something!
		}
		catch (IOException ignored)
		{
			// Ignore
		}
		finally
		{
			try
			{
				if (baos != null)
				{
					baos.close();
				}
			}
			catch (IOException ignored)
			{
			}
		}
	}

	public String getContentType()
	{
		return type;
	}

	public InputStream getInputStream() throws IOException
	{
		if (baos == null)
		{
			throw new IOException("no data");
		}
		
		return new ByteArrayInputStream(baos.toByteArray());
	}

	public String getName()
	{
		return name;
	}

	public OutputStream getOutputStream() throws IOException
	{
		baos = new ByteArrayOutputStream();
		return baos;
	}
}


package com.javasm.email;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
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;
import javax.mail.internet.MimeUtility;



/**
 * ClassName: MailSender 
 * @Description: 邮件发送
 * @author Mr.Wang
 * @date 2017年11月11日
 */
public class MailSender
{
	/** 默认 Content Type -> text/plain */
	public static final String DEFAULT_CONTENT_TYPE	= "text/plain";
	/** 默认字符编码 -> UTF-8 */
	public static final String DEFAULT_ENCODING		= GeneralHelper.DEFAULT_ENCODING;
	/** 默认 SMTP 端口 -> 25 */
	public static final int DEFAULT_PORT			= 25;
	
	private String host			= "";
	private String from			= "";
	private String user			= "";
	private String password		= "";
	private String subject		= "";
	private String text			= "";
	private String contentType	= DEFAULT_CONTENT_TYPE;
	private String charset		= DEFAULT_ENCODING;
	private int port			= DEFAULT_PORT;
	private boolean auth		= true;
	private boolean needReceipt	= false;
	private Date sentDate		= null;
	
	private List<String>		to				= new ArrayList<String>();
	private List<String>		cc				= new ArrayList<String>();
	private List<String>		bcc				= new ArrayList<String>();
	private List<String>		replyTo			= new ArrayList<String>();
	private List<String> 		fileAcc 		= new ArrayList<String>();
	private List<MimeBodyPart> 	byteAcc 		= new ArrayList<MimeBodyPart>();
	
	public int getPort()
	{
		return port;
	}

	public void setPort(int port)
	{
		this.port = port;
	}
	
	public boolean isAuth()
	{
		return auth;
	}

	public void setAuth(boolean auth)
	{
		this.auth = auth;
	}

	public String getCharset()
	{
		return charset;
	}

	public void setCharset(String charset)
	{
		this.charset = charset;
	}

	public String getContentType()
	{
		return contentType;
	}

	public void setContentType(String contentType)
	{
		this.contentType = contentType;
	}

	public boolean isNeedReceipt()
	{
		return needReceipt;
	}

	public void setNeedReceipt(boolean needReceipt)
	{
		this.needReceipt = needReceipt;
	}

	public String getFrom()
	{
		return from;
	}

	public void setFrom(String from)
	{
		this.from = from;
	}

	public String getHost()
	{
		return host;
	}

	public void setHost(String host)
	{
		this.host = host;
	}

	public String getPassword()
	{
		return password;
	}

	public void setPassword(String password)
	{
		this.password = password;
	}

	public String getSubject()
	{
		return subject;
	}

	public void setSubject(String subject)
	{
		this.subject = subject;
	}

	public String getText()
	{
		return text;
	}

	public void setText(String text)
	{
		this.text = text;
	}
	
	public Date getSentDate()
	{
		return sentDate;
	}
	
	public void setSentDate(Date sentDate)
	{
		this.sentDate = sentDate;
	}

	public String getUser()
	{
		return user;
	}

	public void setUser(String user)
	{
		this.user = user;
	}

	public List<String> getFileAcc()
	{
		return fileAcc;
	}
	
	public List<MimeBodyPart> getByteAcc()
	{
		return byteAcc;
	}
	
	public void setFileAcc(List<String> accessory)
	{
		this.fileAcc = accessory;
	}
	
	public void setByteAcc(List<MimeBodyPart> accessory)
	{
		this.byteAcc = accessory;
	}

	public List<String> getReplyTo()
	{
		return replyTo;
	}

	public List<String> getTo()
	{
		return to;
	}
	
	public void setTo(List<String> to)
	{
		this.to = to;
	}
	
	public List<String> getCc()
	{
		return cc;
	}
	
	public void setCc(List<String> cc)
	{
		this.cc = cc;
	}
	
	public List<String> getBcc()
	{
		return bcc;
	}
	
	public void setBcc(List<String> bcc)
	{
		this.bcc = bcc;
	}
	
	public void addFileAcc(String accessory)
	{
		fileAcc.add(accessory);
	}
	
	/** 添加 byte array 形式的附件 */
	public void addByteAcc(byte[] accessory, String type, String fileName) throws Exception
	{
		ByteArrayDataSource ds	 = new ByteArrayDataSource(accessory, type, fileName);

		//BASE64Encoder enc = new BASE64Encoder();
		//fileName = "=?GBK?B?" + enc.encode(fileName.getBytes()) + "?=";
		fileName = MimeUtility.encodeText(fileName, charset, "B");

		MimeBodyPart mimeFile = new MimeBodyPart();
		mimeFile.setDataHandler(new DataHandler(ds));
		//mimeFile.setFileName(ds.getName());
		mimeFile.setFileName(fileName);
		
		byteAcc.add(mimeFile);
	}
	
	public void addReplyTo(String address)
	{
		replyTo.add(address);
	}
	
	public void addTo(String address)
	{
		to.add(address);
	}
	
	public void addCc(String address)
	{
		cc.add(address);
	}
	
	public void addBcc(String address)
	{
		bcc.add(address);
	}
	
	/** 发送邮件 */
	public void send() throws Exception
	{
		Transport transport = null;
		
		try
		{
			Properties props = new Properties();
			props.put("mail.transport.protocol", "smtp");
			props.put("mail.smtp.auth", Boolean.toString(auth));
			Session session = Session.getDefaultInstance(props, null);
			MimeMessage msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress(from));
			
			for(String i : to)
				msg.addRecipient(Message.RecipientType.TO, new InternetAddress(i));
			for(String i : cc)
				msg.addRecipient(Message.RecipientType.CC, new InternetAddress(i));
			for(String i : bcc)
				msg.addRecipient(Message.RecipientType.BCC, new InternetAddress(i));

			if(replyTo.size() > 0)
			{
				InternetAddress[] replyAddress = new InternetAddress[replyTo.size()];
				
				for(int i = 0; i < replyAddress.length; i++)
					replyAddress[i] = new InternetAddress((String)replyTo.get(i));
				
				msg.setReplyTo(replyAddress);
			}
			
			if(needReceipt)
				msg.addHeader("Disposition-Notification-To", from);
			
			if(sentDate != null)
				msg.setSentDate(sentDate);
			else
				msg.setSentDate(new Date());
			
			msg.setSubject(subject, charset);
			
			MimeMultipart mm	= new MimeMultipart();
			MimeBodyPart mbText	= new MimeBodyPart();
			mbText.setContent(text, contentType + ";charset=" + charset);
			mm.addBodyPart(mbText);
			
			for(String filePath : fileAcc)
			{
				String fileName = (new File(filePath)).getName();
				fileName = MimeUtility.encodeText(fileName, charset, "B");
				
				MimeBodyPart mbFile		= new MimeBodyPart();
				DataSource datasource	= new FileDataSource(filePath);
				
				mbFile.setDataHandler(new DataHandler(datasource));
				mbFile.setFileName(fileName);
				mm.addBodyPart(mbFile);
			}
			
			for(MimeBodyPart part : byteAcc)
				mm.addBodyPart(part);
			
			msg.setContent(mm);
			msg.saveChanges();
			
			transport = session.getTransport();
			transport.connect(host, port, user, password);
			transport.sendMessage(msg, msg.getAllRecipients());
		}
		finally
		{
			if(transport != null) try{ transport.close(); } catch (Exception e) { }
		}
	}
}

package com.javasm.email;


import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Array;
import java.net.URL;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ClassName: GeneralHelper 
 * @Description: 通用方法帮助类
 * @author Mr.Wang
 * @date 2017年11月11日
 */
public class GeneralHelper
{
	private static final String[] SHORT_DATE_PATTERN 				= {"yyyy-MM-dd", "yyyy/MM/dd", "yyyy\\MM\\dd", "yyyyMMdd"};
	private static final String[] LONG_DATE_PATTERN 				= {"yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy\\MM\\dd HH:mm:ss", "yyyyMMddHHmmss"};
	private static final String[] LONG_DATE_PATTERN_WITH_MILSEC 	= {"yyyy-MM-dd HH:mm:ss.SSS", "yyyy/MM/dd HH:mm:ss.SSS", "yyyy\\MM\\dd HH:mm:ss.SSS", "yyyyMMddHHmmssSSS"};
	
	/** 空字符串 */
	public static final String EMPTY_STRING				= "";
	/** 空字符串 */
	public static final String DEFAULT_ENCODING			= "UTF-8";
	/** 当前操作系统平台 */
	public static final String OS_PLATFORM				= getOSName();
	/** 当前操作系统平台是否为 Windows */
	public static final boolean IS_WINDOWS_PLATFORM		= isWindowsPlatform();
	/** 当前操作系统平台的换行符 */
	public static final String NEWLINE_CHAR				= IS_WINDOWS_PLATFORM ? "\r\n" : "\n";
	
	
	/** 检查字符串不为 null 或空字符串 */
	public final static boolean isStrNotEmpty(String str)
	{
		return str != null && str.length() != 0;
	}

	/** 检查字符串不为 null 、空字符串或只包含空格 */
	public final static boolean isTrimStrNotEmpty(String str)
	{
		boolean result = isStrNotEmpty(str);
		return result ? isStrNotEmpty(str.trim()) : result;
	}

	/** 检查字符串为 null 或空字符串 */
	public final static boolean isStrEmpty(String str)
	{
		return !isStrNotEmpty(str);
	}

	/** 检查字符串为 null 、空字符串或只包含空格 */
	public final static boolean isTrimStrEmpty(String str)
	{
		boolean result = isStrEmpty(str);
		return result ?  result : isStrEmpty(str.trim());
	}

	/** 把参数 str 转换为安全字符串:如果 str = null,则把它转换为空字符串 */
	public final static String safeString(String str)
	{
		if(str == null)
			str = "";
		
		return str;
	}

	/** 把参数 obj 转换为安全字符串:如果 obj = null,则把它转换为空字符串 */
	public final static String safeString(Object obj)
	{
		if(obj == null)
			return "";
		
		return obj.toString();
	}

	/** 把参数 str 转换为安全字符串并执行去除前后空格:如果 str = null,则把它转换为空字符串 */
	public final static String safeTrimString(String str)
	{
		return safeString(str).trim();
	}

	/** 检查字符串是否符合整数格式 */
	public final static boolean isStrNumeric(String str)
	{
		return str.matches("^0$|^\\-?[1-9]+[0-9]*$");
	}

	/** 检查字符串是否符合电子邮件格式 */
	public final static boolean isStrEmailAddress(String str)
	{
		return str.matches("^[a-z0-9_\\-]+(\\.[_a-z0-9\\-]+)*@([_a-z0-9\\-]+\\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)$");
	}

	/** 检查字符串是否符合 IP 地址格式 */
	public final static boolean isStrIPAddress(String str)
	{
		return str.matches("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
	}

	/** 检查字符串是否符合 HTML 超链接元素格式 */
	public final static boolean isStrLink(String str)
	{
		return str.matches("<a[^>]*href=\\\"[^\\s\\\"]+\\\"[^>]*>[^<]*<\\/a>");
	}

	/** 检查字符串是否符合 URL 格式 */
	public final static boolean isStrURL(String str)
	{
		return str.matches("^((https?|ftp|news):\\/\\/)?([a-z]([a-z0-9\\-]*\\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel)|(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(\\/[a-z0-9_\\-\\.~]+)*(\\/([a-z0-9_\\-\\.]*)(\\?[a-z0-9+_\\-\\.%=&amp;]*)?)?(#[a-z][a-z0-9_]*)?$");
	}
	
	/** 屏蔽正则表达式的转义字符(但不屏蔽 ignores 参数中包含的字符) */
	public static final String escapeRegexChars(String str, char ... ignores)
	{
		final char ESCAPE_CHAR	 = '\\';
		final char[] REGEX_CHARS = {'.', ',', '?', '+', '-', '*', '^', '$', '|', '&', '{', '}', '[', ']', '(', ')', '\\'};
		
		char[] regex_chars = REGEX_CHARS;
		
		if(ignores.length > 0)
		{
			Set<Character> cs = new HashSet<Character>(REGEX_CHARS.length);
			
			for(int i = 0; i < REGEX_CHARS.length; i++)
				cs.add(REGEX_CHARS[i]);
			for(int i = 0; i < ignores.length; i++)
				cs.remove(ignores[i]);
				
			int i		= 0;
			regex_chars = new char[cs.size()];
			Iterator<Character> it = cs.iterator();
			
			while(it.hasNext())
				regex_chars[i++] = it.next();				
		}
		
		StringBuilder sb = new StringBuilder();
		
		for(int i = 0; i < str.length(); i++)
		{
			char c = str.charAt(i);
			
			for(int j = 0; j < regex_chars.length; j++)
			{
				if(c == regex_chars[j])
				{
					sb.append(ESCAPE_CHAR);
					break;
				}
			}
			
			sb.append(c);
		}
		
		return sb.toString();
	}

	/** 符分割字符串(分割符:" \t\n\r\f,;") */
	public final static String[] splitStr(String str)
	{
		return splitStr(str, " \t\n\r\f,;");
	}
	
	/** 符分割字符串(分割符:由 delim 参数指定) */
	public final static String[] splitStr(String str, String delim)
	{
		StringTokenizer st	= new StringTokenizer(str, delim);
		String[] array		= new String[st.countTokens()];
		
		int i = 0;
		while(st.hasMoreTokens())
			array[i++] = st.nextToken();
		
		return array;
	}

	/** 调用 {@linkplain Thread#sleep(long)} 方法使当前线程睡眠 period 毫秒 <br>
	 * 
	 * 如果 {@linkplain Thread#sleep(long)} 方法被中断则返回 false
	 * 
	 */
	public final static boolean waitFor(long period)
	{
		if(period > 0)
		{
			try
			{
				Thread.sleep(period);
			}
			catch(Exception e)
			{
				return false;
			}
		}
		else
			Thread.yield();
		
		return true;
	}

	/** 调用 {@linkplain Thread#sleep(long)} 方法使当前线程睡眠 period 个 unit 时间单元 <br>
	 * 
	 * 如果 {@linkplain Thread#sleep(long)} 方法被中断则返回 false
	 * 
	 */
	public final static boolean waitFor(long period, TimeUnit unit)
	{
		return waitFor(unit.toMillis(period));
	}

	/** String -> Integer,如果转换不成功则返回 null */
	public final static Integer str2Int(String s)
	{
		Integer returnVal;
		try {
			returnVal = Integer.decode(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> int,如果转换不成功则返回默认值 d */
	public final static int str2Int(String s, int d)
	{
		int returnVal;
		try {
			returnVal = Integer.parseInt(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> int,如果转换不成功则返回 0 */
	public final static int str2Int_0(String s)
	{
		return str2Int(s, 0);
	}

	/** String -> Short,如果转换不成功则返回 null */
	public final static Short str2Short(String s)
	{
		Short returnVal;
		try {
			returnVal = Short.decode(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> short,如果转换不成功则返回默认值 d */
	public final static short str2Short(String s, short d)
	{
		short returnVal;
		try {
			returnVal = Short.parseShort(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> short,如果转换不成功则返回 0 */
	public final static short str2Short_0(String s)
	{
		return str2Short(s, (short)0);
	}

	/** String -> Long,如果转换不成功则返回 null */
	public final static Long str2Long(String s)
	{
		Long returnVal;
		try {
			returnVal = Long.decode(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> long,如果转换不成功则返回默认值 d */
	public final static long str2Long(String s, long d)
	{
		long returnVal;
		try {
			returnVal = Long.parseLong(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> long,如果转换不成功则返回 0 */
	public final static long str2Long_0(String s)
	{
		return str2Long(s, 0L);
	}

	/** String -> Float,如果转换不成功则返回 null */
	public final static Float str2Float(String s)
	{
		Float returnVal;
		try {
			returnVal = Float.valueOf(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> float,如果转换不成功则返回默认值 d */
	public final static float str2Float(String s, float d)
	{
		float returnVal;
		try {
			returnVal = Float.parseFloat(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> float,如果转换不成功则返回 0 */
	public final static float str2Float_0(String s)
	{
		return str2Float(s, 0F);
	}

	/** String -> Double,如果转换不成功则返回 null */
	public final static Double str2Double(String s)
	{
		Double returnVal;
		try {
			returnVal = Double.valueOf(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> double,如果转换不成功则返回默认值 d */
	public final static double str2Double(String s, double d)
	{
		double returnVal;
		try {
			returnVal = Double.parseDouble(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> double,如果转换不成功则返回 0.0 */
	public final static double str2Double_0(String s)
	{
		return str2Double(s, 0D);
	}

	/** String -> Byte,如果转换不成功则返回 null */
	public final static Byte str2Byte(String s)
	{
		Byte returnVal;
		try {
			returnVal = Byte.decode(safeTrimString(s));
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> byte,如果转换不成功则返回默认值 d */
	public final static byte str2Byte(String s, byte d)
	{
		byte returnVal;
		try {
			returnVal = Byte.parseByte(safeTrimString(s));
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> byte,如果转换不成功则返回 0 */
	public final static byte str2Byte_0(String s)
	{
		return str2Byte(s, (byte)0);
	}

	/** String -> Character,如果转换不成功则返回 null */
	public final static Character str2Char(String s)
	{
		Character returnVal;
		try {
			returnVal = safeTrimString(s).charAt(0);
		} catch(Exception e) {
			returnVal = null;
		}
		return returnVal;
	}

	/** String -> char,如果转换不成功则返回默认值 d */
	public final static char str2Char(String s, char d)
	{
		char returnVal;
		try {
			returnVal = safeTrimString(s).charAt(0);
		} catch(Exception e) {
			returnVal = d;
		}
		return returnVal;
	}

	/** String -> char,如果转换不成功则返回 0 */
	public final static char str2Char_0(String s)
	{
		return str2Char(s, Character.MIN_VALUE);
	}

	/** String -> Boolean,如果转换不成功则返回 null */
	public final static Boolean str2Boolean(String s)
	{
		return Boolean.valueOf(safeTrimString(s));
	}

	/** String -> boolean,如果转换不成功则返回默认值 d */
	public final static boolean str2Boolean(String s, boolean d)
	{
		s = safeTrimString(s);
		
		if(s.equalsIgnoreCase("true"))
			return true;
		else if(s.equalsIgnoreCase("false"))
			return false;
		
		return d;
	}

	/** String -> boolean,如果转换不成功则返回 0 */
	public final static boolean str2Boolean_False(String s)
	{
		return str2Boolean(s, false);
	}

	/** String -> java.util.Date, str 的格式由 format  定义 */
	public final static Date str2Date(String str, String format)
	{
		Date date = null;
		
		try
		{
			DateFormat df = new SimpleDateFormat(format);
			date = df.parse(safeTrimString(str));
		}
		catch(Exception e)
		{

		}

		return date;
	}

	/** String -> java.util.Date,由函数自身判断 str 的格式 */
	public final static Date str2Date(String str)
	{
		Date date = null;

		try
		{
			final char SEPARATOR	= '-';
			final String[] PATTERN	= {"yyyy", "MM", "dd", "HH", "mm", "ss", "SSS"};
			String[] values			= safeTrimString(str).split("\\D");
			String[] element		= new String[values.length];
			
			int length = 0;
			for(String e : values)
			{
				e = e.trim();
				if(e.length() != 0)
				{
					element[length++] = e;
					if(length == PATTERN.length)
						break;
				}
			}

			if(length > 0)
			{
	       		StringBuilder value	= new StringBuilder();

				if(length > 1)
				{
        			for(int i = 0; i < length; ++i)
        			{
        				value.append(element[i]);
        				value.append(SEPARATOR);
        			}
				}
				else
				{
					String src	= element[0];
					int remain	= src.length();
					int pos		= 0;
					int i		= 0;

					for(i = 0; remain > 0 && i < PATTERN.length; ++i)
					{
						int p_length	= PATTERN[i].length();
						int v_length	= Math.min(p_length, remain);
						String v 		= src.substring(pos, pos + v_length);
						pos			+= v_length;
						remain 		-= v_length;

						value.append(v);
						value.append(SEPARATOR);
					}

					length = i;
				}

     			StringBuilder format = new StringBuilder();

     			for(int i = 0; i < length; ++i)
				{
					format.append(PATTERN[i]);
					format.append(SEPARATOR);
				}

				date = str2Date(value.toString(), format.toString());
			}
		}
		catch(Exception e)
		{

		}

		return date;
	}
	
	/** String -> java.util.Date,由 Patterns 指定可能的日期格式 */
	public final static Date str2Date(String str, String[] Patterns)
	{
		Date date = null;
		
		for(int i = 0; i < Patterns.length; ++i)
		{
			date = str2Date(str, Patterns[i]);

			if( date != null)
				break;
		}

		return date;
	}
	
	/** String -> java.util.Date,由 GeneralHelper.SHORT_DATE_PATTERN 指定可能的日期格式 */
	public final static Date str2ShortDate(String str)
	{
		return str2Date(str, SHORT_DATE_PATTERN);
	}

	/** String -> java.util.Date,由 GeneralHelper.LONG_DATE_PATTERN 指定可能的日期格式 */
	public final static Date str2LongDate(String str)
	{
		return str2Date(str, LONG_DATE_PATTERN);
	}

	/** String -> java.util.Date,由 GeneralHelper.LONG_DATE_PATTERN_WITH_MILSEC 指定可能的日期格式 */
	public final static Date str2LongDateWithMilliSecond(String str)
	{
		return str2Date(str, LONG_DATE_PATTERN_WITH_MILSEC);
	}
	
	/** 类型转换处理器接口 */
	public static interface TypeHandler<T>
	{
		T handle(String v);
	}
	
	/** String -> Any,字符串转换为 8 种基础数据类型、及其包装类 {@link Date}、 或 {@link String} 
	 * 
	 * @param type	: 目标类型的 {@link Class} 对象
	 * @param v		: 要转换的字符串
	 * @return		: 转换结果,如果转换不成功返回 null
	 * @throws 		: 如果目标类型不支持抛出 {@link IllegalArgumentException}
	 * 
	 */
	public static final <T> T str2Object(Class<T> type, String v)
	{
		return str2Object(type, v, null);
	}
	
	/** String -> Any,如果 handler 为 null 则把字符串转换为 8 种基础数据类型、及其包装类、 {@link Date} 或 {@link String},
	 * 			      如果 handler 不为 null 则由 handler 执行转换 
	 * 
	 * @param type	: 目标类型的 {@link Class} 对象
	 * @param v		: 要转换的字符串
	 * @param handler	: 类型转换处理器
	 * @return		: 转换结果,如果转换不成功返回 null
	 * @throws 		: 如果目标类型不支持抛出 {@link IllegalArgumentException}
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static final <T> T str2Object(Class<T> type, String v, TypeHandler<T> handler)
	{
		Object param = null;
		
		if(handler != null)
			return handler.handle(v);
		
		if(type == String.class)
			param =  safeTrimString(v);
		else if(type == int.class)
			param =  str2Int_0(v);
		else if(type == long.class)
			param =  str2Long_0(v);
		else if(type == byte.class)
			param =  str2Byte_0(v);
		else if(type == char.class)
			param =  str2Char_0(v);
		else if(type == float.class)
			param =  str2Float_0(v);
		else if(type == double.class)
			param =  str2Double_0(v);
		else if(type == short.class)
			param =  str2Short_0(v);
		else if(type == boolean.class)
			param =  str2Boolean_False(v);
		else if(type == Integer.class)
			param =  str2Int(v);
		else if(type == Long.class)
			param =  str2Long(v);
		else if(type == Byte.class)
			param =  str2Byte(v);
		else if(type == Character.class)
			param =  str2Char(v);
		else if(type == Float.class)
			param =  str2Float(v);
		else if(type == Double.class)
			param =  str2Double(v);
		else if(type == Short.class)
			param =  str2Short(v);
		else if(type == Boolean.class)
			param =  str2Boolean(v);
		else if(Date.class.isAssignableFrom(type))
			param =  str2Date(v);
		else
			throw new IllegalArgumentException(String.format("object type '%s' not valid", type));
		
		return (T)param;
	}

	/** Any -> Object[] <br>
	 * 
	 *  obj == null					: 返回 Object[] {null} <br>
	 *  obj 为对象数组				: 强制转换为 Object[], 并返回自身 <br>
	 *  obj 为基础类型数组			: 返回 Object[], 其元素类型为基础类型的包装类 <br>
	 *  obj 为 {@link Collection}	: 通过 toArray() 方法返回 Object[] <br>
	 *  obj 为 {@link Iterable}		: 遍历 {@link Iterable}, 并返回包含其所有元素的 Object[] <br>
	 *  obj 为 {@link Iterator}		: 遍历 {@link Iterator}, 并返回包含其所有元素的 Object[] <br>
	 *  obj 为 {@link Enumeration}	: 遍历 {@link Enumeration}, 并返回包含其所有元素的 Object[] <br>
	 *  obj 为普通对象				: 返回 Object[] {obj} <br>
	 * 
	 * @param obj	: 任何对象
	 * 
	 */
	public static final Object[] object2Array(Object obj)
	{
		Object[] array;
		
		if(obj == null)
			array = new Object[] {obj};
		else if(obj.getClass().isArray())
		{
			Class<?> clazz = obj.getClass().getComponentType();
			
			if(Object.class.isAssignableFrom(clazz))
				array = (Object[])obj;
			else
			{
				int length = Array.getLength(obj);
				
				if(length > 0)
				{
					array = new Object[length];
					
					for(int i = 0; i < length; i++)
						array[i] = Array.get(obj, i);
				}
				else
					array = new Object[0];
			}
		}
		else if(obj instanceof Collection<?>)
			array = ((Collection<?>)obj).toArray();
		else if(obj instanceof Iterable<?>)
		{
			List<Object> list = new ArrayList<Object>();
			Iterator<?> it = ((Iterable<?>)obj).iterator();
			
			while(it.hasNext())
				list.add(it.next());
			
			array = list.toArray();
		}
		else if(obj instanceof Iterator)
		{
			List<Object> list = new ArrayList<Object>();
			Iterator<?> it = (Iterator<?>)obj;
			
			while(it.hasNext())
				list.add(it.next());
			
			array = list.toArray();
		}
		else if(obj instanceof Enumeration<?>)
		{
			List<Object> list = new ArrayList<Object>();
			Enumeration<?> it = (Enumeration<?>)obj;
			
			while(it.hasMoreElements())
				list.add(it.nextElement());
			
			array = list.toArray();
		}
		else
			array = new Object[] {obj};
		
		return array;
	}

	/** 返回 date 加上 value 天后的日期(清除时间信息) */
	public final static Date addDate(Date date, int value)
	{
		return addDate(date, value, true);
	}

	/** 返回 date 加上 value 天后的日期,trimTime 指定是否清除时间信息 */
	public final static Date addDate(Date date, int value, boolean trimTime)
	{
		return addTime(date, Calendar.DATE, value, trimTime);

	}

	/** 返回 date 加上 value 个 field 时间单元后的日期(不清除时间信息) */
	public final static Date addTime(Date date, int field, int value)
	{
		return addTime(date, field, value, false);
	}

	/** 返回 date 加上 value 个 field 时间单元后的日期,trimTime 指定是否去除时间信息 */
	public final static Date addTime(Date date, int field, int value, boolean trimTime)
	{
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(field, value);

		if(trimTime)
		{
        		c.set(Calendar.HOUR, 0);
        		c.set(Calendar.MINUTE, 0);
        		c.set(Calendar.SECOND, 0);
        		c.set(Calendar.MILLISECOND, 0);
		}

		return c.getTime();

	}

	/** java.util.Date -> String,str 的格式由 format  定义 */
	public final static String date2Str(Date date, String format)
	{
		DateFormat df	= new SimpleDateFormat(format);
		return df.format(date);
	}

	/** 修整 SQL 语句字符串:' -> '',(includeWidlcard 指定是否对星号和问号作转换:* -> %, ? -> _) */
	public static final String regularSQLStr(String str, boolean includeWidlcard)
	{
		str = str.replace("'", "''");

		if(includeWidlcard)
		{
			str = str.replace('*', '%');
			str = str.replace('?', '_');
		}

		return str;
	}
	
	/** 获取 clazz 的 {@link ClassLoader} 对象,如果为 null 则返回当前线程的 Context {@link ClassLoader} */
	public static final ClassLoader getClassLoader(Class<?> clazz)
	{
		ClassLoader loader = clazz.getClassLoader();
		
		if(loader == null)
			loader = Thread.currentThread().getContextClassLoader();
		
		return loader;
	}
	
	/** 加载类名为  className 的 {@link Class} 对象,如果加载失败则返回 null */
	public static final Class<?> loadClass(String className)
	{
		Class<?> clazz		= null;
		ClassLoader loader	= getClassLoader(GeneralHelper.class);
		
		try
		{
			clazz = loader.loadClass(className);
		}
		catch(ClassNotFoundException e)
		{
			
		}
		
		return clazz;
	}

	/** 用 {@linkplain Class#forName(String)} 加载 {@link Class} 对象,如果加载失败则返回 null */
	public static final Class<?> classForName(String name)
	{
		Class<?> clazz = null;
		
		try
		{
			clazz = Class.forName(name);
		}
		catch(ClassNotFoundException e)
		{
			
		}
		
		return clazz;
	}

	/** 用 {@linkplain Class#forName(String, boolean, ClassLoader)} 加载 {@link Class} 对象,如果加载失败则返回 null */
	public static final Class<?> classForName(String name, boolean initialize, ClassLoader loader)
	{
		Class<?> clazz = null;
		
		try
		{
			clazz = Class.forName(name, initialize, loader);
		}
		catch(ClassNotFoundException e)
		{
			
		}
		
		return clazz;
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 对象 */
	public static final URL getClassResource(Class<?> clazz, String resPath)
	{
		URL url = clazz.getResource(resPath);
		
		if(url == null)
		{
			ClassLoader loader = clazz.getClassLoader();
			if(loader != null) url = loader.getResource(resPath);
			
			if(url == null)
			{
				loader = Thread.currentThread().getContextClassLoader();
				if(loader != null) url = loader.getResource(resPath);
			}
		}

		return url;
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 对象列表 */
	public static final List<URL> getClassResources(Class<?> clazz, String resPath)
	{
		List<URL> urlList		= new ArrayList<URL>();
		Enumeration<URL> urls	= null;
		
		try
		{
    		ClassLoader loader = clazz.getClassLoader();
    		if(loader != null) urls = loader.getResources(resPath);
    		
    		if(urls == null || !urls.hasMoreElements())
    		{
    			loader = Thread.currentThread().getContextClassLoader();
    			if(loader != null) urls = loader.getResources(resPath);
    		}
		}
		catch(IOException e)
		{
			throw new RuntimeException(e);
		}
		
		if(urls != null)
		{
			while(urls.hasMoreElements())
				urlList.add(urls.nextElement());
		}

		return urlList;
	}

	/** 获取 clazz 资源环境中 resPath 的 {@link InputStream} */
	public static final InputStream getClassResourceAsStream(Class<?> clazz, String resPath)
	{
		InputStream is = clazz.getResourceAsStream(resPath);
		
		if(is == null)
		{
			ClassLoader loader = clazz.getClassLoader();
			if(loader != null) is = loader.getResourceAsStream(resPath);
			
			if(is == null)
			{
				loader = Thread.currentThread().getContextClassLoader();
				if(loader != null) is = loader.getResourceAsStream(resPath);
			}
		}

		return is;
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 绝对路径(返还的绝对路径用 UTF-8 编码) */
	public static final String getClassResourcePath(Class<?> clazz, String resPath)
	{
		return getClassResourcePath(clazz, resPath, DEFAULT_ENCODING);
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 绝对路径(返还的绝对路径用 pathEnc 编码) */
	public static final String getClassResourcePath(Class<?> clazz, String resPath, String pathEnc)
	{
		String path = null;

		try
		{
			URL url = getClassResource(clazz, resPath);
			
			if(url != null)
			{
				path = url.getPath();
				path = URLDecoder.decode(path, pathEnc);
			}
		}
		catch(UnsupportedEncodingException e)
		{
			throw new RuntimeException(e);
		}

		return path;
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 绝对路径列表(返还的绝对路径用 UTF-8 编码) */
	public static final List<String> getClassResourcePaths(Class<?> clazz, String resPath)
	{
		return getClassResourcePaths(clazz, resPath, DEFAULT_ENCODING);
	}

	/** 获取 clazz 资源环境中 resPath 相对路径的 URL 绝对路径列表(返还的绝对路径用 pathEnc 编码) */
	public static final List<String> getClassResourcePaths(Class<?> clazz, String resPath, String pathEnc)
	{
		List<String> pathList = new ArrayList<String>();

		try
		{
			List<URL> urlList = getClassResources(clazz, resPath);
			
			for(URL url : urlList)
			{
				String path = URLDecoder.decode(url.getPath(), pathEnc);
				pathList.add(path);
			}
		}
		catch(UnsupportedEncodingException e)
		{
			throw new RuntimeException(e);
		}

		return pathList;
	}

	/** 获取 clazz 资源环境的当前 URL 绝对路径(返回的绝对路径用 pathEnc 编码) */
	public static final String getClassPath(Class<?> clazz)
	{
		return getClassResourcePath(clazz, ".");
	}

	/** 获取 resource 资源的 locale 本地化文件中名字为 key 的字符串资源,并代入 params 参数 */
	public static final String getResourceMessage(Locale locale, String resource, String key, Object ... params)
	{
		ResourceBundle bundle = ResourceBundle.getBundle(resource, locale);
		String msg = bundle.getString(key);

		if(params != null && params.length > 0)
			msg = MessageFormat.format(msg, params);

		return msg;
	}

	/** 获取 resource 资源的默认本地化文件中名字为 key 的字符串资源,并代入 params 参数 */
	public static final String getResourceMessage(String resource, String key, Object ... params)
	{
		return getResourceMessage(Locale.getDefault(), resource, key, params);
	}

	/** 获取 e 异常的堆栈列表,最带的堆栈层数由 levels 指定 */
	public static final List<String> getExceptionMessageStack(Throwable e, int levels)
	{
		List<String> list = new ArrayList<String>();

		if(levels == 0)
			levels = Integer.MAX_VALUE;

		for(int i = 0; i < levels; ++i)
		{
			StringBuilder sb = new StringBuilder();

			if(i > 0)
				sb.append("Caused by -> ");

			sb.append(e.getClass().getName());
			String msg = e.getLocalizedMessage();
			if(msg != null)
				sb.append(": ").append(msg);

			list.add(sb.toString());

			e = e.getCause();
			if(e == null)
				break;
		}

		return list;
	}

	/** 获取 e 异常的整个堆栈列表 */
	public static final List<String> getExceptionMessageStack(Throwable e)
	{
		return getExceptionMessageStack(e, 0);
	}

	/** 输出 e 异常的 levels 层堆栈列表到 ps 中 */
	public static final void printExceptionMessageStack(Throwable e, int levels, PrintStream ps)
	{
		List<String> list = getExceptionMessageStack(e, levels);

		for(String msg : list)
			ps.println(msg);
	}

	/** 输出 e 异常的 levels 层堆栈列表到标准错误流中 */
	public static final void printExceptionMessageStack(Throwable e, int levels)
	{
		printExceptionMessageStack(e, levels, System.err);
	}

	/** 输出 e 异常的整个堆栈列表到 ps 中 */
	public static final void printExceptionMessageStack(Throwable e, PrintStream ps)
	{
		printExceptionMessageStack(e, 0, ps);
	}

	/** 输出 e 异常的整个堆栈列表到标准错误流中 */
	public static final void printExceptionMessageStack(Throwable e)
	{
		printExceptionMessageStack(e, 0);
	}
	
	/** 把元素添加到 {@link Map} 中,不保证线程安全(不替换原值) */
	public static final <K, V> boolean tryPut(Map<K, V> map, K key, V value)
	{
		return tryPut(map, key, value, false);
	}
	
	/** 把元素添加到 {@link Map} 中,不保证线程安全 */
	public static final <K, V> boolean tryPut(Map<K, V> map, K key, V value, boolean replace)
	{
		if(replace || !map.containsKey(key))
		{
			map.put(key, value);
			return true;
		}
		
		return false;
	}

	/** 把元素添加到 {@link Map} 中,并保证线程安全(不替换原值) */
	public static final <K, V> boolean syncTryPut(Map<K, V> map, K key, V value)
	{
		return syncTryPut(map, key, value, false);
	}
	
	/** 把元素添加到 {@link Map} 中,并保证线程安全 */
	public static final <K, V> boolean syncTryPut(Map<K, V> map, K key, V value, boolean replace)
	{
		synchronized(map)
		{
			return tryPut(map, key, value, replace);
		}
	}

	/** 把元素添加到 {@link Map} 中,不保证线程安全(不替换原值) */
	public static final <K, V> int tryPutAll(Map<K, V> map, Map<K, V> src)
	{
		return tryPutAll(map, src, false);
	}
	
	/** 把元素添加到 {@link Map} 中,不保证线程安全 */
	public static final <K, V> int tryPutAll(Map<K, V> map, Map<K, V> src, boolean replace)
	{
		if(replace)
		{
			map.putAll(src);
			return src.size();
		}
		
		int count = 0;
		Set<Entry<K, V>> entries = src.entrySet();
		
		for(Entry<K, V> e : entries)
		{
			if(!map.containsKey(e.getKey()))
			{
				map.put(e.getKey(), e.getValue());
				++count;
			}
		}
		
		return count;
	}

	/** 把元素添加到 {@link Map} 中,并保证线程安全(不替换原值) */
	public static final <K, V> int syncTryPutAll(Map<K, V> map, Map<K, V> src)
	{
		return syncTryPutAll(map, src, false);
	}
	
	/** 把元素添加到 {@link Map} 中,并保证线程安全 */
	public static final <K, V> int syncTryPutAll(Map<K, V> map, Map<K, V> src, boolean replace)
	{
		synchronized(map)
		{
			return tryPutAll(map, src, replace);
		}
	}

	/** 从 {@link Map} 中删除元素,不保证线程安全 */
	public static final <K, V> boolean tryRemove(Map<K, V> map, K key)
	{
		if(map.containsKey(key))
		{
			map.remove(key);
			return true;
		}
		
		return false;
	}

	/** 从 {@link Map} 中删除元素,并保证线程安全 */
	public static final <K, V> boolean syncTryRemove(Map<K, V> map, K key)
	{
		synchronized(map)
		{
			return tryRemove(map, key);
		}
	}

	/** 清空 {@link Map},不保证线程安全 */
	public static final <K, V> void tryClear(Map<K, V> map)
	{
		map.clear();
	}

	/** 清空 {@link Map},并保证线程安全 */
	public static final <K, V> void syncTryClear(Map<K, V> map)
	{
		synchronized(map)
		{
			tryClear(map);
		}
	}

	/** 获取当前 JVM 进程的 ID */
	public static final int getProcessId()
	{
		return Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
	}

	/** 获取当前 JVM 进程的 Java 版本 */
	public static final String getJavaVersion()
	{
		return System.getProperty("java.version");
	}

	/** 获取当前操作系统的名称 */
	public static final String getOSName()
	{
		return System.getProperty("os.name");
	}

	/** 检查当前操作系统是否为 Windows 系列 */
	public static final boolean isWindowsPlatform()
	{
		// return CURRENT_OS.toUpperCase().indexOf("WINDOWS") != -1;
		
		return File.pathSeparatorChar == ';';
	}

	/** 按拼音排序的字符串比较器 */
	public static class PinYinComparator implements Comparator<String>
	{
		@Override
		public int compare(String o1, String o2)
		{
			java.text.Collator cmp = java.text.Collator.getInstance(Locale.CHINA);
			return cmp.compare(o1, o2);
		}
	}

	/** 按文件名称进行文件筛选的文件过滤器,构造函数参数 name 指定文件名的正则表达式 */
	public static class FileNameFileFilter implements FileFilter
	{
		protected static final int FLAGS = IS_WINDOWS_PLATFORM ? Pattern.CASE_INSENSITIVE : 0;

		Pattern pattern;

		public FileNameFileFilter(String name)
		{
			String exp = name;
			exp = exp.replace('.', '#');
			exp = exp.replaceAll("#", "\\\\.");
			exp = exp.replace('*', '#');
			exp = exp.replaceAll("#", ".*");
			exp = exp.replace('?', '#');
			exp = exp.replaceAll("#", ".?");
			exp = "^" + exp + "$";

			pattern = Pattern.compile(exp, FLAGS);
		}

		@Override
		public boolean accept(File file)
		{
			Matcher matcher = pattern.matcher(file.getName());
			return matcher.matches();
		}
	}
	
	/**
	 * 
	 * @Description:比较两个时间点 如果secondDate表示的时间等于此 firstDate 表示的时间,则返回 0 值; 如果此
	 *                      firstDate 的时间在参数<secondDate>表示的时间之前,则返回小于 0 的值; 如果此
	 *                      firstDate 的时间在参数<secondDate>表示的时间之后,则返回大于 0 的值
	 * @param firstDate
	 * @param secondDate
	 * @ReturnType int
	 * @author:
	 * @Created 2012 2012-9-20上午08:34:33
	 */
	public static int compare(Date firstDate, Date secondDate) {

		Calendar firstCalendar = null;
		/** 使用给定的 Date 设置此 Calendar 的时间。 **/
		if (firstDate != null) {
			firstCalendar = Calendar.getInstance();
			firstCalendar.setTime(firstDate);
		}

		Calendar secondCalendar = null;
		/** 使用给定的 Date 设置此 Calendar 的时间。 **/
		if (firstDate != null) {
			secondCalendar = Calendar.getInstance();
			secondCalendar.setTime(secondDate);
		}

		try {
			/**
			 * 比较两个 Calendar 对象表示的时间值(从历元至现在的毫秒偏移量)。 如果参数表示的时间等于此 Calendar
			 * 表示的时间,则返回 0 值; 如果此 Calendar 的时间在参数表示的时间之前,则返回小于 0 的值; 如果此
			 * Calendar 的时间在参数表示的时间之后,则返回大于 0 的值
			 * **/
			return firstCalendar.compareTo(secondCalendar);
		} catch (NullPointerException e) {
			throw new IllegalArgumentException(e);
		} catch (IllegalArgumentException e) {
			throw new IllegalArgumentException(e);
		}
	}

	/**
	 * List<Object>去重
	 * 	Object 必须实现equals和hashCode方法
	 * @param list
	 */
	public static void removeDuplicateWithObject(List list) {
		   Set set = new HashSet();
		   List newList = new ArrayList();
		   for (Iterator iter = list.iterator(); iter.hasNext();) {
		          Object element = iter.next();
		          if (set.add(element))
		             newList.add(element);
		       }
		      list.clear();
		      list.addAll(newList);
		}
	
	/**
	 * 将map转换成List
	 * @param map
	 * @return
	 */
	public static List<Object> mapByList(HashMap<String, Object> map){
		List<Object> list = new ArrayList<Object>();
		Set<Entry<String, Object>> set = map.entrySet();
		Iterator<Entry<String, Object>> it = set.iterator();
		//将map对象里面的属性循环遍历出来
		while(it.hasNext()){
			Entry<String, Object> entry = it.next();
			//得到value值,装到list里面,也可以entry.getKey()。
			//如果2个都需要装。可以弄成一个对象来装
			list.add(entry.getValue());
		}
		return list;
	}
	
	/**
	 * 将Date转换成String【yyyy-MM-dd】
	 * @param date
	 * @return
	 */
	public static String dateConvertString(Date date){
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		String str=sdf.format(date);
		return str;
	}
	
	/**
	 * 根据指定长度 分隔字符串
	 * 
	 * @param str
	 *            需要处理的字符串
	 * @param length
	 *            分隔长度
	 * 
	 * @return 字符串集合
	 */
	public static List<String> splitString(String str, int length) {
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < str.length(); i += length) {
			int endIndex = i + length;
			if (endIndex <= str.length()) {
				list.add(str.substring(i, i + length));
			} else {
				list.add(str.substring(i, str.length() - 1));
			}
		}
		return list;
	}

	/**
	 * 将字符串List转化为字符串,以分隔符间隔.
	 * 
	 * @param list
	 *            需要处理的List.
	 *            
	 * @param separator
	 *            分隔符.
	 * 
	 * @return 转化后的字符串
	 */
	public static String toString(List<String> list, String separator) {
		StringBuffer stringBuffer = new StringBuffer();
		for (String str : list) {
			stringBuffer.append(separator + str);
		}
		stringBuffer.deleteCharAt(0);
		return stringBuffer.toString();
	}
	
	/** 
	   * Description: 随机从数组中取出指定的不重复的n个数。 
	   * @param ArrayList 原始数组 
	   * @param int n 随机抽取的个数 
	   * @return 返回抽取的数组 
	   */  
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List getRandomArray(List list)  
	{  
		Collections.shuffle(list);	//洗牌
		return list;
	}
	
	/**
	 * 截取指定的长度
	 * @param list
	 * @param num
	 * @return
	 */
	public static List subList(List list ,int num)  {
		List newList = getRandomArray(list);
		return newList.subList(0, num);
	}

}

fastdfs分布式文件存储

认识fastdfs

了解fastdfs

FastDFS是由国人余庆所开发,其项目地址https://github.com/happyfish100

FastDFS是一个轻量级的开源分布式文件系统,主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。

支持存储服务器在线扩容,支持相同的文件只保存一份,节约磁盘。

FastDFS只能通过Client API访问,不支持POSIX访问方式。

FastDFS适合中大型网站使用,用来存储资源文件(如:图片、文档、视频等)

FastDFS组成部分

FastDFS由跟踪服务器(tracker server)、存储服务器(storage server)和客户端(client)三个部分组成,主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size <500MB)为载体的在线服务。

Tracker server(跟踪服务器)
跟踪服务器:用来调度来自客户端的请求。且在内存中记录所有存储组和存储服务器的信息状态。
Storage server(存储服务器)
用来存储文件(data)和文件属性(metadata)
Client客户端
提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。

FastDFS服务器架构
  • 存储服务器会定期向跟踪服务器发送状态信息(心跳包)。
  • 客户端发起上传请求时,向跟踪服务器查询可用的存储服务器。
  • 客户端向存储服务器上传文件内容,存储服务器保存文件并生成文件路径以及文件名
  • 存储服务器将路径及文件名返回给客户端

在这里插入图片描述

使用

jar包准备
  • Maven
    <dependency>
      <groupId>org.csource</groupId>
      <artifactId>fastdfs-client-java</artifactId>
      <version>1.27</version>
    </dependency>

    <!--用于读字节数组  方法FileUtils-->      
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>
配置文件

resources文件夹下fdfs_client.conf( text格式 )

connect_timeout = 2    //连接超时时间
network_timeout = 30   //网络连接超时时间
charset = UTF-8
http.tracker_http_port = 8111
tracker_server = 192.168.20.252:22122   //跟踪服务器IP地址
使用客户端api
public class DfsUtil {
    private static TrackerClient client = null;
    private static String httpPort = null;
    private static String REAL_NAME = "realName";
    private static String FILE_SIZE = "size";
    private static String UPLOAD_TIME = "uploadTime";
    //初始化fastdfs服务
    static {
        String conf_path = DfsUtil.class.getClassLoader().getResource("fdfs_client.conf").getPath();
        try {
            //加载conf配置文件
            ClientGlobal.init(conf_path);
            //所有的跟踪服务器信息在TrackerClient对象中。
            //知道所有的跟踪服务器组
            client = new TrackerClient();
            // 得到http服务端口
            httpPort = ClientGlobal.getG_tracker_http_port() + "";
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //上传(文件信息,文件的元数据信息)  
    //byte[] bytes 一般用于10M以下文件
    public static String upload(byte[] bytes,String realName,long size){
        TrackerServer ts = null;
        //创建存储服务器对象
        StorageServer ss = null;
        StorageClient1 storageClient1 = null;
        try {
            //从跟踪服务器组拿到一个具体的跟踪服务器
            ts = client.getConnection();
            //即使传入的存储服务器对象为null也会自动分配
            //也可以指定具体存储服务器对象 一般为null
            storageClient1 = new StorageClient1(ts, ss);
            //获取文件后缀名
            String extName = realName.substring(realName.lastIndexOf(".") + 1);
            //元数据列表,(类似写的注释)上传文件习惯把上传日期,文件大小,文件真实名
            NameValuePair[] metaList = new NameValuePair[]{
                new NameValuePair(REAL_NAME,realName),
                new NameValuePair(FILE_SIZE,size+""),
                new NameValuePair(UPLOAD_TIME,System.currentTimeMillis()+""),
            };
            //上传 并返回上传结果
            String s = storageClient1.upload_file1(bytes, extName, metaList);
            return s;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //释放连接
            if(storageClient1!=null)storageClient1=null;
            if(ss!=null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    

    //获取文件元数据信息
    public static Map<String,String> getMetaList(String path){
        TrackerServer ts = null;
        StorageServer ss = null;
        StorageClient1 storageClient1 = null;
        try {
            ts = client.getConnection();
            storageClient1 = new StorageClient1(ts, ss);
            //根据得来的路径从数据库拉取资源 返回数组
            NameValuePair[] metadata1 = storageClient1.get_metadata1(path);
            //遍历数组 放入集合map
            Map<String,String> result = new HashMap<>();
            for(NameValuePair nv:metadata1){
                result.put(nv.getName(),nv.getValue());
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(storageClient1!=null)storageClient1=null;
            if(ss!=null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    //下载
    public static byte[] download(String path){
        TrackerServer ts = null;
        StorageServer ss = null;
        StorageClient1 storageClient1 = null;
        try {
            ts = client.getConnection();//
            storageClient1 = new StorageClient1(ts, ss);
            byte[] bytes = storageClient1.download_file1(path);
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(storageClient1!=null)storageClient1=null;
            if(ss!=null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    //删除
    public static boolean delete(String path){
        TrackerServer ts = null;
        StorageServer ss = null;
        StorageClient1 storageClient1 = null;
        try {
            ts = client.getConnection();//
            storageClient1 = new StorageClient1(ts, ss);
            //表示删除文件,0成功,2失败
            int i = storageClient1.delete_file1(path);
            return i==0?true:false;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(storageClient1!=null)storageClient1=null;
            if(ss!=null) {
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(ts!=null){
                try {
                    ts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    //生成HttpUrl   用于图片展示等
    public static String getHttpPath(String path){
        String url ="http://";
        try {
            //得到一台具体的跟踪服务器
            TrackerServer connection = client.getConnection();
            //得到跟踪服务器的主机名
            String hostName = connection.getInetSocketAddress().getHostName();
            url = url+hostName+":"+httpPort+"/"+path;
            return url;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
//Test
public class AppTest
{
    /**
     * Rigorous Test :-)
     */
    //上传
    @Test
    public void upload() throws IOException {
        File f = new File("C:/Users/JAVASM/Desktop/学习笔记/学习中/java/java图片/4.jpg");
        byte[] bytes = FileUtils.readFileToByteArray(f);
        String name = f.getName();
        long length = f.length();

        String upload = DfsUtil.upload(bytes, name, length);
        System.out.println(upload);
        //group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg  group1-存储服务器
    }

    //获取文件元数据信息
    @Test
    public void getMetaDatas(){
        String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
        Map<String, String> metaList = DfsUtil.getMetaList(path);
        System.out.println(metaList);
    }
    
    //下载 用到了
    @Test
    public void download() throws IOException {
        String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
        byte[] download = DfsUtil.download(path);
        File f = new File("D:/aa.png");
        FileUtils.writeByteArrayToFile(f,download);
    }

    //删除
    @Test
    public void del() throws IOException {
        String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
        boolean delete = DfsUtil.delete(path);
    }

    //生成HttpUrl
    @Test
    public void getHttpPath(){
        String path = "group1/M00/00/12/wKgU_F9yra6AUyizAACoxG3uRvc315.jpg";
        String httpPath = DfsUtil.getHttpPath(path);
        System.out.println(httpPath);
    }
}

JJWT使用

token替代session进行登录验证

在这里插入图片描述

使用

LoginHandler(将登陆成功的token存入响应头发给前端)
    @PostMapping("login")
    public ResponseEntity login(@RequestBody Map<String,String> map){
        String uphone = map.get("uphone");
        String valicode = map.get("valicode");
        //校验验证 ..
        boolean isok = us.checkValicode(uphone,valicode);
        if(!isok)
            throw new MvcException(StatusEnum.VALICODE_ERROR);
        //根据手机号取获取用户对象 ..
        Sysuser loginuser = us.login(uphone);

        if(loginuser!=null){
            //1.生成token,把用户标识信息放进去
            String token = JwtUtil.generate(uphone);
            //2.把token放在响应头,发送给客户端
            HttpHeaders headers = new HttpHeaders();
            headers.add("token",token);
            loginuser.setUpwd("");
            return new ResponseEntity(new ResponseBean(StatusEnum.LOGIN_SUC,loginuser),headers,HttpStatus.OK);
        }
        throw new MvcException(StatusEnum.LOGIN_ERROR);
    }

前端axios请求与响应拦截器写法
//base.js

axios.defaults.baseURL = 'http://localhost:8080';
axios.defaults.withCredentials = true;

//配置发送请求前的拦截器 可以设置token信息
axios.interceptors.request.use(function (config) {
	// debugger;
	//4.不需要登录就可以发起的请求,需要放行,不用发送token,(登录,获取验证码...)
	let url = config.url;
	if(url.startsWith("/user/valicode") || url.startsWith("/user/login")){
		return config;
	}
	
	//5.发送请求的时候,从localstorage中获取token,放在请求头
	let token = localStorage.getItem("token");
	if(token==null || token==undefined){
		parent.location.href="/ssm_html/login.html";
	}
	
	config.headers['token']=token;
    return config;
}, function (error) {
    return Promise.reject(error);
});

// 配置响应拦截器
axios.interceptors.response.use(function (resp) {
	data = resp.data;
	if(data.code==51000){
		parent.location.href="/ssm_html/error.html";
	}else if(data.code==50005){
		parent.location.href="/ssm_html/login.html";//从iframe框架中找到父页面进行href重定向。
	}else if(data.code==51001){
		location.href="/ssm_html/nooptions.html";//无操作权限
	}else if(data.code==50007){
		localStorage.removeItem("token")
		parent.location.href="/ssm_html/login.html";
	}
	
	//3.从服务端的头数据中获取token,保存localstorage
	let token = resp.headers['token']
	if(token!=null && token!=undefined)
		localStorage.setItem("token",token);
		
    return data;
}, function (error) {
    return Promise.reject(error);
});
LoginInterceptor(spring注册登录拦截器)
springmvc.xml
跨域设置开启暴露响应头设置   exposed-headers="token"-暴露的响应头 
    <mvc:cors>
        <mvc:mapping path="/**" allowed-origins="*" allowed-headers="*" allowed-methods="*" allow-credentials="true" exposed-headers="token"/>
    </mvc:cors>
配置登陆拦截器
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/user/login"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/user/valicode/**"></mvc:exclude-mapping>
            <bean class="com.javasm.common.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
//LoginInterceptor

public class LoginInterceptor implements HandlerInterceptor {

    @Resource
    private RedisService rs;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 对预检请求放行
        String method = request.getMethod();
        if("OPTIONS".equals(method))
            return true;     
         //1.从请求头中获取客户端发送的token
        String token = request.getHeader("token");
         //6.校验token
        if(token==null){
            throw new MvcException(StatusEnum.NO_LOGIN);
        }
        //2.校验token的有效性
        Claims claims = JwtUtil.parse(token);
        if(claims==null){
            //返回token过期了
            throw new MvcException(StatusEnum.TOKEN_EXPIRE);
        }
        //3.获取tokne中的用户标识信息,根据用户标识信息去redis中获取完整信息
        //可以放在request中setAttribute,也可以自定义一个线程变量。
        String uphone = (String)claims.get("uphone");
        String userinfo = rs.hget(RedisKey.USERS_HASH, uphone);
        Gson g = new Gson();
        Sysuser sysuser = g.fromJson(userinfo, Sysuser.class);
        CurrentLoginUser.setLoginuser(sysuser);
//        request.setAttribute("LOGIN_USER",sysuser);       
        //4.获取剩余有效时间,判断是否需要刷新token
        long current = System.currentTimeMillis();
        long expire = claims.getExpiration().getTime();
        if(expire-current<=28*60*1000){
            String newtoken = JwtUtil.generate(uphone);
            response.addHeader("token",newtoken);
        }
        if(sysuser!=null)
            return true;
        else
            throw new MvcException(StatusEnum.NO_LOGIN);
    }
}

工具类

public class JwtUtil {
    private static final String secretKey="fmsZ+gLbV8DVA2lCLECj+6ytDwD0hARxIVkwMJoZWnjEf/CcfANYd7ZgfnDnWpJl07mBOKkeB5TMemGGWlUf+A==";
    private static final long expireMills=30*60*1000;

    public static String getSecureKey(){
        SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS512);//生成秘钥的工具
        String encode = Encoders.BASE64.encode(key.getEncoded());
        System.out.println(encode);
        return encode;
    }
   /**
     * 生成token
     *
     * @param claims:字符串中要保存的用户信息
     * @return
     */
    public static String generate(String uphone){
        Date currentDate = new Date();
        long l = currentDate.getTime()+expireMills;
        Date expireDate = new Date(l);
        Map<String,String> map = new HashMap<>();
        map.put("uphone",uphone);
        SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretKey));
        String jws = Jwts.builder().setClaims(map).setIssuedAt(currentDate).setExpiration(expireDate).signWith(key).compact();
        return jws;
    }
    /**
     * 解析token
     *
     * @param token
     * @return
     */
    public static Claims parse(String token){
        try{
            Jws<Claims> jws = Jwts.parserBuilder().setSigningKey(secretKey).build().parseClaimsJws(token);
            Claims body = jws.getBody();
            return body;
        }catch(Exception e){
            return null;
        }
    }

}

activiti工作流引擎

1.workflow engine:

​ 驱动项目中的工作流程的统一第三方组件。

2.设计理念:

​ 以请假流程来说, 填写请假申请单,点击保存把申请单保存数据库.

在这里插入图片描述

在编写流程审批的代码之前.

​ 1.设置流程定义文件(bpmn流程描述语言).leave.bpmn

​ 2.需要在mysql数据库中建好activiti相关的表。

​ 3.在项目中添加activiti的依赖jar包。

​ 4.调用api把流程定义文件部署到数据库。

进入流程审批的编码:

​ 1.在保存并提交把申请单保存数据库的时候,调用api启动请假流程。

​ 2.调用api根据登录人查找他的待办任务列表。

​ 3.调用api,当前登录人需要先签收一个任务,完成指定的任务,完成任务的时候可能需要记录审批意见。

3.使用activiti:

1.设计流程定义文件
  • 安装插件:actiBpm
  • 流程定义的节点(id,name,assignee|candidate users|candidate groups(节点的执行人))
    • id:英文
    • name:中文
    • assignee:执行人(${loginUser},老班A)。可以是用户名,可以是表达式
    • candidateUsers候选人列表。可以是多个用户名,可以是表达式 (不常用)
    • candidateGroups候选人角色列表(段长),可以是多个角色名,可以是表达式
    • 分支线上写条件表达式:${days<=3} ${approveResult}:审批通过与否
  • 生成png图片
2.在mysql中创建activiti数据库表:
  1. 下载activiti-5.22.0.zip,执行database文件夹下的create数据库创建sql脚本文件,
  2. 了解25张数据库表:
    • act_evt,act_ge:元数据表(存储引擎版本信息,流程定义xml文件数据)
    • act_id_*:用户与角色表(存储系统用户与用户组信息)
    • act_re_*:流程部署表(存储流程部署信息,流程定义文件信息)
    • act_ru_*:正在执行当中的流程数据表(存储流程实例与任务信息)
    • act_hi_*: 执行完结的流程数据历史表(存储历史流程实例与历史任务信息)
3.在项目中依赖activiti项
 <!--<activiti-version>5.22.0</activiti-version>-->

<dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-engine</artifactId>
            <version>${activiti-version}</version>
</dependency>
<dependency>
            <groupId>org.activiti</groupId>
            <artifactId>activiti-spring</artifactId>
            <version>${activiti-version}</version>
</dependency>
4.把activiti的核心的服务对象加入spring容器
<!--activiti.xml-->

<!--别忘了spring.xml注入-->
<!--<import resource="classpath:activiti.xml"></import>-->


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <!--是否允许并行任务-->
        <property name="jobExecutorActivate" value="false" />
    </bean>

    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>
    
    <!--创建5个核心服务bean对象-->
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />

</beans>
5.调用api把流程定义文件部署到数据库表:
  • 用到RepositoryService,用来做流程部署的增删查操作
/**
 * 用来测试流程部署,在系统管理-->流程管理(增删查)
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class TestRepositoryService {

    @Resource
    private RepositoryService rs;

    //添加新的流程部署
    @Test
    public void deloy(){
        DeploymentBuilder deployment = rs.createDeployment();
        deployment.name("请假流程2");//前端执行
        deployment.addClasspathResource("bpmn/leave2.bpmn");//上传
        deployment.addClasspathResource("bpmn/leave2.png");//上传
        Deployment deploy = deployment.deploy();//相当于insert
        String deployId = deploy.getId();//新增记录的id
        System.out.println(deployId);
    }

   //查询部署列表,支持条件查询,支持分页查询
    @Test
    public void queryDeploy(){
        DeploymentQuery deploymentQuery = rs.createDeploymentQuery();
//        deploymentQuery.deploymentName("");//条件查询
        List<Deployment> list = deploymentQuery.list();
        System.out.println(list);
    }
}
    
    //日常绝对不用
    @Test
    public void del(){
        rs.deleteDeployment("25001");
    }
6.调用api把用户与角色数据添加到activiti数据库表
  • 用到IdentityService:newUser,newGroup,createMemberShip
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class TestIdentityService {
//lhs:学生,  老班A:班主任   jy,wmz:段长
    @Resource
    private IdentityService ds;

    //创建用户
    @Test
    public void addUser(){
        String uname="wmz";
        User user = ds.newUser(uname);//创建一个user对象
        ds.saveUser(user);
    }

    @Test
    public void delUser(){
        String uname="老班A";
        ds.deleteUser(uname);//创建一个user对象
    }

    //创建角色
    @Test
    public void addGroup(){
        String roleName="学生";
        Group group = ds.newGroup(roleName);
        ds.saveGroup(group);

        String roleName1="班主任";
        Group group1 = ds.newGroup(roleName1);
        ds.saveGroup(group1);

        String roleName2="段长";
        Group group2 = ds.newGroup(roleName2);
        ds.saveGroup(group2);
    }

    //设置用户-角色
    @Test
    public void updateMemberShip(){
        ds.createMembership("lhs","学生");
        ds.createMembership("老班A","班主任");
        ds.createMembership("jy","段长");
        ds.createMembership("wmz","段长");
    }
}
7.添加申请申请单并提交审批
Service
//ILeaveService

public interface ILeaveService {
    //->启动请假申请流程
    ///保存请假申请单草稿
    public void addLeaveOrder(LeaveOrder lo);
    //更新流程实例id到申请单外键
    public void updateProcessInstanceId2LeaveOrder(LeaveOrder lo);
    ///保存申请单并提交审核
    public void submitLeaveOrder(LeaveOrder lo,String loginUserName);
    ///保存请假申请单并提交流程审核
    public void addLeaveAndSubmit(LeaveOrder lo,String loginUserName);


    //->完成流程审批
    ///获取待办任务列表
    public List<ProcessTask> getTodoTaskList(String loginuserName);

    ///执行审批
    public void doApprove(String loginuser, String taskid, String processinstnceid,String comment, String result);

    ///签收任务
    public void doClaim(String taskid,String loginUserName);

    //查看申请单状态
    List getMyLeaveOrders(String loginUser);

    //更新申请单状态
    public void updateStatusByProcessInstanceId(String pid,Integer status);
//
@Service
public class LeaveServiceImpl implements ILeaveService {

    @Resource
    private LeaveOrderMapper lm;

    @Resource
    private RuntimeService rs;

    @Resource
    private TaskService ts;

    @Resource
    private HistoryService hs;

    @Resource
    private RedisService redisService;

    //保存请假申请单草稿
    @Override
    public void addLeaveOrder(LeaveOrder lo) {
        lm.insertSelective(lo);
    }

    //更新流程实例id到申请单外键
    //要求参数对象中必须有lid,processinstanceid
    @Override
    public void updateProcessInstanceId2LeaveOrder(LeaveOrder lo) {
        lo.setStatus("1");
        lm.updateByPrimaryKeySelective(lo);

//        public static final String PROCESS_KEY="process:";
        String key = RedisKey.PROCESS_KEY+lo.getProcessinstanceid();
        redisService.set(key, JSON.toJSONString(lo));
    }

    //保存申请单并提交审核
    @Transactional
    @Override
    public void submitLeaveOrder(LeaveOrder lo,String loginUserName) {
        Map<String,Object> valiables = new HashMap<>();
        valiables.put("loginUser",loginUserName);
        valiables.put("days",lo.getLdays());

        //启动了流程,执行startEvent
//添加申请单即向自己的业务表中添加数据;
// RuntimeService对象中的startProcessinstanceByKey(String key,Map<String,Object> valiables)
// act_hi_procinst
        ProcessInstance pi = rs.startProcessInstanceByKey(ProcessKey.LEAVE2,valiables);
        String processInstanceId = pi.getProcessInstanceId();

        //完成请假申请task
        TaskQuery taskQuery = ts.createTaskQuery();
        taskQuery.processInstanceId(processInstanceId);
        Task task = taskQuery.singleResult();
        String taskid=task.getId();
//        TaskService中的complete方法,把申请task给执行完
        ts.complete(taskid);

        //更新流程实例id到申请单外键
        lo.setProcessinstanceid(processInstanceId);
        updateProcessInstanceId2LeaveOrder(lo);
    }

    //保存请假申请单并提交流程审核 调用上面两个方法
    @Transactional
    @Override
    public void addLeaveAndSubmit(LeaveOrder lo,String loginUserName) {
        addLeaveOrder(lo);
        submitLeaveOrder(lo,loginUserName);
    }

    //查询待办任务列表
    @Override
    public List<ProcessTask> getTodoTaskList(String loginuserName) {
        List<ProcessTask> result = new ArrayList<>();

//        TaskService中的createTaskQuery方法根据流程实例id来查询任务。
        //查询运行时的任务
        TaskQuery taskQuery = ts.createTaskQuery();
        //执行任务的执行人或候选人
        taskQuery.taskCandidateOrAssigned(loginuserName);
        taskQuery.processDefinitionKey(ProcessKey.LEAVE2);
        //查询的所有流程定义下的任务项,适合于应用在工作台欢迎页
        List<Task> list = taskQuery.list();

        for(Task t:list){
            String processInstanceId = t.getProcessInstanceId();
            //需要去查询到请假申请单的完整信息
            String key = RedisKey.PROCESS_KEY+processInstanceId;
            String s = redisService.get(key);
            LeaveOrder leaveOrder = JSON.parseObject(s, LeaveOrder.class);
            result.add(new ProcessTask(t,leaveOrder));
        }

        return result;
    }

    //执行审批
    @Transactional
    @Override
    public void doApprove(String loginuser, String taskid,String processinstnceid, String comment, String result) {
        ts.addComment(taskid,processinstnceid,result,comment);
        ts.complete(taskid);
    }

    //签收任务
    @Override
    public void doClaim(String taskid, String loginUserName) {
        ts.claim(taskid,loginUserName);
    }

    //查看申请单状态
    @Override
    public List getMyLeaveOrders(String loginUser) {

        List<LeaveOrder> orders = lm.selectOrders(loginUser);
        for (LeaveOrder l:orders){
            String processinstanceid = l.getProcessinstanceid();
            if(processinstanceid!=null){
                HistoricProcessInstanceQuery hq = hs.createHistoricProcessInstanceQuery();
                hq.processInstanceId(processinstanceid);
                //得到流程实例对象
                HistoricProcessInstance pi = hq.singleResult();
                Date endTime = pi.getEndTime();
                if(endTime==null){
                    l.setStatus("审核中");
                }else{
                    l.setStatus("审核结束");
                }
            }
        }
        return orders;
    }

    //更新申请单状态
    @Override
    public void updateStatusByProcessInstanceId(String pid, Integer status) {
        lm.updateStatusByPid(pid,status);
    }
}
enity
public class LeaveOrder {
    private String lid;
    //申请人
    private String luser;
    private Integer ldays;
    private String lbegintime;
    private String lendtime;
    //流程实例id
    private String processinstanceid;
    //0:草稿,1:审核中,2:审核结束
    private String status="0";

    @Override
    public String toString() {
        return "LeaveOrder{" +
                "lid='" + lid + '\'' +
                ", luser='" + luser + '\'' +
                ", ldays=" + ldays +
                ", lbegintime='" + lbegintime + '\'' +
                ", lendtime='" + lendtime + '\'' +
                ", processinstanceid='" + processinstanceid + '\'' +
                ", status='" + status + '\'' +
                '}';
    }

    public String getStatus() {return status;}
    public void setStatus(String status) {this.status = status;}
    public String getLid() {return lid;}
    public void setLid(String lid) {this.lid = lid == null ? null : lid.trim();}
    public String getLuser() {return luser;}
    public void setLuser(String luser) {
        this.luser = luser == null ? null : luser.trim();
    }
    public Integer getLdays() {return ldays;}
    public void setLdays(Integer ldays) {this.ldays = ldays;}
    public String getLbegintime() {return lbegintime;}
    public void setLbegintime(String lbegintime) {this.lbegintime = lbegintime;}
    public String getLendtime() {return lendtime;}
    public void setLendtime(String lendtime) {this.lendtime = lendtime;}
    public String getProcessinstanceid() {return processinstanceid;}

    public void setProcessinstanceid(String processinstanceid) {
        this.processinstanceid = processinstanceid == null ? null : processinstanceid.trim();
    }
}
public class ProcessTask {
    private Task task;
    private Object obj;

    public ProcessTask(Task t, LeaveOrder leaveOrder) {
        this.task=t;
        this.obj=leaveOrder;
    }

    @Override
    public String toString() {
        return "ProcessTask{" +
                "task=" + task +
                ", obj=" + obj +
                '}';
    }
    public Task getTask() {return task;}
    public void setTask(Task task) {this.task = task;}
    public Object getObj() {return obj;}
    public void setObj(Object obj) {this.obj = obj;}
}
mapper
public interface LeaveOrderMapper {
    int insert(LeaveOrder record);
    int insertSelective(LeaveOrder record);
    int updateByPrimaryKeySelective(LeaveOrder record);
    List<LeaveOrder> selectOrders(String loginUser);
    void updateStatusByPid(@Param("pid") String pid, @Param("status") Integer status);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javasm.leave.mapper.LeaveOrderMapper">
  <resultMap id="BaseResultMap" type="com.javasm.leave.entity.LeaveOrder">
    <id column="lid" jdbcType="VARCHAR" property="lid" />
    <result column="luser" jdbcType="VARCHAR" property="luser" />
    <result column="ldays" jdbcType="INTEGER" property="ldays" />
    <result column="lbegintime" jdbcType="TIMESTAMP" property="lbegintime" />
    <result column="lendtime" jdbcType="TIMESTAMP" property="lendtime" />
    <result column="processinstanceid" jdbcType="VARCHAR" property="processinstanceid" />
    <result column="status" property="status" />
  </resultMap>
  <sql id="Base_Column_List">
    lid, luser, ldays, lbegintime, lendtime, processinstanceid
  </sql>
  <select id="selectOrders" parameterType="string" resultMap="BaseResultMap">
    select * from leave_order where luser=#{luser}
  </select>



  <insert id="insert" parameterType="com.javasm.leave.entity.LeaveOrder">
    insert into leave_order (lid, luser, ldays, 
      lbegintime, lendtime, processinstanceid
      )
    values (#{lid,jdbcType=VARCHAR}, #{luser,jdbcType=VARCHAR}, #{ldays,jdbcType=INTEGER}, 
      #{lbegintime,jdbcType=TIMESTAMP}, #{lendtime,jdbcType=TIMESTAMP}, #{processinstanceid,jdbcType=VARCHAR}
      )
  </insert>
  <insert id="insertSelective" parameterType="com.javasm.leave.entity.LeaveOrder">
    insert into leave_order
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="lid != null">
        lid,
      </if>
      <if test="luser != null">
        luser,
      </if>
      <if test="ldays != null">
        ldays,
      </if>
      <if test="lbegintime != null">
        lbegintime,
      </if>
      <if test="lendtime != null">
        lendtime,
      </if>
      <if test="processinstanceid != null">
        processinstanceid,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="lid != null">
        #{lid,jdbcType=VARCHAR},
      </if>
      <if test="luser != null">
        #{luser,jdbcType=VARCHAR},
      </if>
      <if test="ldays != null">
        #{ldays,jdbcType=INTEGER},
      </if>
      <if test="lbegintime != null">
        #{lbegintime,jdbcType=TIMESTAMP},
      </if>
      <if test="lendtime != null">
        #{lendtime,jdbcType=TIMESTAMP},
      </if>
      <if test="processinstanceid != null">
        #{processinstanceid,jdbcType=VARCHAR},
      </if>
    </trim>
  </insert>

  <update id="updateStatusByPid">
    update leave_order set status=#{status} where processinstanceid=#{pid}
  </update>

  <update id="updateByPrimaryKeySelective" parameterType="com.javasm.leave.entity.LeaveOrder">
    update leave_order
    <set>
      <if test="luser != null">
        luser = #{luser,jdbcType=VARCHAR},
      </if>
      <if test="ldays != null">
        ldays = #{ldays,jdbcType=INTEGER},
      </if>
      <if test="lbegintime != null">
        lbegintime = #{lbegintime,jdbcType=TIMESTAMP},
      </if>
      <if test="lendtime != null">
        lendtime = #{lendtime,jdbcType=TIMESTAMP},
      </if>
      <if test="processinstanceid != null">
        processinstanceid = #{processinstanceid,jdbcType=VARCHAR},
      </if>
      <if test="status != null">
        status = #{status},
      </if>
    </set>
    where lid = #{lid,jdbcType=VARCHAR}
  </update>

</mapper>
Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class TestLeave {

    @Resource
    private ILeaveService ls;

    //lhs:学生,  老班A:班主任   jy,wmz:段长

    @Test
    public void getMyLeaveOrders(){
        String loginUser="lhs";
        List<LeaveOrder> result = ls.getMyLeaveOrders(loginUser);
        System.out.println(result);
    }

    //保存草稿
    @Test
    public void addLeave(){
        String loginUser = "lhs";
        LeaveOrder o = new LeaveOrder();
        o.setLid(StringUtil.getUid());
        o.setLdays(1);
        o.setLuser(loginUser);
        ls.addLeaveOrder(o);
    }

    //提交申请单进行审核
    @Test
    public void submitLeaveOrder(){
        String lid="73a0c94ddd0e406a9442e7e856108115";//申请单id,前端传过来
        String loginUserName = "lhs";//可以前端传过来,可以从session中获取或token中获取
        int days = 1;//前端传递过来。
        LeaveOrder lo = new LeaveOrder();
        lo.setLid(lid);
        lo.setLdays(days);
        lo.setLuser(loginUserName);
        ls.submitLeaveOrder(lo,loginUserName);
    }

    //保存请假申请单并提交流程审核
    @Test
    public void addLeaveOrderAndSumit(){
        String loginUser = "lhs";
        LeaveOrder o = new LeaveOrder();
        o.setLid(StringUtil.getUid());
        o.setLdays(1);
        o.setLuser(loginUser);
        ls.addLeaveAndSubmit(o,loginUser);
    }

    //获取待办任务列表
    @Test
    public void getTodoList(){
        String loginuser="老班A";
        List<ProcessTask> todoTaskList = ls.getTodoTaskList(loginuser);
        System.out.println(todoTaskList);
    }

    //签收任务
    @Test
    public void doClaim(){
        String loginuser="wmz";
        String taskid="15004";
        ls.doClaim(taskid,loginuser);
    }

    //执行审批
    @Test
    public void doApprove(){
        String loginuser="老班A";
        String taskid="40009";
        String processinstnceid="40001";
        String comment="我是老班A,我同意了,注意安全";
        String result ="同意";

        ls.doApprove(loginuser,taskid,processinstnceid,comment,result);
    }
}

补:申请单状态更新 ( 新 )

在这里插入图片描述

${leaveEndListener.notify(execution)}
leaveEndListener-java文件名称
notify-方法名称

在这里插入图片描述

//leaveEndListener
//只要到结束流程那一步 就会自动取流程ID 更新状态
//开始不行 因为那时候还没有生成流程ID 取不到流程ID 

@Service("leaveEndListener")
public class LeaveEndListener {
    @Resource
    private ILeaveService ls;

    public void notify(DelegateExecution execution){
        ls.updateStatusByProcessInstanceId(execution.getProcessInstanceId(),2);
    }
}
8.流程跟踪
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring.xml")
public class TestHistoryService {
    @Resource
    private HistoryService hs;
    @Resource
    private TaskService ts;
    @Resource
    private RepositoryService rs;
    @Resource
    private ProcessEngine pe;

    private Comment getCommentByTaskId(String taskid,List<Comment> commentList){
        for(Comment comment:commentList){
            if(taskid.equals(comment.getTaskId()))
                return comment;
        }
        return null;
    }

    //作为申请人,根据流程实例id,查询该流程下的历史任务
    @Test
    public void getHistoryTaskList(){
        String pid="40001";//流程实例id
        //用于获取审批意见
        //根据流程实例id 获得某个流程实例的所有comment
        List<Comment> commentList = ts.getProcessInstanceComments(pid);

        //创建历史任务实例
        HistoricTaskInstanceQuery htq = hs.createHistoricTaskInstanceQuery();
        htq.processInstanceId(pid);
        //根据创建时间排序
        htq.orderByTaskCreateTime().asc();
        List<HistoricTaskInstance> taskList = htq.list();

        for(HistoricTaskInstance t:taskList){
            Date claimTime = t.getClaimTime();
            Date endTime = t.getEndTime();
            String name = t.getName();
            String assignee = t.getAssignee();
            String taskId = t.getId();
            Comment comment = getCommentByTaskId(taskId, commentList);
            if(comment!=null)
                System.out.println(name+"--"+assignee+"--"+claimTime+"-"+endTime+"--"+comment.getType()+"--"+comment.getFullMessage());
            else
                System.out.println(name+"--"+assignee+"--"+claimTime+"-"+endTime);
        }
    }



    //作为审批人,根据流程实例id,以及个人的登录名,获取本人的已办任务
    @Test
    public void getAlreadyDoTaskList(){
        String loginUserName="老班A";
        HistoricTaskInstanceQuery htq = hs.createHistoricTaskInstanceQuery();
        htq.taskAssignee(loginUserName);
        htq.processFinished();
        htq.processDefinitionKey(ProcessKey.LEAVE2);
        List<HistoricTaskInstance> list = htq.list();
        for(HistoricTaskInstance t:list){
            System.out.println(t.getName()+"--"+t.getId()+"--"+t.getProcessInstanceId()+"--"+t.getEndTime());
        }
    }

    //流程示意图创建(图片)
    @Test
    public void getHiTask() {
        String pid = "37501";//前端传递到后端的流程实例id

        HistoricProcessInstance hpi = hs.createHistoricProcessInstanceQuery().processInstanceId(pid).singleResult();//查询历史流程实例对象

        HistoricActivityInstanceQuery q = hs.createHistoricActivityInstanceQuery().processInstanceId(pid);//历史task查询
        List<HistoricActivityInstance> list = q.list();//根据流程实例id,查询该流程实例下所有已执行的任务

        List<String> highLightedActivitis = new ArrayList<String>();//已执行的任务的节点id
        for (HistoricActivityInstance h : list) {
            highLightedActivitis.add(h.getActivityId());
            System.out.println(h.getActivityId()+"-"+h.getActivityName());
        }

        //得到需要高亮的线的id集合
        ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) rs.getProcessDefinition(hpi.getProcessDefinitionId());
        List<String> highLightFlows=getRedFlows(definitionEntity, list);

        BpmnModel bpmnModel = rs.getBpmnModel(hpi.getProcessDefinitionId());
        ProcessEngineConfiguration c = pe.getProcessEngineConfiguration();
        ProcessDiagramGenerator pdg = c.getProcessDiagramGenerator();//流程示意图创建器
        InputStream in = pdg.generateDiagram(bpmnModel, "bmp", highLightedActivitis, highLightFlows, "宋体",
                "宋体", null, null, 1.0);

        //  <img src="/aa/ss">
        try {
            OutputStream os = new FileOutputStream("D:/aa.bmp");
            int r;
            byte[] bs = new byte[2048];
            while ((r = in.read(bs)) != -1) {
                os.write(bs, 0, r);
            }
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<String> getRedFlows(ProcessDefinitionEntity processDefinitionEntity,
                                     List<HistoricActivityInstance> historicActivityInstances) {
        // 用以保存高亮的线flowId
        List<String> highFlows = new ArrayList<String>();
        // 对历史流程节点进行遍历
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            ActivityImpl activityImpl = processDefinitionEntity
                    // 得到节点定义的详细信息
                    .findActivity(historicActivityInstances.get(i).getActivityId());
            // 用以保存后需开始时间相同的节点
            List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();
            ActivityImpl sameActivityImpl1 = processDefinitionEntity
                    .findActivity(historicActivityInstances.get(i + 1).getActivityId());
            // 将后面第一个节点放在时间相同节点的集合里
            sameStartTimeNodes.add(sameActivityImpl1);
            for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
                HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
                HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
                if (activityImpl1.getStartTime().equals(activityImpl2.getStartTime())) {
                    // 如果第一个节点和第二个节点开始时间相同保存
                    ActivityImpl sameActivityImpl2 = processDefinitionEntity
                            .findActivity(activityImpl2.getActivityId());
                    sameStartTimeNodes.add(sameActivityImpl2);
                } else {
                    // 有不相同跳出循环
                    break;
                }
            }
            // 取出节点的所有出去的线
            List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
            for (PvmTransition pvmTransition : pvmTransitions) {
                // 对所有的线进行遍历
                ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
                // 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
                if (sameStartTimeNodes.contains(pvmActivityImpl)) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值