zoukankan      html  css  js  c++  java
  • ZXing生成二维码

    使用Google开源项目二维码读取和生成工具ZXing实现。

    1、配置pom.xml文件:

    <!-- QRCode 生成动态二维码 -->
            <dependency>  
                <groupId>com.google.zxing</groupId>
                <artifactId>core</artifactId>  
                <version>2.2</version>  
            </dependency>  
            <dependency>  
                <groupId>com.google.zxing</groupId>  
                <artifactId>javase</artifactId>  
                <version>2.2</version>  
            </dependency> 
    View Code

    2、在web.xml中配置请求的servlet:

    <!-- QRCode -->
        <servlet>
              <servlet-name>qrCode</servlet-name>
              <servlet-class>com.fan.servlet.BarCode2DServlet</servlet-class>
          </servlet>
          <servlet-mapping>
              <servlet-name>qrCode</servlet-name>
              <url-pattern>/qrCode</url-pattern>
          </servlet-mapping>
    View Code

    3、servlet代码:

    @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            OutputStream stream = null;
            try {
                stream = resp.getOutputStream();
                String  filePath = getServletConfig().getServletContext().getRealPath("/");
                QRCodeUtil.encode("根据什么生成二维码", "嵌入图片的地址", stream, true, filePath); 
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (stream != null) {
                    stream.flush(); 
                    stream.close(); 
                } 
            } 
        } 
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            this.doGet(req, resp);
        }
    View Code

    4、生成二维码的工具类QRCodeUtil.java:

    /**
     * 二维码工具类
     * 
     */
    public class QRCodeUtil {
    
        private static final String CHARSET = "utf-8";
        private static final String FORMAT_NAME = "JPG";
        // 二维码尺寸
        private static final int QRCODE_SIZE = 200;
        // LOGO宽度
        private static final int WIDTH = 40;
        // LOGO高度
        private static final int HEIGHT = 40;
    
        private static BufferedImage createImage(String content, String imgPath,
                boolean needCompress) throws Exception {
            Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                    BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
            // 去掉白边
            int[] rec = bitMatrix.getEnclosingRectangle();  
            if(rec != null){
                int resWidth = rec[2] + 1;  
                int resHeight = rec[3] + 1;  
                BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);  
                resMatrix.clear();  
                for (int i = 0; i < resWidth; i++) {  
                    for (int j = 0; j < resHeight; j++) {  
                        if (bitMatrix.get(i + rec[0], j + rec[1])) { 
                             resMatrix.set(i, j); 
                        } 
                    }  
                }  
            }
    
            int width = bitMatrix.getWidth();
            int height = bitMatrix.getHeight();
            BufferedImage image = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
                }
            }
            if (imgPath == null || "".equals(imgPath)) {
                Log.info("no logo success:");
                return image;
            }
            
            // 配置了logo路径时插入图片
            QRCodeUtil.insertImage(image, imgPath, needCompress);
            Log.info("have logo success");
            return image;
        }
    
        /**
         * 插入LOGO
         */
        private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
            //new一个URL对象  
            URL url = new URL(imgPath);  
            //打开链接  
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();  
            //设置请求方式为"GET"  
            conn.setRequestMethod("GET");  
            //超时响应时间为5秒  
            conn.setConnectTimeout(5 * 1000);  
            //通过输入流获取图片数据  
            InputStream inStream = conn.getInputStream();  
            //得到图片的二进制数据,以二进制封装得到数据,具有通用性  
            byte[] data = readInputStream(inStream);  
            //创建文件用于暂存公司LOGO
            File tmpFile = createTmpFile();
            //new一个文件对象用来保存图片,默认保存当前工程根目录  
            //创建输出流  
            FileOutputStream outStream = new FileOutputStream(tmpFile);  
            //写入数据  
            outStream.write(data);
            //关闭输出流  
            outStream.close();  
            Image src = ImageIO.read(tmpFile);
            if(src != null){
                int width = src.getWidth(null);
                int height = src.getHeight(null);
                if (needCompress) { // 压缩LOGO
                    if (width > WIDTH) {
                        width = WIDTH;
                    }
                    if (height > HEIGHT) {
                        height = HEIGHT;
                    }
                    Image image = src.getScaledInstance(width, height,
                            Image.SCALE_SMOOTH);
                    BufferedImage tag = new BufferedImage(width, height,
                            BufferedImage.TYPE_INT_RGB);
                    Graphics g = tag.getGraphics();
                    g.drawImage(image, 0, 0, null); // 绘制缩小后的图
                    g.dispose();
                    src = image;
                }
                // 插入LOGO
                Graphics2D graph = source.createGraphics();
                int x = (QRCODE_SIZE - width) / 2;
                int y = (QRCODE_SIZE - height) / 2;
                graph.drawImage(src, x, y, width, height, null);
                Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
                graph.setStroke(new BasicStroke(3f));
                graph.draw(shape);
                graph.dispose();
            }
        }
        
        private static File createTmpFile(){
            String path = "/tmpLogo";
            File f = new File(path);
            if(!f.exists()){
                f.mkdirs();
            } 
            // fileName表示你创建的文件名;为txt类型;
            String fileName="zxing_tmp.png";
            File tmpFile = new File(f,fileName);
            if(!tmpFile.exists()){
                try {
                    tmpFile.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return tmpFile;
        }
        
        
        /**
         * 把文件读出来
         */
       public static byte[] readInputStream(InputStream inStream) throws Exception{  
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
            //创建一个Buffer字符串  
            byte[] buffer = new byte[1024];  
            //每次读取的字符串长度,如果为-1,代表全部读取完毕  
            int len = 0;  
            //使用一个输入流从buffer里把数据读取出来  
            while( (len=inStream.read(buffer)) != -1 ){  
                //用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度  
                outStream.write(buffer, 0, len);  
            }  
            //关闭输入流  
            inStream.close();  
            //把outStream里的数据写入内存  
            return outStream.toByteArray();  
        }
    
        /**
         * 生成二维码(内嵌LOGO)
         */
        public static void encode(String content, String imgPath, HttpServletResponse resp, boolean needCompress) throws Exception {
            BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
            ImageIO.write(image, FORMAT_NAME, resp.getOutputStream());
        }
    
        /**
         * 生成二维码(内嵌LOGO)
         */
        public static void encode(String content, String imgPath, HttpServletResponse resp)
                throws Exception {
            QRCodeUtil.encode(content, imgPath, resp, false);
        }
    
        /**
         * 生成二维码
         */
        public static void encode(String content, HttpServletResponse resp,
                boolean needCompress) throws Exception {
            QRCodeUtil.encode(content, null, resp, needCompress);
        }
    
        /**
         * 生成二维码
         */
        public static void encode(String content, HttpServletResponse resp) throws Exception {
            QRCodeUtil.encode(content, null, resp, false);
        }
    
        /**
         * 生成二维码(内嵌LOGO)
         */
        public static void encode(String content, String imgPath,
                OutputStream output, boolean needCompress, String realPath) throws Exception {
            BufferedImage image = QRCodeUtil.createImage(content, imgPath,
                    needCompress);
            
            File file =new File(realPath + "res/qrcodeTmp");
            if (!file.exists() && !file.isDirectory()) {
                file.mkdirs();
            }
            ImageIO.setCacheDirectory(file);
            
            ImageIO.write(image, FORMAT_NAME, output);
        }
        
        /**
         * 生成二维码
         */
        public static void encode(String content, OutputStream output)
                throws Exception {
            QRCodeUtil.encode(content, null, output, false, "/");
        }
    
        /**
         * 解析二维码
         */
        public static String decode(File file) throws Exception {
            BufferedImage image;
            image = ImageIO.read(file);
            if (image == null) {
                return null;
            }
            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(
                    image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result result;
            Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
            result = new MultiFormatReader().decode(bitmap, hints);
            String resultStr = result.getText();
            return resultStr;
        }
    
        /**
         * 解析二维码
         */
        public static String decode(String path) throws Exception {
            return QRCodeUtil.decode(new File(path));
        }
    }
    View Code

    5、页面上如何请求:

    <img src="${base}/qrCode">

    这样就可以把生成的二维码到指定<img>标签的位置。

    注意:ImageIO.write(image, FORMAT_NAME, resp.getOutputStream()); 的write方法会默认找temp目录,如果服务器上没有temp目录则图片展示不出来,且报错Can't create cache file!具体报错信息如下:

    javax.imageio.IIOException: Can't create output stream!
            at javax.imageio.ImageIO.write(ImageIO.java:1560)
            at com.fan.util.QRCodeUtil.encode(QRCodeUtil.java:237)
            at com.fan.BarCode2DServlet.doGet(BarCode2DServlet.java:44)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at com.lenovo.moc.portal.controller.SecurityFilter.doFilter(SecurityFilter.java:43)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
            at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
            at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2466)
            at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2455)
            at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
            at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
            at java.lang.Thread.run(Thread.java:662)
    Caused by: javax.imageio.IIOException: Can't create cache file!
            at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:397)
            at javax.imageio.ImageIO.write(ImageIO.java:1558)
            ... 28 more
    Caused by: java.io.IOException: No such file or directory
            at java.io.UnixFileSystem.createFileExclusively(Native Method)
            at java.io.File.checkAndCreate(File.java:1705)
            at java.io.File.createTempFile0(File.java:1726)
            at java.io.File.access$100(File.java:120)
            at java.io.File$1.createTempFile(File.java:1955)
            at sun.misc.IOUtils.createTempFile(IOUtils.java:88)
            at javax.imageio.stream.FileCacheImageOutputStream.<init>(FileCacheImageOutputStream.java:71)
            at com.sun.imageio.spi.OutputStreamImageOutputStreamSpi.createOutputStreamInstance(OutputStreamImageOutputStreamSpi.java:50)
            at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:393)
    View Code

    为什么呢?源码如下:在默认的temp下生成一个imgio**************.tmp的临时文件然后删除。

     

     

    怎样让他缓存在自己想要的目录下呢?使用ImageIO中的cacheDirectory属性来设置即可。

  • 相关阅读:
    什么是socket ??
    WebView的使用
    UIWebView 使用
    UIWebView与JavaScript的交互
    iOS中UIWebView使用JS交互
    iOS app支付宝接口调用的一点总结(补充支付宝SDK&Demo下载地址)
    51单片机 按键,键盘检测
    51单片机 数码管的显示与译码器
    C51数据类型扩充定义
    STC12C5A60S2 内部AD+1602显示
  • 原文地址:https://www.cnblogs.com/siv8/p/6094867.html
Copyright © 2011-2022 走看看