ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java web报表,jasperReport使用简介

2020-12-14 16:02:06  阅读:295  来源: 互联网

标签:web exporter java String request jasperReport jasperPrint setParameter response


转载请注明出处!!!

jasperReport使用简介

需求简介:java web需生成报表,然后打印出来。报表用的jasperReport,编辑报表的可视化工具用的iReport。其次,web的打印是个比较棘手的问题,网上有很多第三方控件,经过不懈努力,找到了不少控件,但是支持直接打印(不跳预览)的免费版好像没有,无奈,用java手写了一个打印控件。

  1. 控件实现的功能:自动使用客户端电脑的默认打印机打印出指定的文件。【直接打印(不展示预览)】。
  2. 可指定双面打印。
  3. 可执行文件。打开一次后自动设置成开机自启文件。

1.下载报表模板编辑器iReport

iReport下载地址。本人用的最新版本,就这也是2014年的了。

若你电脑的java环境是jdk8,则下载后应该会出现无法打开的情况。解决办法:

2.做模板

红框内的组件是常用的,也是此教程中涉及到的组件。

若 组件面板 没有的话可以在 窗口-->组件面板 中打开。

设置静态文本(static text)即模板中不用在程序中赋值的文本。如:标题、表格头等等。

设置程序中赋值的文本(text field)

需要遍历的数据,模板制作方式:

图片组件的添加

如果需要转为pdf,并且模板中涉及到中文,则需要设置下编码。

点击上方的preview按钮,即可将jrxml文件编译成jasper文件,如图。若无法出现下图所示,说明模板编译时出错,请认真检查!

若出现 null ,解决办法:

此时,与jrxml文件同级目录下回出现jasper文件。jrxml文件编译之后会产生jasper文件,类似于java文件编译后产生class文件。

3.java中操作jasperReport

java操作jasperReport所需jar包

其中pdf.freejar包为手动添加到本地maven的结果。教程点此

<!--java操作pdf start-->
        <dependency>
            <groupId>spire</groupId>
            <artifactId>pdf.free</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!--java操作pdf end-->
        <!-- jasperReports Start -->
        <!-- 该包的作用完成ireport中Preview按扭功能。通过该包可以通过java来ireport生成摸班(.jrxml或.jasper)填充数据源并导出pdf,excel,html等格式文件 -->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.0.0</version>
        </dependency>
        <dependency>
            <!-- 生成pdf所依赖的包 -->
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-pdfa</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!--将.jrxml编译成.jasper.如果你不使用java编译,而使用ireport工具编译则无须导入该 包 -->
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.13</version>
        </dependency>
        <!-- jasperreports End -->

java操作jasperReport工具类

package com.jdkj.detectSystem.Util;

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.base.JRBaseReport;
import net.sf.jasperreports.engine.export.*;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.j2ee.servlets.ImageServlet;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.sql.Connection;
import java.util.Map;

/**
 * @Description: java操作jasperReport工具类
 * @Param:
 * @return:
 */
@SuppressWarnings("deprecation")
public class JasperHelper {
    public static final String PRINT_TYPE = "print";
    public static final String PDF_TYPE = "pdf";
    public static final String EXCEL_TYPE = "excel";
    public static final String HTML_TYPE = "html";
    public static final String WORD_TYPE = "word";

    public static void prepareReport(JasperReport jasperReport, String type) {
        /*
         * 如果导出的是excel,则需要去掉周围的margin
         */
        if ("excel".equals(type)) {
            try {
                Field margin = JRBaseReport.class.getDeclaredField("leftMargin");
                margin.setAccessible(true);
                margin.setInt(jasperReport, 0);
                margin = JRBaseReport.class.getDeclaredField("topMargin");
                margin.setAccessible(true);
                margin.setInt(jasperReport, 0);
                margin = JRBaseReport.class.getDeclaredField("bottomMargin");
                margin.setAccessible(true);
                margin.setInt(jasperReport, 0);
                Field pageHeight = JRBaseReport.class.getDeclaredField("pageHeight");
                pageHeight.setAccessible(true);
                pageHeight.setInt(jasperReport, 2147483647);
            } catch (Exception exception) {
            }
        }
    }

    /**
     * 导出excel
     */
    public static void exportExcel(JasperPrint jasperPrint, String defaultFilename, HttpServletRequest request,
                                   HttpServletResponse response) throws IOException, JRException {
        /*
         * 设置头信息
         */
        response.setContentType("application/vnd.ms-excel");
        String defaultname = null;
        if (defaultFilename.trim() != null && defaultFilename != null) {
            defaultname = defaultFilename + ".xls";
        } else {
            defaultname = "export.xls";
        }

        response.setHeader("Content-Disposition",
                "attachment; filename=\"" + URLEncoder.encode(defaultname, "UTF-8") + "\"");

        ServletOutputStream ouputStream = response.getOutputStream();
        JRXlsExporter exporter = new JRXlsExporter();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);

        exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE); // 删除记录最下面的空行

        exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);// 删除多余的ColumnHeader
        //
        exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);// 显示边框
        exporter.exportReport();
        ouputStream.flush();
        ouputStream.close();
    }

    public static enum DocType {
        PDF, HTML, XLS, XML, RTF
    }

    @SuppressWarnings("rawtypes")
    public static JRAbstractExporter getJRExporter(DocType docType) {
        JRAbstractExporter exporter = null;
        switch (docType) {
            case PDF:
                exporter = new JRPdfExporter();
                break;
            case HTML:
                exporter = new JRHtmlExporter();
                break;
            case XLS:
                exporter = new JExcelApiExporter();
                break;
            case XML:
                exporter = new JRXmlExporter();
                break;
            case RTF:
                exporter = new JRRtfExporter();
                break;
        }
        return exporter;
    }

    /**
     * 导出pdf,注意此处中文问题,
     * 这里应该详细说:主要在ireport里变下就行了
     * 1)在ireport的classpath中加入iTextAsian.jar 2)在ireport画jrxml时,看ireport最左边有个属性栏。
     * 下边的设置就在点字段的属性后出现。 pdf font name :STSong-Light ,pdf encoding :UniGB-UCS2-H
     */
    private static void exportPdf(JasperPrint jasperPrint, String defaultFilename, HttpServletRequest request,
                                  HttpServletResponse response) throws IOException, JRException {
        response.setContentType("application/pdf");
        String defaultname = null;
        if (defaultFilename.trim() != null && defaultFilename != null) {
            defaultname = defaultFilename + ".pdf";
        } else {
            defaultname = "export.pdf";
        }
        String fileName = new String(defaultname.getBytes("GBK"), "ISO8859_1");
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
        ServletOutputStream ouputStream = response.getOutputStream();
        JasperExportManager.exportReportToPdfStream(jasperPrint, ouputStream);
        ouputStream.flush();
        ouputStream.close();
    }

    /**
     * @Description:
     * @Param: [defaultFilename 存储文件路径及名称, is 模板源文件,parameters map参数,conn 列表参数]
     * @Return: void
     * @Author: WQ
     * @Date: 2020/8/24
     */
    public static void exportPdfFile(String defaultFilename, File is, Map<String, Object> parameters, JRDataSource conn) {
        try {
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
            prepareReport(jasperReport, "pdf");
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);
            JasperExportManager.exportReportToPdfFile(jasperPrint, defaultFilename);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 将jrxml文件编译成jasper文件
     * @Param: [jrxmlPath, jasperPath]
     * @Return: java.lang.String 返回jasper文件路径
     * @Author: WQ
     * @Date: 2020/8/24
     */
    public static String jrxmlToJasper(String jrxmlPath, String jasperPath) throws JRException, IOException {
        JasperCompileManager.compileReportToFile(jrxmlPath, jasperPath);
        return jasperPath;
    }

    /**
     * 导出html
     */
    private static void exportHtml(JasperPrint jasperPrint, String defaultFilename, HttpServletRequest request,
                                   HttpServletResponse response) throws IOException, JRException {
        response.setContentType("text/html");
        ServletOutputStream ouputStream = response.getOutputStream();
        JRHtmlExporter exporter = new JRHtmlExporter();
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
        // 设置图片文件存放路径,此路径为服务器上的绝对路径
        String imageDIR = request.getSession().getServletContext().getRealPath("/");
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_DIR_NAME, imageDIR);

        // 设置图片请求URI
        String imageURI = request.getContextPath() + "/";
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, imageURI);

        // 设置导出图片到图片存放路径
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.TRUE);
        exporter.setParameter(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR, Boolean.TRUE);

        exporter.exportReport();

        ouputStream.flush();
        ouputStream.close();
    }

    /**
     * 导出word
     */
    @SuppressWarnings("rawtypes")
    private static void exportWord(JasperPrint jasperPrint, String defaultFilename, HttpServletRequest request,
                                   HttpServletResponse response) throws JRException, IOException {
        response.setContentType("application/msword;charset=utf-8");
        String defaultname = null;
        if (defaultFilename.trim() != null && defaultFilename != null) {
            defaultname = defaultFilename + ".doc";
        } else {
            defaultname = "export.doc";
        }
        String fileName = new String(defaultname.getBytes("GBK"), "utf-8");
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
        JRExporter exporter = new JRRtfExporter();
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, response.getOutputStream());

        exporter.exportReport();
    }

    /**
     * 按照类型导出不同格式文件
     *
     * @param type            文件类型
     * @param is              jasper文件的来源
     * @param request
     * @param response
     * @param defaultFilename 默认的导出文件的名称
     */
    public static void export(String type, String defaultFilename, File is, HttpServletRequest request,
                              HttpServletResponse response, Map parameters, Connection conn) {
        try {
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
            prepareReport(jasperReport, type);

            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);

            if (EXCEL_TYPE.equals(type)) {
                exportExcel(jasperPrint, defaultFilename, request, response);
            } else if (PDF_TYPE.equals(type)) {
                exportPdf(jasperPrint, defaultFilename, request, response);
            } else if (HTML_TYPE.equals(type)) {
                exportHtml(jasperPrint, defaultFilename, request, response);
            } else if (WORD_TYPE.equals(type)) {
                exportWord(jasperPrint, defaultFilename, request, response);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void export(String type, String defaultFilename, File is, HttpServletRequest request,
                              HttpServletResponse response, Map parameters, JRDataSource conn) {
        try {
            JasperReport jasperReport = (JasperReport) JRLoader.loadObject(is);
            prepareReport(jasperReport, type);

            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, conn);

            if (EXCEL_TYPE.equals(type)) {
                exportExcel(jasperPrint, defaultFilename, request, response);
            } else if (PDF_TYPE.equals(type)) {
                exportPdf(jasperPrint, defaultFilename, request, response);
            } else if (HTML_TYPE.equals(type)) {
                exportHtml(jasperPrint, defaultFilename, request, response);
            } else if (WORD_TYPE.equals(type)) {
                exportWord(jasperPrint, defaultFilename, request, response);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 输出html静态页面,必须注入request和response
     *
     * @throws JRException
     * @throws IOException
     */
    public static void showHtml(String defaultFilename, String reportfile, HttpServletRequest request,
                                HttpServletResponse response, Map parameters, JRDataSource conn) throws JRException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        JRAbstractExporter exporter = getJRExporter(DocType.HTML);

        JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile, parameters, conn);
        request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

        PrintWriter out = response.getWriter();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);

        // 设置图片文件存放路径,此路径为服务器上的绝对路径
        String imageDIR = request.getSession().getServletContext().getRealPath("/");
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_DIR_NAME, imageDIR);

        // 设置图片请求URI
        String imageURI = request.getContextPath() + "/";
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, imageURI);

        // 设置导出图片到图片存放路径
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.TRUE);
        exporter.setParameter(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR, Boolean.TRUE);
        exporter.exportReport();

        out.flush();

    }

    public static void showHtml(String defaultFilename, String reportfile, HttpServletRequest request,
                                HttpServletResponse response, Map parameters, Connection conn) throws JRException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");

        JRAbstractExporter exporter = getJRExporter(DocType.HTML);

        JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile, parameters, conn);
        request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

        PrintWriter out = response.getWriter();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
        // 设置图片文件存放路径,此路径为服务器上的绝对路径
        String imageDIR = request.getSession().getServletContext().getRealPath("/");
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_DIR_NAME, imageDIR);

        // 设置图片请求URI
        String imageURI = request.getContextPath() + "/";
        exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, imageURI);

        // 设置导出图片到图片存放路径
        exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.TRUE);
        exporter.setParameter(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR, Boolean.TRUE);
        exporter.exportReport();
        out.flush();

    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void showPdf(String defaultFilename, String reportfile, HttpServletRequest request,
                               HttpServletResponse response, Map parameters, JRDataSource conn) throws JRException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        response.setContentType("application/pdf");

        JRAbstractExporter exporter = getJRExporter(DocType.PDF);

        JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile, parameters, conn);
        request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

        OutputStream out = response.getOutputStream();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
        exporter.exportReport();
        out.flush();

    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public static void showPdf(String defaultFilename, String reportfile, HttpServletRequest request,
                               HttpServletResponse response, Map parameters, Connection conn) throws JRException, IOException {

        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html");
        response.setContentType("application/pdf");

        JRAbstractExporter exporter = getJRExporter(DocType.PDF);

        JasperPrint jasperPrint = JasperFillManager.fillReport(reportfile, parameters, conn);
        request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

        OutputStream out = response.getOutputStream();

        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
        exporter.exportReport();
        out.flush();

    }

}

实际操作

项目结构:

核心操作类:

package com.wq.jasperReportDemo.service.impl;

import com.wq.jasperReportDemo.entity.UserDO;
import com.wq.jasperReportDemo.service.UserDOSercice;
import com.wq.jasperReportDemo.util.JasperHelper;
import lombok.SneakyThrows;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: jasperReportDemo
 * @description: 用户操作业务层
 * @author: WQ
 **/
@Service
public class UserDOServiceImpl implements UserDOSercice {


    /**
     * @Description: 获取模板生成的pdf文件的路径
     * @Param: [jrxmlPath]
     * @return: java.lang.String
     * @Author: WQ
     * @Date: 2020/12/14
     */
    @SneakyThrows
    @Override
    public String getPdfPath(String jrxmlPath) {
        String imgPath = "C:\\Users\\19855\\Desktop\\jasperDemo\\img.jpg";
        String basePath = jrxmlPath.substring(0, jrxmlPath.length() - 7);
        //定义生成的pdf文件路径
        String pdfPath = basePath + ".pdf";
        //生成jasper文件路径
        String jasperPath = basePath + ".jasper";
        // jrxml文件编译成jasper文件
        JasperHelper.jrxmlToJasper(jrxmlPath, jasperPath);
        // 遍历数据渲染
        List<UserDO> list = new ArrayList<>();
        list.add(new UserDO("张三", "123"));
        list.add(new UserDO("李四", "456"));
        list.add(new UserDO("王五", "789"));
        //获取数据源
        JRDataSource jrDataSource = new JRBeanCollectionDataSource(list);
        // map数据渲染
        Map<String, Object> map = new HashMap<>();
        map.put("test", "测试字段");
        map.put("imgPath", imgPath);//图片也是传入图片的路径。传图片的base64字符串无法正常显示(本人测试过)
        //创建jasper文件
        File reportFile = new File(jasperPath);
        //调用工具类,导出pdf文件
        JasperHelper.exportPdfFile(pdfPath, reportFile, map, jrDataSource);
        return pdfPath;
    }
}

测试方法

@SpringBootTest
class JasperReportDemoApplicationTests {

    @Autowired
    private UserDOSercice userDOSercice;

    @Test
    void contextLoads() {
        String pdfPath = userDOSercice.getPdfPath("C:\\Users\\19855\\Desktop\\jasperDemo\\report1.jrxml");
        System.out.println(pdfPath);
    }

}

表格的边框啥的,都是可以加的,右击单个组件,选择padding and borders即可设置。

4.将pdf转为base64字符串并在前端打印出来

转base64工具类

package com.wq.jasperReportDemo.util;

import org.apache.tomcat.util.codec.binary.Base64;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @program: jasperReportDemo
 * @description:
 * @author: WQ
 * @create: 2020-12-14 15:34
 **/
public class FileUtil {

    /**
     * 文件转为base64字符串。filePath:文件路径
     */
    public static String fileToBase64(String filePath) throws IOException {
        File file = new File(filePath);
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        byte[] bs = Base64.encodeBase64(buffer);
        return new String(bs);
    }

}

5.前端接收,并调用打印控件打印出结果

控件有偿,需要私聊。

            $.ajax({
                url: "http://localhost:5777/print",
                type: "post",
                data: data,
                //打开下方注释即双面打印
                //headers: {
                //    'Page-Type': 'DUPLEX'
                //},
                success: function (data) {
                    layer.close(layer.index);
                    if ("Success" == data) {
                        layer.msg("报表已打印", {offset: "100px"});
                        return true;
                    } else {
                        layer.msg("报表打印失败", {anim: 6, offset: "100px"});
                    }
                    return false;
                },
                error: function () {
                    layer.close(layer.index);
                    layer.msg("打印失败。连接打印机失败或控件未下载", {anim: 6, offset: "100px"});
                    return false;
                }
            })

标签:web,exporter,java,String,request,jasperReport,jasperPrint,setParameter,response
来源: https://blog.csdn.net/weiqiang915/article/details/111165998

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有