java Map实现的cache manager

本文介绍了一个基于Java的虚拟缓存工具,它模仿了memcached的功能,能够存储和缓存Java对象。该工具使用ConcurrentHashMap来实现线程安全的数据存储,并通过序列化实现了对象的深度克隆,以确保数据的一致性和完整性。
一个模仿memcached的JAVA虚拟缓存工具,可以缓存java对象;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * java Map cache manager 改进版
 * 特点:无线程,取出时判断过期,系列化实现的深度克隆,覆盖原则
 * 问题: 线程安全,克隆带来的时效损耗
 * @author frank
 *
 */
public class VirtualCache{
    
    /**
     * 开发模式
     */
    private boolean isdev = false;
    
    private static String ERROR_SET = "VirtualCache缓存数据异常:key=";
    
    private static String ERROR_GET= "VirtualCache取出数据异常:key=";
    
    /**
     * 虚拟缓存
     */
    private Map<String,Object> cache = new ConcurrentHashMap<String, Object>();
    
    /**
     * 过期时间
     */
    private Map<String,Long> tasks = new ConcurrentHashMap<String,Long>();
    
    public VirtualCache(boolean isdev){
        this.isdev = isdev;
    }
    
    public VirtualCache(){
        
    }
    
    /**
     * 深度克隆
     */
    private Object clone(String key,Object obj,boolean isSet){
    	if(obj == null)
    		return null;
        ByteArrayOutputStream bo = null;
        ObjectOutputStream oo = null;
        ByteArrayInputStream bi = null;
        ObjectInputStream oi = null;
        Object value = null;
        try {
            bo=new ByteArrayOutputStream();
            oo = new ObjectOutputStream(bo);
            oo.writeObject(obj);
            bi=new ByteArrayInputStream(bo.toByteArray());
            oi=new ObjectInputStream(bi);
            value = oi.readObject();
        } catch (Exception e) {
        	this.printError(e, key,isSet);
        } finally{
            if(oo != null)
                try {
                    oo.close();
                } catch (Exception e) {
                	this.printError(e, key,isSet);
                }
            if(oi != null)
                try {
                    oi.close();
                } catch (Exception e) {
                	this.printError(e, key,isSet);
                }
        }
        return value;
    }
    
    /**
     * 日志输出
     */
    private void printError(Exception e,String key,boolean isSet){
    	if(isSet)
    		System.err.println(ERROR_SET + key);
    	else
    		System.err.println(ERROR_GET + key);
        if(this.isdev)
            e.printStackTrace();
    }
    
    /**
     * 存入缓存
     */
    public void set(String key,Object value,long timeout){
        this.delete(key);
        this.cache.put(key, this.clone(key,value,true));
        if(timeout > 0l)
        	this.tasks.put(key,timeout*1000l + System.currentTimeMillis());
    }
    
    /**
     * 获取缓存
     */
    public Object get(String key){
    	Long timeout = this.tasks.get(key);
		if(timeout != null && timeout <= System.currentTimeMillis())
			this.delete(key);
		return this.clone(key,this.cache.get(key),false);
    }

    /**
     * 删除缓存
     */
    public void delete(String key){
    	this.cache.remove(key);
    	this.tasks.remove(key);
    }
    
}
<think>我们正在处理一个关于使用Java实现地图服务发布图层功能的GIS问题。根据用户的问题,他想要了解如何使用Java实现地图服务的发布,特别是图层的发布功能。结合提供的引用,我们可以从引用[2]和引用[3]中提取相关信息。 引用[2]提到:使用图层组功能,把单个图层组合起来,一起发布,作为一个完整的地图服务。在图层组中进行图层叠加和样式绑定。具体步骤包括:点击图层组添加新图层组,添加名称和标题,填写数据地图中的边界,添加图层选择对应的图层样式,点击保存。 引用[3]则详细介绍了GIS的组件,其中服务层提到提供WMS(地图服务)、WFS(要素服务)等OGC标准接口,典型的技术工具包括GeoServer。同时,在GeoServer技术解析部分,我们得知GeoServer是一个开源的服务层软件,用于发布地理空间数据。 因此,我们可以推断用户想要的是通过Java代码来操作GeoServer这样的服务端软件,以实现发布地图图层的功能。GeoServer提供了REST API,允许我们通过编程方式(如使用Java)来管理服务器上的图层、图层组、样式等。 实现思路: 1. 使用Java程序通过HTTP请求调用GeoServer的REST API。 2. 根据GeoServer REST API的文档,构建相应的请求(如创建数据存储、发布图层、创建图层组等)。 步骤: 1. 准备GeoServer环境:安装并运行GeoServer,确保可以访问其管理界面(通常为http://localhost:8080/geoserver)。 2. 在GeoServer中创建好工作空间(workspace)和数据存储(store),这些也可以通过REST API创建。 3. 使用Java发送HTTP请求(如使用HttpClient)来发布图层。 下面是一个使用Java通过GeoServer REST API发布图层的示例步骤: ### 1. 添加数据存储(Store) 在发布图层之前,需要先添加数据存储。假设我们有一个Shapefile文件,我们可以创建一个新的数据存储。 ### 2. 发布图层(Layer) 添加数据存储后,就可以发布该存储中的图层。 ### 3. 创建图层组(Layer Group,可选) 如果需要将多个图层组合在一起发布,可以创建图层组。 ### Java代码示例 以下是一个使用Java发送HTTP请求到GeoServer的示例。注意:需要添加Apache HttpClient库。 ```java import org.apache.http.HttpResponse; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class GeoServerPublisher { private static final String GEOSERVER_URL = "http://localhost:8080/geoserver/rest"; private static final String USERNAME = "admin"; private static final String PASSWORD = "geoserver"; public static void main(String[] args) { try { // 创建认证凭证 CredentialsProvider provider = new BasicCredentialsProvider(); provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(USERNAME, PASSWORD)); // 创建HttpClient try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(provider).build()) { // 示例:创建工作空间(如果不存在) createWorkspace(httpClient, "myworkspace"); // 示例:创建Shapefile数据存储 createShapefileDataStore(httpClient, "myworkspace", "mydatastore", "file:/data/myshapefile.shp"); // 示例:发布图层(自动发布,创建存储后即可发布,但可能需要配置样式等) // 发布图层通常不需要单独调用,因为创建存储时会自动发布。但可能需要配置图层的样式等属性。 // 示例:创建图层组(可选) createLayerGroup(httpClient, "myworkspace", "mygroup", new String[]{"mylayer"}); } } catch (Exception e) { e.printStackTrace(); } } private static void createWorkspace(CloseableHttpClient httpClient, String workspace) throws Exception { String url = GEOSERVER_URL + "/workspaces"; HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Content-Type", "application/json"); String json = "{\"workspace\":{\"name\":\"" + workspace + "\"}}"; httpPost.setEntity(new StringEntity(json)); HttpResponse response = httpClient.execute(httpPost); // 检查响应状态码,201表示创建成功 System.out.println("Create workspace response: " + response.getStatusLine().getStatusCode()); } private static void createShapefileDataStore(CloseableHttpClient httpClient, String workspace, String storeName, String shapefilePath) throws Exception { String url = GEOSERVER_URL + "/workspaces/" + workspace + "/datastores"; HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Content-Type", "application/json"); String json = "{\"dataStore\": {\"name\": \"" + storeName + "\", \"connectionParameters\": {\"url\": \"" + shapefilePath + "\", \"namespace\": \"" + workspace + "\"}}}"; httpPost.setEntity(new StringEntity(json)); HttpResponse response = httpClient.execute(httpPost); System.out.println("Create datastore response: " + response.getStatusLine().getStatusCode()); } private static void createLayerGroup(CloseableHttpClient httpClient, String workspace, String groupName, String[] layerNames) throws Exception { String url = GEOSERVER_URL + "/layergroups"; HttpPost httpPost = new HttpPost(url); httpPost.setHeader("Content-Type", "application/json"); // 构建图层组的JSON StringBuilder layersJson = new StringBuilder(); for (String layerName : layerNames) { if (layersJson.length() > 0) layersJson.append(","); layersJson.append("{\"@type\":\"layer\",\"name\":\"").append(workspace).append(":").append(layerName).append("\"}"); } String json = "{\"layerGroup\": {\"name\": \"" + groupName + "\", \"workspace\": \"" + workspace + "\", \"publishables\": {\"published\": [" + layersJson + "]}}}"; httpPost.setEntity(new StringEntity(json)); HttpResponse response = httpClient.execute(httpPost); System.out.println("Create layer group response: " + response.getStatusLine().getStatusCode()); } } ``` ### 注意事项 1. 上述代码仅为示例,实际使用中需要根据GeoServer的版本和具体配置进行调整。 2. GeoServer REST API的详细文档可以参考官方文档:https://docs.geoserver.org/latest/en/user/rest/index.html 3. 需要确保GeoServer已经运行,并且网络可访问。 4. 需要处理异常和错误情况,例如当工作空间已存在时,创建请求会失败。 ### 总结 通过Java调用GeoServer的REST API,我们可以实现地图图层的发布和管理。这为自动化发布地图服务提供了可能,特别是在需要频繁更新或批量发布图层的场景中。 ### 相关问题 1. 如何通过Java代码配置GeoServer图层的样式(SLD)? 2. GeoServer REST API中如何管理图层属性(如设置图层的坐标参考系统)? 3. 除了GeoServer,还有哪些地图服务器支持通过Java进行图层发布? 4. 如何处理GeoServer REST API调用中的安全认证问题?</think>### Java实现地图服务发布图层功能 在GIS系统中发布地图图层涉及以下核心步骤(基于GeoServer实现): #### 1. 环境准备 ```java // Maven依赖 <dependency> <groupId>org.geoserver</groupId> <artifactId>geoserver-manager</artifactId> <version>1.7.0</version> </dependency> ``` #### 2. 核心代码实现 ```java import it.geosolutions.geoserver.rest.GeoServerRESTManager; import it.geosolutions.geoserver.rest.GeoServerRESTPublisher; public class LayerPublisher { private static final String GEOSERVER_URL = "http://localhost:8080/geoserver"; private static final String ADMIN = "admin"; private static final String PASSWORD = "geoserver"; public void publishShapefileLayer(String workspace, String storeName, String layerName, String shpPath) { try { // 创建连接管理器 GeoServerRESTManager manager = new GeoServerRESTManager( GEOSERVER_URL, ADMIN, PASSWORD); GeoServerRESTPublisher publisher = manager.getPublisher(); // 1. 创建工作空间 publisher.createWorkspace(workspace); // 2. 创建数据存储(连接Shapefile) publisher.createShapefileDatastore( storeName, workspace, new File(shpPath) ); // 3. 发布图层 boolean published = publisher.publishDBLayer( workspace, storeName, layerName, "EPSG:4326", // 坐标系 "default_point" // 样式名称 ); System.out.println("图层发布" + (published ? "成功" : "失败")); } catch (Exception e) { e.printStackTrace(); } } } ``` #### 3. 关键参数说明 1. **工作空间(workspace)**:项目的逻辑容器 2. **数据存储(storeName)**:物理数据连接(支持Shapefile/PostGIS等) 3. **图层名称(layerName)**:服务的显示名称 4. **坐标系(EPSG代码)**:如`EPSG:4326`(WGS84)或`EPSG:3857`(Web墨卡托) #### 4. 完整工作流程 1. **数据准备**:将Shapefile放在GeoServer可访问路径 2. **服务发布**:执行上述Java代码 3. **服务验证**:访问WMS服务URL: ``` http://localhost:8080/geoserver/{workspace}/wms?service=WMS&version=1.1.0&request=GetMap ``` ### 技术原理 GIS服务发布的核心是通过OGC标准协议(WMS/WFS)暴露空间数据[^3]。GeoServer作为服务层组件,其架构包含: - **数据层**:存储Shapefile/PostGIS等空间数据 - **服务层**:通过REST API管理地图服务 - **应用层**:Java SDK封装REST接口实现自动化发布 ### 注意事项 1. 确保GeoServer已启动且REST插件启用 2. Shapefile需包含`.shp`, `.shx`, `.dbf`三个基础文件 3. 复杂场景建议使用PostGIS数据库替代文件存储 4. 样式文件(SLD)可通过`publishStyle()`方法单独发布 ### 备选方案 ```mermaid graph LR A[Java程序] --> B{发布方式} B --> C[GeoServer REST API] B --> D[GeoTools直接生成] B --> E[MapServer CGI] ``` ### 相关问题 1. 如何通过Java代码动态生成地图切片(Tile Cache)? 2. GeoServer的REST API与Web管理界面有何性能差异? 3. 发布PostGIS数据库图层需要哪些额外配置? 4. 如何实现地图服务的权限控制(基于Java)? 5. 除了GeoServer,还有哪些开源地图服务器支持Java集成? [^1]: Python与GIS地理信息系统实战 [^2]: GIS基础知识 GeoServer [^3]: 地理信息系统(GIS)与代码集成指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值