专栏首页跟牛老师一起学WEBGISOpenlayers4+servlet实现切片的本地缓存

Openlayers4+servlet实现切片的本地缓存

概述

本文实现的是结合Openlayers4和java servlet实现公网资源切片的本地缓存。

优点

相比较其他下载利器,本实例具有以下优点: 1. 实现简单,操作简单; 2. 不会出现IP被封; 3. 结合web,看到哪下到哪,主动保存未缓存的切片; 4. 可通过修改URL和代码缓存多种地图切片。

缺点

鉴于web的实现,该切片缓存的方式具有以下缺点: 1. 被动式缓存,需要用户浏览需要下载的区域; 2. 无法批量缓存。 3. 主要是针对开发人员的,非开发人员使用有困难;

实现效果

实现思路

实现代码

页面代码

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>切片下载</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v4.1.1/css/ol.css" type="text/css">
    <style type="text/css">
        body, #map {
            border: 0px;
            margin: 0px;
            padding: 0px;
            width: 100%;
            height: 100%;
            font-size: 13px;
            overflow: hidden;
        }
    </style>
    <script src="https://openlayers.org/en/v4.1.1/build/ol.js"></script>
    <script type="text/javascript" src="plugin/jquery/jquery-3.1.1.min.js"></script>
    <script type="text/javascript">
        var map;
        function init(){
            var cva_w = getGeoheyLayer("blue");
            var province = new ol.layer.Image({
                source: new ol.source.ImageWMS({
                    ratio: 1,
                    url: 'http://localhost:6080/geoserver/bj_grid/wms',
                    params: {
                        'FORMAT': 'image/png',
                        'VERSION': '1.1.1',
                        STYLES: '',
                        LAYERS: 'bj_grid:bou2_4p',
                    }
                })
            });
            map = new ol.Map({
                controls: ol.control.defaults({
                    attribution: false
                }),
                target: 'map',
                layers: [cva_w, province],
                view: new ol.View({
                    center: ol.proj.transform([104.214, 35.847], 'EPSG:4326', 'EPSG:3857'),
                    zoom: 4
                })
            });
        }
        function getGeoheyLayer(style){
            var url = "http://localhost:8081/lzugis-web/tile?layer="+style+"&z={z}&x={x}&y={y}";
            var layer = new ol.layer.Tile({
                source: new ol.source.XYZ({
                    url:url
                })
            });
            return layer;
        }
    </script>
</head>
<body onLoad="init()">
<div id="map">
</div>
</body>
</html>

servlet代码

package com.lzugis.web.servlet;

import com.lzugis.web.helper.CommonConfig;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by admin on 2017/9/10.
 */
@WebServlet(description = "wms services", urlPatterns =  {"/tile"})
public class TileServiceServlet extends HttpServlet {

    private String url = "https://s4.geohey.com/s/mapping/";
    private String tilepath = "d:/tile/geohey/";

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String x = request.getParameter("x"),
                y = request.getParameter("y"),
                z = request.getParameter("z"),
                layer = request.getParameter("layer");

        StringBuffer tileUrl = new StringBuffer();
        tileUrl.append(url);
        tileUrl.append(layer+"/all?");
        tileUrl.append("z="+z+"&x="+x+"&y="+y);
        tileUrl.append("&retina=&ak=MGUxMmI2ZTk4YTVhNDEzYmJhZDJkNDM3ZWI5ZDAwOGE");

        String tilefile = tilepath+layer+"/"+z+"/"+x+"_"+y+".png";
        File tile = new File(tilefile);
        byte[] tileByte = null;
        /**
         * 如果文件存在,则直接读取文件
         * 如果文件不存在,在先保存
         */
        if(tile.exists()){
            tileByte = getFileBytes(tilefile);
        }
        else{
            tileByte = getUrlBytes(tileUrl.toString());
            saveTileFile(tileByte, tilefile);
        }
        OutputStream os = response.getOutputStream();
        InputStream is = new ByteArrayInputStream(tileByte);
        try {
            int count = 0;
            byte[] buffer = new byte[1024 * 1024];
            while ((count = is.read(buffer)) != -1) {
                os.write(buffer, 0, count);
            }
            os.flush();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            os.close();
            is.close();
        }
    }

    private void saveTileFile(byte[] tileByte, String tilefile){
        try {
            BufferedImage bi = null;
            bi = ImageIO.read(new ByteArrayInputStream(tileByte));
            //判断文件夹是否存在,否则创建
            File filetile = new File(tilefile);
            if (!filetile.getParentFile().exists()) {
                filetile.getParentFile().mkdirs();
            }
            ImageIO.write(bi, "png", filetile);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private byte[] getFileBytes(String tilefile){
        byte[] buffer = null;
        try {
            File file = new File(tilefile);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    private byte[] getUrlBytes(String tilurl){
        try {
            //new一个URL对象
            URL url = new URL(tilurl);
            //打开链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            InputStream inStream = conn.getInputStream();
            //得到图片的二进制数据,以二进制封装得到数据,具有通用性
            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();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Openlayers3中统计图的实现

    在前文中讲到了在Arcgis for js中统计图的实现,在本文,讲述在Openlayers3中结合highcharts实现统计图。

    lzugis
  • OpenLayers3基础教程——OL3基本概念

    从本节开始,我会陆陆续续的更新有关OL3的相关文章——OpenLayers3基础教程,欢迎大家关注我的博客,同时也希望我的博客能够给大家带来一点帮助。

    lzugis
  • OL3+中链家地图找房功能实现

    看看链家的地图找房功能,其实比较简单,主要包涵: 1)基于行政区划的统计展示; 2)分级别展示,逐级钻取。

    lzugis
  • 和弦推导逻辑简析与实现,以及Raphael库试用

    ? 诚然,吉他有上千个和弦。世界上最厉害的吉他大师,也无法一眼辨识出所有的和弦。 更多时候,我们熟记几个基本的和弦,然后通过一定的计算法则,去推导其他的和弦。...

    IMWeb前端团队
  • 模式识别新研究:微软OCR两层优化提升自然场景下的文字识别精度

    用户1737318
  • 和弦推导逻辑简析与实现,以及Raphael库试用

    诚然,吉他有上千个和弦。世界上最厉害的吉他大师,也无法一眼辨识出所有的和弦。 更多时候,我们熟记几个基本的和弦,然后通过一定的计算法则,去推导其他的和弦。因而推...

    IMWeb前端团队
  • Tomcat用户权限设置

    1、vi /etc/tomcat6/tomcat-user.xml //系统安装目录 2、删除注释符 <!-- --> 3、增加账号 Tomcat ...

    Java帮帮
  • 教你在Java接口中定义方法

    基本上所有的Java教程都会告诉我们Java接口的方法都是public、abstract类型的,没有方法体的。

    哲洛不闹
  • JAVA非对称加密算法-RSA算法

    Erwin
  • 教你在Java接口中定义方法

    接下来,SimpleTimeClient类实现了TimeClient接口,具体代码如下:

    哲洛不闹

扫码关注云+社区

领取腾讯云代金券