基于SpringBoot+Gradle+Zxing+JQuery(原生JS)开发条形码/二维码扫描工具,且采用原生JS调用浏览器摄像头

零、


近日在做课设的时候,碰到一个比较有趣的玩意。就是在应用上添加扫描二维码/条形码的技术。

下面,介绍一下本文采用的一些框架:

  • SpringBoot+Gradle+JPA为框架的后端系统

  • JavaScript(JQuery)编写的前端系统,其中涉及的HTTP协议发包,接收返回的JSON格式字符串皆采用JavaScript。

  • 二维码扫描方面采用了Google提供的zxing。

最终结果如下图所示,即通过扫描条形码,获得条形码号,最终成功借入书籍。

一、准备工作


首先,先需要通过Gradle导入zxing包,对应的代码如下:

compile group: 'org.json', name: 'json', version: '20180813'
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.12.0'
compile 'com.google.zxing:core:3.3.0'
compile 'com.google.zxing:javase:3.3.0'

其中,第三第四行是zxing包

下面,定义前后端对接的接口如下:

{
    "account":String,
    "img":String
}
说明:
·account是借书者的帐号(学号)
·img想借的书的条形码照片
后端返回格式:
{
    "msg":String
}

这里,前端格式是基于Http MultiFilePart的,而后端格式是基于JSON的。前端在发图的时候,应当将图片编码成Base64格式的字符串。在完成了一些基础的定义后,就可以开始正式的编写工作了。

二、后端代码编写


首先先编写SpringBoot中Controller类的代码,主要负责读取数据:

@RequestMapping(value = "service/order.book")
    public String receive_order_request(MultipartHttpServletRequest request) {
        String account=request.getParameter("account");
        String file=request.getParameter("img");
        //System.out.println("Account="+account);
        String s= bookEngine.translateBorrowBook(account,file);
        System.out.println(s);
        return s;
    }

再编写Service类代码,进行图片信息的获取。这里Base64ToImage函数可以将字符串重新编码成图片,并写入相对路径中的目录下。

String bar="";
if(Base64ToImage(file,"tmp.jpg"))
    bar=decodeBar("tmp.jpg");
System.out.println("FIND BAR="+bar);

核心的decodeBar函数如下,告知图片所在位置即可:

public  String decodeBar(String imgPath)throws Exception{
        BufferedImage image = null;
        Result result = null;
        try {
            image = ImageIO.read(new File(imgPath));
            if (image == null) {
                System.out.println("the decode image may be not exit.");
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Hashtable<DecodeHintType, Object> hints = new Hashtable<>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            //hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
            result = new MultiFormatReader().decode(bitmap,hints);
            return result.getText();
        } catch (Exception e) {
            throw  e;
        }
    }

三、前端代码编写


前端代码设计到的问题主要有2点,一是如何调用摄像头进行图像获取,二是如何采用JS进行发包。第一个问题主要可以通过canvas和video标签实现。要注意的为id为video和canvas的两个标签。

<div class="slider_bg" id="mainContainer">
    <div class="container">
        <div id="content">
            <div class="word">
                <h1>TIPS:请将书本条形码对准窗口</h1>
                <div id="form">
                    <form style="margin-left: -200px;margin-top: 20px;" action="" >
                        <table height="253" id="table">
                            <tr>
                               <td ><video id="video" width="200px" height="150px" autoplay="autoplay" muted="muted" style="margin-left: 70px;margin-top: 20px;"></video></td>
                            </tr>
                            <tr>
                                <td ><a id="resulttxt" style="margin-left: 90px;margin-top: 20px;">尚未检测出书本</a></td>
                            </tr>
                        </table>
                    </form>
                </div>
            </div>

        </div>

        <div class="mainBox"style="margin-left: 60px;margin-top: -60px">
            <div class="newBook">
                <div class="bookTip"></div>
                <div class="bookInfo">
                    <table id="borrowedlist" width="200px"  class="bookTip" style="margin-left: 60px;">
                        <tr ><th>您的借书:</th></tr>


                    </table>
                </div>
            </div>

        </div>
        <canvas id="canvas" width="400px" height="300px" style="visibility: hidden"></canvas>
    </div>
</div>

下面,需要获取video上的图片,然后保存到canvas上(已设置隐藏),再通过ajax发包发给服务器端,这里takePhoto函数每4秒钟执行一次。

<script type = "text/javascript">
    window.onload = function()
    {
        getMedia();
        window.setInterval("takePhoto()",4000);
    }
    
    function getMedia() {
        let constraints = {
            video: {width: 200, height: 150},
            audio: true
        };
        //获得video摄像头区域
        let video = document.getElementById("video");
        //这里介绍新的方法,返回一个 Promise对象
        // 这个Promise对象返回成功后的回调函数带一个 MediaStream 对象作为其参数
        // then()是Promise对象里的方法
        // then()方法是异步执行,当then()前的方法执行完后再执行then()内部的程序
        // 避免数据没有获取到
        let promise = navigator.mediaDevices.getUserMedia(constraints);
        promise.then(function (MediaStream) {
            video.srcObject = MediaStream;
            video.play();
        });
    }

    function takePhoto() {
        //获得Canvas对象
        let video = document.getElementById("video");
        let canvas = document.getElementById("canvas");
        var f=video
        //alert(f)
         let ctx = canvas.getContext('2d');
         ctx.drawImage(video, 0, 0, 400, 300);
        //alert("GUGU")
        var imgData = canvas.toDataURL("image/jpg");
        //alert("PAPA")
        var base64Data = imgData.split(",")[1];
        //alert(base64Data)
        //alert("DUDU")
        var fd=new FormData();
        fd.append('img',base64Data)
        fd.append("account",sessionStorage.getItem("userAccount"))
        //alert("RUSH")
        $.ajax({
            type: "POST",
            url: "http://localhost:8080/service/order.book",
            processData:false,  //tell jQuery not to process the data
            contentType: false,  //tell jQuery not to set contentType
            data:fd,
            success: function (res) {
                //var res=tmp.parseJSON();
                //alert("tmp="+tmp.toString()+"JSON="+res.toString())
                if(res.toString()==="SUCCESS") {
                    $("#resulttxt").html("<a>成功借书</a>")
                    window.location.replace(window.location.href.substring(0, window.location.href.lastIndexOf('/')) + "/borrow.html")
                }
               else if(res.toString()==="ERROR_FULL"){
                    $("#resulttxt").html("<a >借书失败,借书已满</a>");
                }
                else if(res.toString()==="ERROR_NOBOOK") {
                    $("#resulttxt").html("<a >借书失败,此书已被借走</a>");
                }
                else if(res.toString()==="BORROWED"){
                    $("#resulttxt").html("<a >您已借入此书</a>")
                }else{
                    $("#resulttxt").html("<a >图像不清</a>")
                }

            },
            error: function (XMLHttpRequest, textStatus) {
                var txt4="<a >"+"请将书本条形码对准窗口:"+"</a>";
                $("#resulttxt").html(txt4);
               alert(textStatus + ":" + XMLHttpRequest.status + " " + XMLHttpRequest.readyState);
            }
        })
    }
</script>

完整的Github开源代码如下,代码中涉及到了基于规则的系统。

https://github.com/zhaominyiz/RuleBasedLibrarySystem

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值