1.基于Springboot上传图片到数据库
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>Proj_fileup</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Proj_fileup Maven Webapp</name>
<url>http://maven.apache.org</url>
<!-- 定义公共资源版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--JSP支持的依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency> -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.1.8</version>
</dependency>
<!-- 数据源依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>jconsole</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 数据库驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.2</version>
</dependency><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0-RC2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0-RC2</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.4.2.1-RELEASE</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatisplus-spring-boot-starter</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.1.8</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.4.5</version>
</dependency>
</dependencies>
<build>
<finalName>Proj_fileup</finalName>
</build>
</project>
2.在resources中加入application.properties
#SpringBoot服务端口配置
server.port=6060
server.context-path=/orgmodel.sysadmin.pwd=1
#spring.resources.static-locations=/css,/images,/img,/js
#SpringMVC JSP目录配置
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp#Http编码配置
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true#Rabbitmq配置
spring.rabbitmq.host=192.168.95.88
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
spring.rabbitmq.virtual-host=/#数据源配置
spring.datasource.name=myself
spring.datasource.url=jdbc:mysql://localhost:3306/fanmh?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.maxActive=20
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1#Mybatis实体类配置
#mybatis.mapper-locations=classpath:mapper/*.xml#MybatisPlus实体类配置
mybatis-plus.mapper-locations=classpath:/mapper/*.xml#日志配置
logging.file=d:/springboot.log
logging.level.com=DEBUG
logging.level.com.test.service.impl=DEBUG
3.在resources下创建mapper包在包下创建mapper.xml
<?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.test.mapper.FileupMapper">
<insert id="saveImg" parameterType="com.test.model.ImgInfo" >
insert into gf_img(id,name,contexttype,length,dt,content) values (#{id},#{name},#{contextType},
#{length},#{dt},#{content,jdbcType=BLOB})
</insert>
<select id="getImgById" resultType="com.test.model.ImgInfo">
select * from gf_img where id=#{id}
</select>
<select id="findimg" resultType="com.test.model.ImgInfo">
select * from gf_img
</select>
<delete id="deleteImgById" parameterType="String">
delete from gf_img where id=#{id}
</delete>
</mapper>
4.创建mapper包,在包下创建FileupMapper(与mapper.xml中mapper namespace指向一致)
package com.test.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import com.test.model.ImgInfo;
@Mapper
public interface FileupMapper {
public void saveImg(ImgInfo img);
public List<ImgInfo> findimg();
public ImgInfo getImgById(@Param("id") String id);
public void deleteImgById(@Param("id") String id);
}
5.定义Service接口
package com.test.service;
import java.util.List;
import com.test.model.ImgInfo;
public interface ImgService {
public void saveImg(ImgInfo img);
public List<ImgInfo> findimg();
public ImgInfo getImgById( String id);
public void deleteImgById( String id);
}
6.定义Service的实现类
package com.test.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.test.mapper.FileupMapper;
import com.test.model.ImgInfo;
import com.test.service.ImgService;@Service
public class ImgServicelmpl implements ImgService{
@Autowired
private FileupMapper mapper;
@Override
public void saveImg(ImgInfo img) {
// TODO Auto-generated method stub
try {
mapper.saveImg(img);
} catch (Exception e) {
e.printStackTrace();
}
}@Override
public ImgInfo getImgById(String id) {
// TODO Auto-generated method stub
try {
return mapper.getImgById(id);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}@Override
public void deleteImgById(String id) {
// TODO Auto-generated method stub
try {
mapper.deleteImgById(id);
} catch (Exception e) {
e.printStackTrace();
}
}@Override
public List<ImgInfo> findimg() {
return mapper.findimg();
}}
7.定义Controller与前台传载数据
package com.test.controller;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.List;import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;import com.test.model.ImgInfo;
import com.test.service.ImgService;
import com.test.util.UUID;
import com.test.util.Util;@Controller
public class FileupController {
@Autowired
private ImgService service;
@RequestMapping("/img.action")
public String list()
{
return "fileup";
}
@RequestMapping("/imgsave.action")
@ResponseBody
public String imgsave(HttpServletRequest req,ImgInfo img)
{
try {
MultipartHttpServletRequest mreq = (MultipartHttpServletRequest)req;
MultipartFile multipartFile = mreq.getFile("uploadfile");
if(!"".equals(Util.fmtStr(multipartFile.getOriginalFilename())))
{
InputStream is = multipartFile.getInputStream();
byte[] data = FileCopyUtils.copyToByteArray(is);
String name = multipartFile.getOriginalFilename();
String contextType = multipartFile.getContentType();
Long length = new Long(data.length);
ImgInfo imgs = new ImgInfo();
String id = UUID.create("attachement");
imgs.setId(id);
imgs.setName(name);
imgs.setContextType(contextType);
imgs.setLength(length);
imgs.setDt(new Timestamp(System.currentTimeMillis()).toString());
imgs.setContent(data);
service.saveImg(imgs);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@RequestMapping("/borrowatt.action")
@ResponseBody
public List<ImgInfo> borrowatt(HttpServletRequest req)
{
List<ImgInfo> list = service.findimg();
return list;
}
@RequestMapping("/imgdelete.action")
@ResponseBody
public void imgdelete(HttpServletRequest req)
{
String id = req.getParameter("id");
service.deleteImgById(id);
}}
8.定义util包包中包含(Clock DownAttServlet Util UUID 四个公共类)
①Clock类
package com.test.util;
import org.apache.commons.logging.Log;
public final class Clock
extends Thread
{/**
* The number of clock ticks in each unsynchronized cycle.
* The default is 100 milliseconds.
*/
public static final int UNSYNCH_TICKS = 100;
/**
* The number of unsychronized cycles before the clock is
* synchronized with the system clock. The default is 10.
*/
public static final int SYNCH_EVERY = 10;
/**
* The current clock.
*/
private static long _clock;
/**
* The number of clock ticks to skip before incrementing the internal clock.
*/
private static int _unsynchTicks;
/**
* The number of cycles to skip before synchronizing with the system clock.
*/
private static int _synchEvery;
/**
* The amount of time in milliseconds by which to advance the clock compared
* to the system clock.
*/
private static long _advance;
/**
* Used to adjust the clock when it gets out of synch. Based on the different
* between the last clock and the system clock at the point of synchronization,
* divided by synchEvery.
*/
private static int _adjust;/**
* Property that determines the number of clock ticks for each
* unsynchronized cycle. The value is an integer, the percision is
* milliseconds. The name of this property is <tt>tyrex.clock.unsynchicks</tt>.
*/
public static final String PROPERTY_UNSYNCH_TICKS = "UUID.clock.unsynchTicks";/**
* Property that determines the number of unsynchronized cycles
* before the clock is synchronized. The value is an integer.
* The name of this property is <tt>tyrex.clock.synchEvery</tt>.
*/
public static final String PROPERTY_SYNCH_EVERY = "UUID.clock.synchEvery";/**
* Returns the current clock.
*
* @return The current clock
*/
public static synchronized long clock()
{
// Synchronization is required since clock is a long.
return _clock;
}
/**
* Sets the number of clock ticks in each unsynchronized cycle.
* Use zero to restore the default value.
* <p>
* The internal clock is advanced every cycle, the length of the
* cycle is controlled by this property. A higher value results
* in a lower clock resolution.
*
* @param ticks The number of clock ticks (milliseconds) for
* each unsynchronized cycle
*/
public static void setUnsynchTicks( int ticks )
{
if ( ticks <= 0 )
ticks = UNSYNCH_TICKS;
else if ( ticks < 100 )
ticks = 100;
_unsynchTicks = ticks;
}
/**
* Returns the number of clock ticks in each unsynchronized cycle.
*
* @return The number of clock ticks (milliseconds) for
* each unsynchronized cycle
*/
public static int getUnsynchTicks()
{
return _unsynchTicks;
}
/**
* Sets the number of unsynchronized cycles before the clock
* is synchronized with the system clock.
* <p>
* Synchronization will occur every <tt>unsynchTicks * synchEvery</tt>
* milliseconds. The larger the value, the less accurate
* the clock is.
*
* @param every The number of unsynchronized cycles
*/
public static void setSynchEvery( int every )
{
if ( every <= 0 )
every = SYNCH_EVERY;
_synchEvery = every;
}
/**
* Artficially advances the clock.
*
* @param byMillis The number of milliseconds by which to
* advance the clock (must be positive)
*/
public synchronized static void advance( long byMillis )
{
// Synchronization is required since clock is a long.
_advance += byMillis;
_clock += byMillis;
}
/**
* Returns the number of milliseconds by which the clock is
* advanced.
*
* @return The number of milliseconds by which the clock is
* advanced
*/
public static long getAdvance()
{
return _advance;
}
public void run()
{
while ( true ) {
try {
for ( int i = 0 ; i < _synchEvery ; ++i ) {
sleep( _unsynchTicks );
synchronized ( Clock.class ) {
_clock += _unsynchTicks + _adjust;
}
}
synchronize();
} catch ( Throwable thrw ) {}
}
}
public static synchronized long synchronize()
{
long current;
long retarded;
long clock;
int adjust;current = System.currentTimeMillis();
clock = _clock;
retarded = clock - _advance;
// Adjust clock to new difference
if ( current != retarded ) {
adjust = (int) ( current - retarded ) / _synchEvery;
if ( adjust != 0 ) {
_adjust += adjust;
/*
if ( Configuration.verbose )
Logger.tyrex.debug( "Clock late by " + ( current - retarded ) +
"ms -> synchronized, adjusting by " + _clock._adjust );
*/
}
}
// Make sure clock is progressive
if ( current > retarded ) {
clock = current + _advance;
_clock = clock;
}
return clock;
}
private Clock()
{
super("com.eway.util.clockDaemon" );
_clock = System.currentTimeMillis();
setPriority( Thread.MAX_PRIORITY );
setDaemon( true );
start();
}
static {
int value;value = 100;
_unsynchTicks = value > 0 ? value : UNSYNCH_TICKS;
value = 10;
_synchEvery = value > 0 ? value : SYNCH_EVERY;new Clock();
}
public static void main( String[] args )
{
long clock;
int count;try {
count = 1000000;
System.out.println( "Using Clock.clock()" );
clock = System.currentTimeMillis();
for ( int i = 0 ; i < count ; ++i ) {
if ( ( i % 100 ) == 0 )
synchronize();
else
clock();
}
clock = System.currentTimeMillis() - clock;
System.out.println( "Performed " + count + " in " + clock + "ms" );
System.out.println( "Using System.currentTimeMillis()" );
clock = System.currentTimeMillis();
for ( int i = 0 ; i < count ; ++i )
System.currentTimeMillis();
clock = System.currentTimeMillis() - clock;
System.out.println( "Performed " + count + " in " + clock + "ms" );
} catch ( Exception except ) { }
}
}
② DownAttServlet类
package com.test.util;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.test.model.ImgInfo;
import com.test.service.ImgService;@WebServlet(urlPatterns = "/IMGfile/*")
public class DownAttServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public DownAttServlet() {
super();
}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try
{
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-store");
response.setDateHeader("Expires",-1);
String attId = request.getParameter("attid");
System.out.println("attId==="+attId);
ImgService attserv = (ImgService)Util.getBean(ImgService.class);
ImgInfo att = attserv.getImgById(attId);
System.out.println("att==="+att);
response.setHeader("Content-Disposition", "attachment; filename="+att.getName());
ServletOutputStream os = response.getOutputStream();
System.out.println("os==="+os);
System.out.println("att.getContent()==="+att.getContent());
os.write(att.getContent());
}
catch(Exception e)
{
e.printStackTrace();
}
}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}}
③Util类
package com.test.util;
import java.io.FileInputStream;
import java.util.Properties;
import java.util.StringTokenizer;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
public class Util {
private static Logger log = LoggerFactory.getLogger(Util.class);
private static Properties wfProp = null;
private static ApplicationContext ctx = null;
public static void setCtx(ApplicationContext actx)
{
ctx = actx;
}
public static Object getBean(Class clz)
{
return ctx.getBean(clz);
}
public static String fmtStr(Object obj)
{
if(obj == null)
return "";
return obj.toString();
}
public static String getString(javax.servlet.http.HttpServletRequest req,String name)
{
String value = fmtStr(req.getParameter(name));
return value;
}
public static Integer getInteger(javax.servlet.http.HttpServletRequest req,String name)
{
String value = fmtStr(req.getParameter(name));
try
{
return Integer.parseInt(value);
}
catch(Exception e)
{
return new Integer(0);
}
}
public static String getMD5(String pwd)
{
byte[] source = pwd.getBytes();
String s = null;
char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
try
{
java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
md.update( source );
byte tmp[] = md.digest();
char str[] = new char[16 * 2];
int k = 0;
for (int i = 0; i < 16; i++) {
byte byte0 = tmp[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
s = new String(str);
}catch( Exception e ) {
e.printStackTrace();
}
return s;
}
public static Properties getLoginProp(String loginId)
{
StringTokenizer st = new StringTokenizer(loginId,":");
String flag = "";
if(st.hasMoreElements())
flag = st.nextToken();
String loginId2 = "";
if(st.hasMoreElements())
loginId2 = st.nextToken();
Properties prop = new Properties();
if(flag.endsWith("test"))
{
flag = flag.substring(0, flag.length()-4);
prop.setProperty("testmode","test");
}
else
prop.setProperty("testmode","no");
prop.setProperty("flag", flag);
prop.setProperty("loginid", loginId2);
return prop;
}public static Properties getRoleProp(String roleId)
{
StringTokenizer st = new StringTokenizer(roleId,":");
String flag = "";
if(st.hasMoreElements())
flag = st.nextToken();
String name = "";
if(st.hasMoreElements())
name = st.nextToken();
Properties prop = new Properties();
prop.setProperty("flag", flag);
prop.setProperty("name", name);
return prop;
}
public static String getGuFangHome()
{
try
{
String gfpath = System.getProperty("GUFANG_HOME");
if(gfpath != null && !"".equals(gfpath))
return gfpath;
ClassLoader cl = Util.class.getClassLoader();
java.net.URL url = cl.getResource("com/test/statusflow/Util.class");
String path = url.getPath();
String packagePath = "com/test/statusflow/Util.class";
int pos = path.indexOf(packagePath);
String path2 = path.substring(0,pos)+"GUFANG_HOME/";
return path2;
}
catch(Exception e)
{
e.printStackTrace();
}
return "";
}
public static String getLastWorkflow(String workflow)
{
try
{
if(wfProp == null)
{
String home = getGuFangHome();
String fileName = home + "/workflow/wfconf.properties";
FileInputStream fis = new FileInputStream(fileName);
wfProp = new Properties();
wfProp.load(fis);
fis.close();
}
}
catch(Exception e)
{
wfProp = new Properties();
log.error("getLastWorkflow", e);
}
String wf = wfProp.getProperty(workflow);
if("".equals(Util.fmtStr(wf)))
return workflow;
else
return wf;
}
}
④UUID类
package com.test.util;
import java.util.*;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
import java.security.SecureRandom;public final class UUID
{public static final String PREFIX = "ID:";
/**
* The identifier resolution in bytes. Identifiers are 16-byte
* long, or 128 bits. Without a prefix, an identifier can be
* represented as 36 hexadecimal digits and hyphens.
* (4 hyphens are used in the UUID format)
*/
public static final int RESOLUTION_BYTES = 16;public static final int MAXIMUM_LENGTH = 64;
/**
* The maximum length of an identifier prefix. Identifiers
* created using {@link #create(String) create(String)} with
* a prefix that is no longer than the maximum prefix size
* are guaranteed to be within the maximum length allowed
* and need not be trimmed.
*/
public static final int MAXIMUM_PREFIX = 28;
/**
* UUID state file property that determined the node identifier.
* The value of this property is an hexadecimal 47-bit value.
* The name of this property is <tt>uuid.nodeIdentifier</tt>.
*/
public static final String PROPERTY_NODE_IDENTIFIER = "uuid.nodeIdentifier";
/**
* UUID state file property that determined the clock sequence.
* The value of this property is an hexadecimal 12-bit value.
* The name of this property is <tt>uuid.clockSequence</tt>.
*/
public static final String PROPERTY_CLOCK_SEQUENCE = "uuid.clockSequence";
/**
* Name of the UUID state file. If no file was specified in the
* configuration properties, this file name is used. The file
* name is <tt>uuid.state</tt>.
*/
public static final String UUID_STATE_FILE = "uuid.state";
/**
* The variant value determines the layout of the UUID. This
* variant is specified in the IETF February 4, 1998 draft.
* Used for character octets.
*/
private static final int UUID_VARIANT_OCTET = 0x08;
/**
* The variant value determines the layout of the UUID. This
* variant is specified in the IETF February 4, 1998 draft.
* Used for byte array.
*/
private static final int UUID_VARIANT_BYTE = 0x80;
/**
* The version identifier for a time-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* character octets.
*/
private static final int UUID_VERSION_CLOCK_OCTET = 0x01;
/**
* The version identifier for a time-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* byte array.
*/
private static final int UUID_VERSION_CLOCK_BYTE = 0x10;
/**
* The version identifier for a name-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* character octets.
*/
private static final int UUID_VERSION_NAME_OCTET = 0x03;
/**
* The version identifier for a name-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* byte array.
*/
private static final int UUID_VERSION_NAME_BYTE = 0x30;
/**
* The version identifier for a random-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* character octets.
*/
private static final int UUID_VERSION_RANDOM_CLOCK = 0x04;
/**
* The version identifier for a random-based UUID. This version
* is specified in the IETF February 4, 1998 draft. Used for
* byte array.
*/
private static final int UUID_VERSION_RANDOM_BYTE = 0x40;
/**
* The difference between Java clock and UUID clock. Java clock
* is base time is January 1, 1970. UUID clock base time is
* October 15, 1582.
*/
private static final long JAVA_UUID_CLOCK_DIFF = 0x0b1d069b5400L;
/**
* Efficient mapping from 4 bit value to lower case hexadecimal digit.
*/
private final static char[] HEX_DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* The number of UUIDs that can be generated per clock tick.
* UUID assumes a clock tick every 100 nanoseconds. The actual
* clock ticks are measured in milliseconds and based on the
* sync-every property of the clock. The product of these two
* values is used to set this variable.
*/
private static int _uuidsPerTick;
/**
* The number of UUIDs generated in this clock tick. This counter
* is reset each time the clock is advanced a tick. When it reaches
* the maximum number of UUIDs allowed per tick, we block until the
* clock advances.
*/
private static int _uuidsThisTick;
/**
* The last clock. Whenever the clock changes, we record the last clock
* to identify when we get a new clock, or when we should increments
* the UUIDs per tick counter.
*/
private static long _lastClock;
/**
* The clock sequence. The clock sequence is obtained from the UUID
* properties and incremented by one each time we boot, or is
* generated randomaly if missing in the UUID properties. The clock
* sequence is made of four hexadecimal digits.
*/
private static char[] _clockSeqOctet;
/**
* The clock sequence. The clock sequence is obtained from the UUID
* properties and incremented by one each time we boot, or is
* generated randomaly if missing in the UUID properties. The clock
* sequence is made of two bytes.
*/
private static byte[] _clockSeqByte;
/**
* The node identifier. The node identifier is obtained from the
* UUID properties, or is generated if missing in the UUID properties.
* The node identifier is made of twelve hexadecimal digits.
*/
private static char[] _nodeIdentifierOctet;
/**
* The node identifier. The node identifier is obtained from the
* UUID properties, or is generated if missing in the UUID properties.
* The node identifier is made of six bytes.
*/
private static byte[] _nodeIdentifierByte;/**
* Property that determines whether to use secure or standard random
* number generator. This value is true or false. The name of this
* property is <tt>tyrex.random.secure</tt>.
*/
public static final String PROPERTY_SECURE_RANDOM = "UUID.random.secure";
/**
* Creates and returns a new identifier.
*
* @return An identifier
*/
public static String create()
{
return String.valueOf( createTimeUUIDChars() );
}
public static String create( String prefix )
{
StringBuffer buffer=new StringBuffer(16);if ( prefix == null )
{
buffer.append("0000");
}
else
{
prefix = prefix + "0000";
buffer.append(prefix.substring(0,4));
}
buffer.append( createTimeUUIDChars() );
return buffer.toString();
}
/**
* Creates and returns a new identifier.
*
* @return An identifier
*/
public static byte[] createBinary()
{
return createTimeUUIDBytes();
}
/**
* Converts a prefixed identifier into a byte array. An exception
* is thrown if the identifier does not match the excepted textual
* encoding.
* <p>
* The format for the identifier is <code>prefix{nn|-}*</code>:
* a prefix followed by a sequence of bytes, optionally separated
* by hyphens. Each byte is encoded as a pair of hexadecimal digits.
*
* @param prefix The identifier prefix
* @param identifier The prefixed identifier
* @return The identifier as an array of bytes
* @throws InvalidIDException The identifier does not begin with
* the prefix, or does not consist of a sequence of hexadecimal
* digit pairs, optionally separated by hyphens
*/
public static byte[] toBytes( String prefix, String identifier )
throws InvalidIDException
{
int index;
char digit;
byte nibble;
byte[] bytes;
byte[] newBytes;if ( identifier == null )
throw new IllegalArgumentException( "Argument identifier is null" );
if ( prefix == null )
throw new IllegalArgumentException( "Argument prefix is null" );
if ( ! identifier.startsWith( prefix ) )
throw new InvalidIDException("");index = 0;
bytes = new byte[ ( identifier.length() - prefix.length() ) / 2 ];
for ( int i = prefix.length() ; i < identifier.length() ; ++i ) {
digit = identifier.charAt( i );
if ( digit == '-' )
continue;
if ( digit >= '0' && digit <= '9' )
nibble = (byte) ( ( digit - '0' ) << 4 );
else if ( digit >= 'A' && digit <= 'F' )
nibble = (byte) ( ( digit - ( 'A' - 0x0A ) ) << 4 );
else if ( digit >= 'a' && digit <= 'f' )
nibble = (byte) ( ( digit - ( 'a' - 0x0A ) ) << 4 );
else
throw new InvalidIDException("");
++i;
if ( i == identifier.length() )
throw new InvalidIDException("");
digit = identifier.charAt( i );
if ( digit >= '0' && digit <= '9' )
nibble = (byte) ( nibble | ( digit - '0' ) );
else if ( digit >= 'A' && digit <= 'F' )
nibble = (byte) ( nibble | ( digit - ( 'A' - 0x0A ) ) );
else if ( digit >= 'a' && digit <= 'f' )
nibble = (byte) ( nibble | ( digit - ( 'a' - 0x0A ) ) );
else
throw new InvalidIDException("");
bytes[ index ] = nibble;
++index;
}
if ( index == bytes.length )
return bytes;
newBytes = new byte[ index ];
while ( index-- > 0 )
newBytes[ index ] = bytes[ index ];
return newBytes;
}
/**
* Converts an identifier into a byte array. An exception is
* thrown if the identifier does not match the excepted textual
* encoding.
* <p>
* The format for the identifier is <code>{nn|-}*</code>:
* a sequence of bytes, optionally separated by hyphens.
* Each byte is encoded as a pair of hexadecimal digits.
*
* @param identifier The identifier
* @return The identifier as an array of bytes
* @throws InvalidIDException The identifier does not consist
* of a sequence of hexadecimal digit pairs, optionally separated
* by hyphens
*/
public static byte[] toBytes( String identifier )
throws InvalidIDException
{
int index;
char digit;
byte nibble;
byte[] bytes;
byte[] newBytes;if ( identifier == null )
throw new IllegalArgumentException( "Argument identifier is null" );
index = 0;
bytes = new byte[ identifier.length() / 2 ];
for ( int i = 0 ; i < identifier.length() ; ++i ) {
digit = identifier.charAt( i );
if ( digit == '-' )
continue;
if ( digit >= '0' && digit <= '9' )
nibble = (byte) ( ( digit - '0' ) << 4 );
else if ( digit >= 'A' && digit <= 'F' )
nibble = (byte) ( ( digit - ( 'A' - 0x0A ) ) << 4 );
else if ( digit >= 'a' && digit <= 'f' )
nibble = (byte) ( ( digit - ( 'a' - 0x0A ) ) << 4 );
else
throw new InvalidIDException( "无效的字符" );
++i;
if ( i == identifier.length() )
throw new InvalidIDException("无效的数字");
digit = identifier.charAt( i );
if ( digit >= '0' && digit <= '9' )
nibble = (byte) ( nibble | ( digit - '0' ) );
else if ( digit >= 'A' && digit <= 'F' )
nibble = (byte) ( nibble | ( digit - ( 'A' - 0x0A ) ) );
else if ( digit >= 'a' && digit <= 'f' )
nibble = (byte) ( nibble | ( digit - ( 'a' - 0x0A ) ) );
else
throw new InvalidIDException( "无效的字符" );
bytes[ index ] = nibble;
++index;
}
if ( index == bytes.length )
return bytes;
newBytes = new byte[ index ];
while ( index-- > 0 )
newBytes[ index ] = bytes[ index ];
return newBytes;
}
/**
* Converts a byte array into a prefixed identifier.
* <p>
* The format for the identifier is <code>prefix{nn|-}*</code>:
* a prefix followed by a sequence of bytes, optionally separated
* by hyphens. Each byte is encoded as a pair of hexadecimal digits.
*
* @param prefix The identifier prefix
* @param byte An array of bytes
* @return A string representation of the identifier
*/
public static String fromBytes( String prefix, byte[] bytes )
{
StringBuffer buffer;if ( prefix == null )
throw new IllegalArgumentException( "Argument prefix is null" );
if ( bytes == null || bytes.length == 0 )
throw new IllegalArgumentException( "Argument bytes is null or an empty array" );
buffer = new StringBuffer( prefix );
for ( int i = 0 ; i < bytes.length ; ++i ) {
buffer.append( HEX_DIGITS[ ( bytes[ i ] & 0xF0 ) >> 4 ] );
buffer.append( HEX_DIGITS[ ( bytes[ i ] & 0x0F ) ] );
}
return buffer.toString();
}
/**
* Converts a byte array into an identifier.
* <p>
* The format for the identifier is <code>{nn|-}*</code>: a sequence
* of bytes, optionally separated by hyphens. Each byte is encoded as
* a pair of hexadecimal digits.
*
* @param byte An array of bytes
* @return A string representation of the identifier
*/
public static String fromBytes( byte[] bytes )
{
StringBuffer buffer;if ( bytes == null || bytes.length == 0 )
throw new IllegalArgumentException( "Argument bytes is null or an empty array" );
buffer = new StringBuffer();
for ( int i = 0 ; i < bytes.length ; ++i ) {
buffer.append( HEX_DIGITS[ ( bytes[ i ] & 0xF0 ) >> 4 ] );
buffer.append( HEX_DIGITS[ ( bytes[ i ] & 0x0F ) ] );
}
return buffer.toString();
}
/**
* Truncates an identifier so that it does not extend beyond
* {@link #MAXIMUM_LENGTH} characters in length.
*
* @param identifier An identifier
* @return An identifier trimmed to {@link #MAXIMUM_LENGTH} characters
*/
public static String trim( String identifier )
{
if ( identifier == null )
throw new IllegalArgumentException( "Argument identifier is null" );
if ( identifier.length() > MAXIMUM_LENGTH )
return identifier.substring( 0, MAXIMUM_LENGTH );
return identifier;
}
/**
* Returns a time-based UUID as a character array. The UUID
* identifier is always 36 characters long.
*
* @return A time-based UUID
*/
public static char[] createTimeUUIDChars()
{
long clock;
char[] chars;
long nextClock;// Acquire lock to assure synchornized generation
synchronized ( UUID.class ) {
clock = Clock.clock();
while ( true ) {
if ( clock > _lastClock ) {
// Since we are using the clock interval for the UUID space,
// we must make sure the next clock provides sufficient
// room so UUIDs do not roll over.
nextClock = _lastClock + ( _uuidsThisTick / 100 );
if ( clock <= nextClock )
clock = Clock.synchronize();
if ( clock > nextClock ) {
// Clock reading changed since last UUID generated,
// reset count of UUIDs generated with this clock.
_uuidsThisTick = 0;
_lastClock = clock;
// Adjust UUIDs per tick in case the clock sleep ticks
// have changed.
_uuidsPerTick = Clock.getUnsynchTicks() * 100;
break;
}
}if ( _uuidsThisTick + 1 < _uuidsPerTick ) {
// Clock did not advance, but able to create more UUIDs
// for this clock, proceed.
++ _uuidsThisTick;
break;
}// Running out of UUIDs for the current clock tick, must
// wait until clock advances. Possible that clock did not
// advance in background, so try to synchronize it first.
clock = Clock.synchronize();
if ( clock <= _lastClock ) {
while ( clock <= _lastClock ) {
// UUIDs generated too fast, suspend for a while.
try {
Thread.currentThread().sleep( Clock.getUnsynchTicks() );
} catch ( InterruptedException except ) { }
clock = Clock.synchronize();
}
}
}// Modify Java clock (milliseconds) to UUID clock (100 nanoseconds).
// Add the count of uuids to low order bits of the clock reading,
// assuring we get a unique clock.
clock = ( _lastClock + JAVA_UUID_CLOCK_DIFF ) * 100 + _uuidsThisTick;chars=new char[12];
chars[ 0 ] = HEX_DIGITS[ (int) ( ( clock >> 28 ) & 0x0F ) ];
chars[ 1 ] = HEX_DIGITS[ (int) ( ( clock >> 24 ) & 0x0F ) ];
chars[ 2 ] = HEX_DIGITS[ (int) ( ( clock >> 20 ) & 0x0F ) ];
chars[ 3 ] = HEX_DIGITS[ (int) ( ( clock >> 16 ) & 0x0F ) ];
chars[ 4 ] = HEX_DIGITS[ (int) ( ( clock >> 12 ) & 0x0F ) ];
chars[ 5 ] = HEX_DIGITS[ (int) ( ( clock >> 8 ) & 0x0F ) ];
chars[ 6 ] = HEX_DIGITS[ (int) ( ( clock >> 4 ) & 0x0F ) ];
chars[ 7 ] = HEX_DIGITS[ (int) ( clock & 0x0F ) ];
chars[ 8 ] = _clockSeqOctet[ 0 ];
chars[ 9 ] = _clockSeqOctet[ 1 ];
chars[ 10 ] = _clockSeqOctet[ 2 ];
chars[ 11 ] = _clockSeqOctet[ 3 ];
/**
chars = new char[ 36 ];
// Add the low field of the clock (4 octets )
chars[ 0 ] = HEX_DIGITS[ (int) ( ( clock >> 28 ) & 0x0F ) ];
chars[ 1 ] = HEX_DIGITS[ (int) ( ( clock >> 24 ) & 0x0F ) ];
chars[ 2 ] = HEX_DIGITS[ (int) ( ( clock >> 20 ) & 0x0F ) ];
chars[ 3 ] = HEX_DIGITS[ (int) ( ( clock >> 16 ) & 0x0F ) ];
chars[ 4 ] = HEX_DIGITS[ (int) ( ( clock >> 12 ) & 0x0F ) ];
chars[ 5 ] = HEX_DIGITS[ (int) ( ( clock >> 8 ) & 0x0F ) ];
chars[ 6 ] = HEX_DIGITS[ (int) ( ( clock >> 4 ) & 0x0F ) ];
chars[ 7 ] = HEX_DIGITS[ (int) ( clock & 0x0F ) ];
chars[ 8 ] = '-';
// Add the medium field of the clock (2 octets)
chars[ 9 ] = HEX_DIGITS[ (int) ( ( clock >> 44 ) & 0x0F ) ];
chars[ 10 ] = HEX_DIGITS[ (int) ( ( clock >> 40 ) & 0x0F ) ];
chars[ 11 ] = HEX_DIGITS[ (int) ( ( clock >> 36 ) & 0x0F ) ];
chars[ 12 ] = HEX_DIGITS[ (int) ( ( clock >> 32 ) & 0x0F ) ];
chars[ 13 ] = '-';
// Add the high field of the clock multiplexed with version number (2 octets)
chars[ 14 ] = HEX_DIGITS[ (int) ( ( ( clock >> 60 ) & 0x0F ) | UUID_VERSION_CLOCK_OCTET ) ];
chars[ 15 ] = HEX_DIGITS[ (int) ( ( clock >> 56 ) & 0x0F ) ];
chars[ 16 ] = HEX_DIGITS[ (int) ( ( clock >> 52 ) & 0x0F ) ];
chars[ 17 ] = HEX_DIGITS[ (int) ( ( clock >> 48 ) & 0x0F ) ];
chars[ 18 ] = '-';
// Add the clock sequence and version identifier (2 octets)
chars[ 19 ] = _clockSeqOctet[ 0 ];
chars[ 20 ] = _clockSeqOctet[ 1 ];
chars[ 21 ] = _clockSeqOctet[ 2 ];
chars[ 22 ] = _clockSeqOctet[ 3 ];
chars[ 23 ] = '-';
// Add the node identifier (6 octets)
chars[ 24 ] = _nodeIdentifierOctet[ 0 ];
chars[ 25 ] = _nodeIdentifierOctet[ 1 ];
chars[ 26 ] = _nodeIdentifierOctet[ 2 ];
chars[ 27 ] = _nodeIdentifierOctet[ 3 ];
chars[ 28 ] = _nodeIdentifierOctet[ 4 ];
chars[ 29 ] = _nodeIdentifierOctet[ 5 ];
chars[ 30 ] = _nodeIdentifierOctet[ 6 ];
chars[ 31 ] = _nodeIdentifierOctet[ 7 ];
chars[ 32 ] = _nodeIdentifierOctet[ 8 ];
chars[ 33 ] = _nodeIdentifierOctet[ 9 ];
chars[ 34 ] = _nodeIdentifierOctet[ 10 ];
chars[ 35 ] = _nodeIdentifierOctet[ 11 ];
*/
}
return chars;
}
/**
* Returns a time-based UUID as a character array. The UUID
* identifier is always 16 bytes long.
*
* @return A time-based UUID
*/
public static byte[] createTimeUUIDBytes()
{
long clock;
byte[] bytes;
long nextClock;// Acquire lock to assure synchornized generation
synchronized ( UUID.class ) {
clock = Clock.clock();
while ( true ) {
if ( clock > _lastClock ) {
// Since we are using the clock interval for the UUID space,
// we must make sure the next clock provides sufficient
// room so UUIDs do not roll over.
nextClock = _lastClock + ( _uuidsThisTick / 100 );
if ( clock <= nextClock )
clock = Clock.synchronize();
if ( clock > nextClock ) {
// Clock reading changed since last UUID generated,
// reset count of UUIDs generated with this clock.
_uuidsThisTick = 0;
_lastClock = clock;
// Adjust UUIDs per tick in case the clock sleep ticks
// have changed.
_uuidsPerTick = Clock.getUnsynchTicks() * 100;
break;
}
}if ( _uuidsThisTick + 1 < _uuidsPerTick ) {
// Clock did not advance, but able to create more UUIDs
// for this clock, proceed.
++ _uuidsThisTick;
break;
}// Running out of UUIDs for the current clock tick, must
// wait until clock advances. Possible that clock did not
// advance in background, so try to synchronize it first.
clock = Clock.synchronize();
if ( clock <= _lastClock ) {
while ( clock <= _lastClock ) {
// UUIDs generated too fast, suspend for a while.
try {
Thread.currentThread().sleep( Clock.getUnsynchTicks() );
} catch ( InterruptedException except ) { }
clock = Clock.synchronize();
}
}
}// Modify Java clock (milliseconds) to UUID clock (100 nanoseconds).
// Add the count of uuids to low order bits of the clock reading,
// assuring we get a unique clock.
clock = ( _lastClock + JAVA_UUID_CLOCK_DIFF ) * 100 + _uuidsThisTick;bytes = new byte[ 16 ];
// Add the low field of the clock (4 octets )
bytes[ 0 ] = (byte) ( ( clock >> 24 ) & 0xFF );
bytes[ 1 ] = (byte) ( ( clock >> 16 ) & 0xFF );
bytes[ 2 ] = (byte) ( ( clock >> 8 ) & 0xFF );
bytes[ 3 ] = (byte) ( clock & 0xFF );
// Add the medium field of the clock (2 octets)
bytes[ 4 ] = (byte) ( ( clock >> 40 ) & 0xFF );
bytes[ 5 ] = (byte) ( ( clock >> 32 ) & 0xFF );
// Add the high field of the clock multiplexed with version number (2 octets)
bytes[ 6 ] = (byte) ( ( ( clock >> 60 ) & 0xFF ) | UUID_VERSION_CLOCK_BYTE );
bytes[ 7 ] = (byte) ( ( clock >> 48 ) & 0xFF );
// Add the clock sequence and version identifier (2 octets)
bytes[ 8 ] = _clockSeqByte[ 0 ];
bytes[ 9 ] = _clockSeqByte[ 1 ];
// Add the node identifier (6 octets)
bytes[ 10 ] = _nodeIdentifierByte[ 0 ];
bytes[ 11 ] = _nodeIdentifierByte[ 1 ];
bytes[ 12 ] = _nodeIdentifierByte[ 2 ];
bytes[ 13 ] = _nodeIdentifierByte[ 3 ];
bytes[ 14 ] = _nodeIdentifierByte[ 4 ];
bytes[ 15 ] = _nodeIdentifierByte[ 5 ];
}
return bytes;
}
/**
* Returns true if the UUID was created on this machine.
* Determines the source of the UUID based on the node
* identifier.
*
* @param uuid The UUID as a byte array
* @return True if created on this machine
*/
public static boolean isLocal( byte[] uuid )
{
if ( uuid == null )
throw new IllegalArgumentException( "Argument uuid is null" );
if ( uuid.length != 16 )
return false;
return ( uuid[ 10 ] == _nodeIdentifierByte[ 0 ] &&
uuid[ 11 ] == _nodeIdentifierByte[ 1 ] &&
uuid[ 12 ] == _nodeIdentifierByte[ 2 ] &&
uuid[ 13 ] == _nodeIdentifierByte[ 3 ] &&
uuid[ 14 ] == _nodeIdentifierByte[ 4 ] &&
uuid[ 15 ] == _nodeIdentifierByte[ 5 ] );
}/**
* Read the UUID state and set the node identifier and clock
* sequence. This method is called exactly once, the first
* time a UUID is requested.
* <p>
* If attempts to load the UUID state from the UUID state
* file. If the file is not found, or does not contain a node
* identifier, a random node identifier is created.
* <p>
* This method sets {@link #_uuidsPerTick} to the number of
* UUIDs allowed per clock tick.
*/
private static void loadState()
{
String stateFile;
FileInputStream input;
FileOutputStream output;
Properties state;
String nodeIdString;
long nodeIdLong;
String seqString;
int seqInt;
StringTokenizer tokenizer;
String token;// Find the name of the UUID state file from the configuration,
// or use a default name.
stateFile = null;
if ( stateFile == null )
stateFile = UUID_STATE_FILE;
state = null;
// Try to read the UUID state file into a properties object.
// If successful, the values will be accessible from the
// object state, otherwise, state is set to null.
try {
input = new FileInputStream( stateFile );
state = new Properties();
state.load( input );
input.close();
} catch ( IOException except ) {
state = null;
}// Minus one means the node identifier or clock sequence could not be determined.
nodeIdLong = -1;
seqInt = -1;
// Read the node identifier from the UUID properties. If the node identifier
// cannot be determined (missing, or invalid), generate a new node identifier
// and new random clock sequence.
if ( state != null ) {
nodeIdString = state.getProperty( PROPERTY_NODE_IDENTIFIER );
if ( nodeIdString != null ) {
try {
nodeIdString = nodeIdString.trim();
nodeIdLong = 0;
tokenizer = new StringTokenizer( nodeIdString, ":" );
while ( tokenizer.hasMoreTokens() ) {
token = tokenizer.nextToken();
nodeIdLong = ( nodeIdLong << 8 ) + Long.parseLong( token, 16 );
}
// This is the only case where we can read the clock sequence. If the
// clock sequence cannot be determined (missing, or invalid), the node
// identifier is considered invalid.
seqString = state.getProperty( PROPERTY_CLOCK_SEQUENCE );
if ( seqString != null ) {
try {
seqString = seqString.trim();
seqInt = Integer.parseInt( seqString, 10 );
++seqInt;
} catch ( NumberFormatException except ) {
nodeIdLong = -1;
}
}
} catch ( NumberFormatException except ) {
}
}
}// Convert clock sequence to 4 hexadecimal digits so it can be stored
// in the UUID state file.
if ( seqInt == - 1 )
seqInt = getRandom().nextInt( 1 << 12 );
seqInt = seqInt & 0x1FFF;
_clockSeqOctet = new char[ 4 ];
_clockSeqOctet[ 0 ] = HEX_DIGITS[ (int) ( ( seqInt >> 12 ) & 0x0F ) ];
_clockSeqOctet[ 1 ] = HEX_DIGITS[ (int) ( ( seqInt >> 8 ) & 0x0F ) ];
_clockSeqOctet[ 2 ] = HEX_DIGITS[ (int) ( ( seqInt >> 4 ) & 0x0F ) ];
_clockSeqOctet[ 3 ] = HEX_DIGITS[ (int) ( seqInt & 0x0F ) ];
_clockSeqByte = new byte[ 2 ];
_clockSeqByte[ 0 ] = (byte) ( ( seqInt >> 8 ) & 0xFF );
_clockSeqByte[ 1 ] = (byte) ( seqInt & 0xFF );// If the state file exists, then we read the node identifier from a file,
// and are expected to store the clock sequence in that file. If we fail to
// store the new clock sequence, must assume a random node identifier.
if ( nodeIdLong != -1 && state != null ) {
state.put( PROPERTY_CLOCK_SEQUENCE, String.valueOf( seqInt ) );
try {
output = new FileOutputStream( stateFile );
state.save( output, "uuid.stateFileHeader" ) ;
output.close();
} catch ( IOException except ) {
nodeIdLong = -1;
}
}// If the node identifier could not be determined, or the state file could
// not be updated, obtain the node identifier and clock sequence from
// a random number.
if ( nodeIdLong == -1 ) {
// If node identifier is not IEEE 802 address, it must have the bit 48 set.
nodeIdLong = getRandom().nextLong();
nodeIdLong = nodeIdLong | ( 1 << 47 );
seqInt = getRandom().nextInt( 1 << 12 );
seqInt = seqInt & 0x1FFF;
_clockSeqOctet = new char[ 4 ];
_clockSeqOctet[ 1 ] = HEX_DIGITS[ (int) ( ( seqInt >> 8 ) & 0x0F ) ];
_clockSeqOctet[ 2 ] = HEX_DIGITS[ (int) ( ( seqInt >> 4 ) & 0x0F ) ];
_clockSeqOctet[ 3 ] = HEX_DIGITS[ (int) ( seqInt & 0x0F ) ];
_clockSeqByte = new byte[ 2 ];
_clockSeqByte[ 0 ] = (byte) ( ( seqInt >> 8 ) & 0xFF );
_clockSeqByte[ 1 ] = (byte) ( seqInt & 0xFF );
}// Convert node identifier to 12 hexadecimal digits, and sequence number
// to 4 hexadecimal digits.
_nodeIdentifierOctet = new char[ 12 ];
for ( int i = 0 ; i < 12 ; ++i )
_nodeIdentifierOctet[ i ] = HEX_DIGITS[ (int) ( ( nodeIdLong >> ( ( 11 - i ) * 4 ) ) & 0x0F ) ];
_nodeIdentifierByte = new byte[ 6 ];
for ( int i = 0 ; i < 6 ; ++i )
_nodeIdentifierByte[ i ] = (byte) ( ( nodeIdLong >> ( ( 5 - i ) * 8 ) ) & 0xFF );
nodeIdString = new String();
for ( int i = 0 ; i < 12 ; i += 2 ) {
if ( i > 0 )
nodeIdString = nodeIdString + ":";
nodeIdString = nodeIdString + HEX_DIGITS[ (int) ( ( nodeIdLong >> ( ( 11 - i ) * 4 ) ) & 0x0F ) ] +
HEX_DIGITS[ (int) ( ( nodeIdLong >> ( ( 10 - i ) * 4 ) ) & 0x0F ) ];
}// The number of UUIDs allowed per tick depends on the number of ticks between
// each advance of the clock, adjusted for 100 nanosecond precision.
_uuidsPerTick = Clock.getUnsynchTicks() * 100;// Need to mask UUID variant on clock sequence, but only after clock sequence
// has been stored.
_clockSeqOctet[ 0 ] = HEX_DIGITS[ (int) ( ( seqInt >> 12 ) & 0x0F ) | UUID_VARIANT_OCTET ];
_clockSeqByte[ 0 ] = (byte) ( ( ( seqInt >> 8 ) & 0xFF ) | UUID_VARIANT_BYTE );
}
static {
loadState();
// This makes sure we miss at least one clock tick, just to be safe.
_uuidsThisTick = _uuidsPerTick;
_lastClock = Clock.clock();
}
public static void main( String[] args ) {
long clock;
HashSet hash;
String id;
int count = 1000000;for ( int i = 0 ; i < 10 ; ++i ) {
System.out.println( create() );
}
clock = System.currentTimeMillis();
hash = new HashSet( count / 100, 100 );
for ( int i = 0 ; i < count ; ++i ) {
if ( ( i % 10000 ) == 0 )
System.out.println( "Checked " + i );
id = create();
if ( hash.contains( id ) )
System.out.println( "Duplicate id " + id );
else
hash.add( id );
}
clock = System.currentTimeMillis() - clock;
System.out.println( "Generated " + count + " UUIDs in " + clock + "ms" );
}
/**
* An exception indicating the identifier is invalid and
* cannot be converted into an array of bytes.
*/
public static class InvalidIDException
extends Exception
{
public InvalidIDException( String message )
{
super( message );
}
}/**
* Returns a random number generator. Depending on the configuration this is
* either a secure random number generator, or a standard random number generator
* seeded with the system clock.
*
* @return A random number generator
*/
public static synchronized Random getRandom()
{
if ( _random == null ) {
if ( false ) {
_random = new SecureRandom();
} else {
_random = new Random( System.currentTimeMillis() + Runtime.getRuntime().freeMemory() );
}
}
return _random;
}/**
* The random number generator. This variable is set on-demand.
*/
private static Random _random;}
9.ApplicationStartup
package com.test;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;import com.test.util.Util;
public class ApplicationStartup implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
//orgmodel.initFunc();
Util.setCtx(event.getApplicationContext());
}}
10.启动类
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;@SpringBootApplication
@ServletComponentScan
public class Starter {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Starter.class);
springApplication.addListeners(new ApplicationStartup());
springApplication.run(args);
}
}
11jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" href="/easyui/themes/default/easyui.css"/>
<link rel="stylesheet" href="/easyui/themes/icon.css"/>
<script>
function imgsave()
{
var isok = $('#frm').form('validate');
alert(isok)
if(!isok)
{
$.messager.alert('警告','数据校验失败');
return;
}
$('#frm').form('submit', {
url:'/imgsave.action',
onSubmit: function(){},
success:function(data){
$('#attdg').datagrid('reload');
}
});}
function imgdelete(){
var rows = $("#attdg").datagrid("getSelections"); // 获取所有选中的行
for (var i = 0; rows && i < rows.length; i++) {
var row = rows[i];
var id=row.id;
var index = $("#attdg").datagrid("getRowIndex", row); // 获取该行的索引
}
$('#frm').form('submit', {
url:'/imgdelete.action?id='+id,
onSubmit: function(){},
success:function(data){
$('#attdg').datagrid('reload');
}
});}
function showimg(cellVal,rowObj,rowNo)
{
alert(rowObj.id);
var html = '<img src="/IMGfile?attid='+rowObj.id+'" width="50px" height="50px"/>';
return html;
}
</script>
</head>
<body class="easyui-layout">
<div id="win" class="easyui-window" title="上传下载" style="width:100%;height:80%"
data-options="iconCls:'icon-save',modal:true">
<form id="frm" action="/usersave" method="POST" enctype="multipart/form-data">
<table id="attdg" class="easyui-datagrid"
data-options="url:'/borrowatt.action?instanceid=${bi.id}',fitColumns:true,
singleSelect:true,toolbar: '#tb'">
<thead>
<tr>
<th data-options="field:'ids',checkbox:true"></th>
<th data-options="field:'id'">ID</th>
<th data-options="field:'name'">名称</th>
<th data-options="field:'length'">大小</th>
<th data-options="field:'dt'">上传时间</th>
<th data-options="field:'contextType'">文件类型</th>
<th data-options="field:'img',formatter:showimg" >图片</th> <!-- ,formatter:showimg -->
</tr>
</thead>
</table>
<div id="tb">
<input name="uploadfile" class="easyui-filebox" style="width:300px">
<a id="btn" οnclick="imgsave()" class="easyui-linkbutton" data-options="iconCls:'icon-search'">保存</a>
<a id="btn" οnclick="imgdelete()" class="easyui-linkbutton" data-options="iconCls:'icon-search'">删除</a>
</div>
</form>
</div></body>
</html>
12.导入easyui的css
13.创建数据库
DROP TABLE IF EXISTS `gf_img`;
CREATE TABLE `gf_img` (
`id` varchar(200) DEFAULT NULL,
`name` varchar(200) DEFAULT NULL,
`contexttype` varchar(100) DEFAULT NULL,
`length` mediumtext,
`dt` varchar(200) DEFAULT NULL,
`content` mediumblob
) ENGINE=InnoDB DEFAULT CHARSET=utf8;