002.SpringBoot将图片上传到数据库中

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;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值