基于 JAX-RS 机制定义 REST 资源 |
作为示例,这里以一个伪地址匹配(从一个 txt 里读取关键字对应的匹配结果)作为领域功能。基于伪地址匹配功能组件创建一个新资源,实现匹配字段,并在地图上显示匹配的结果。资源预期如下:
资源名称:addressMatchRoot,addressMatch
资源 URI:../services/address-sample/restjsr/adressmatch
资源支持的表述格式:XML、JSON、RJSON
资源 URI 参数:
名称 | 类型 | 描述 |
keyWord | String |
用户输入的中文地址 |
领域资源创建与使用的总体流程为:
实现地址匹配业务组件实现类 AddressMatchImpl、地址匹配资源 AddressMatchResource。
分别添加模块配置文件 addressmatchRest、JAX-RS 资源配置文件 addressMatchResources.xml、SuperMap iServer 服务配置文件 iserver-services.xml、以及数据文件 addressMatchDatas。
重启 SuperMap iServer 服务,访问创建的领域服务资源:http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch。
示例工程请参见:%SuperMap iServer_HOME%\samples\code\DSSE_JSR,将示例工程编译为 Jar(参见:dsse_jsr.jar),放到 %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib 下,重启 SuperMap iServer 服务,即可进行资源访问。
设计实现 AddressMatchImpl 做为服务组件提供“伪地址匹配功能”,AddressMatchImpl 通过使用 SuperMap iServer 的地图服务组件实现标签显示,整体功能通过 JAX-RS 服务接口暴露为 REST 资源,REST 资源实现类为 AddressMatchResource,如下图所示。
地址匹配业务组件实现类 AddressMatchImpl,具体实现过程如下:
package com.supermap.sample.components.impl;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.supermap.sample.components.AddressMatchConfig;
import com.supermap.sample.components.AddressMatchResult;
import com.supermap.sample.components.AddressMatch;
import com.supermap.services.components.Component;
import com.supermap.services.components.ComponentContext;
import com.supermap.services.components.ComponentContextAware;
import com.supermap.services.components.commontypes.Color;
import com.supermap.services.components.commontypes.DatasetType;
import com.supermap.services.components.commontypes.DatasetVectorInfo;
import com.supermap.services.components.commontypes.FillGradientMode;
import com.supermap.services.components.commontypes.ImageOutputOption;
import com.supermap.services.components.commontypes.LabelBackShape;
import com.supermap.services.components.commontypes.MapImage;
import com.supermap.services.components.commontypes.MapParameter;
import com.supermap.services.components.commontypes.OutputFormat;
import com.supermap.services.components.commontypes.Point2D;
import com.supermap.services.components.commontypes.Rectangle;
import com.supermap.services.components.commontypes.RectifyType;
import com.supermap.services.components.commontypes.Style;
import com.supermap.services.components.commontypes.TextAlignment;
import com.supermap.services.components.commontypes.TextStyle;
import com.supermap.services.components.commontypes.ThemeLabel;
import com.supermap.services.components.commontypes.UGCThemeLayer;
import com.supermap.services.components.spi.MapProvider;
/**
* 地址匹配业务组件实现类。
* 该类实现地址匹配的功能。
* <p>
* The address matching business component implementation class.
* The address matching function implemented by this class
* </p>
* @author Administrator
*
*/
@Component(providerTypes={MapProvider.class}, optional=false,type="")
public class AddressMatchImpl implements AddressMatch, ComponentContextAware {
private String mapName;
private MapProvider mapProvider;
// 地址匹配的数据信息
// The address matching data information
private List<String> datas = new ArrayList();
public AddressMatchImpl() {
}
/**
* 根据指定的中文地址模糊匹配,获得地址匹配的结果。
* <p>
* Get the address matching result according to the fuzzy matching of the specified Chinese address.
* </p>
* @param keyWord
* @return
*/
public AddressMatchResult[] match(String keyWord) {
if (keyWord == null) {
throw new IllegalArgumentException("Argument keyWord can not be null");
}
List<AddressMatchResult> matchResults = new ArrayList();
// 搜索原始数据信息,找到和关键子匹配的数据条目
// 元素数据以字符串信息保存,并以 ";" 来区分各个字段。如 北京;12958399.4681885;4852082.42975164
// Search the original data to find out the data entries matching the keywords.
// The entries are saved as strings separated by ";". For instance, Ottawa; Canada; -75.650749206543;45.374217987060
for (String dataStr : this.datas) {
String[] dataArray = dataStr.split(";");
String capital = dataArray[0];
String matchedAddress= null;
// 搜索与关键字匹配的条目。
// Search the entries matching the keywords.
if (capital.contains(keyWord)) {
matchedAddress=capital;
}
if (matchedAddress!= null) {
AddressMatchResult result = new AddressMatchResult();
result.keyWord = keyWord;
try {
double smx = Double.parseDouble(dataArray[1]);
double smy = Double.parseDouble(dataArray[2]);
result.location = new Point2D(smx, smy);
result.matchedAddress = matchedAddress;
result.imageUrl = this.getImageURI(result);
matchResults.add(result);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
AddressMatchResult[] resultArray = new AddressMatchResult[matchResults.size()];
// 将匹配结果列表转换成匹配结果数组
// Convert the result list into an array
matchResults.toArray(resultArray);
return resultArray;
}
/**
* 根据匹配得到的地址进行出图 ,即获取图片的 URI 地址。
* <p>
* Outputs a map according to the result, i.e., gets the URI of the map image.
* </p>
* @param result
* @return
*/
private String getImageURI(AddressMatchResult result) {
MapParameter defaultMapParameter = this.mapProvider.getDefaultMapParameter(this.mapName);
ImageOutputOption outputOption = new ImageOutputOption();
outputOption.format = OutputFormat.BMP;
// 添加专题图
// Add the thematic map
ThemeLabel themeLabel = new ThemeLabel();
themeLabel.memoryData = new HashMap<String, String>();
String capitalName = result.matchedAddress;
String value = capitalName + " Location: (" + String.format("%.1f", result.location.x) + " ," +String.format("%.1f", result.location.y) + ")";
themeLabel.memoryData.put(capitalName, value);
themeLabel.labelExpression = "NAME";
themeLabel.labelBackShape = LabelBackShape.ROUNDRECT;
Style style = new Style();
style.fillBackColor = new Color(java.awt.Color.MAGENTA.getRed(), java.awt.Color.MAGENTA.getGreen(), java.awt.Color.MAGENTA.getBlue());
style.fillBackOpaque = true;
style.fillForeColor = new Color(java.awt.Color.YELLOW.getRed(), java.awt.Color.YELLOW.getGreen(), java.awt.Color.YELLOW.getBlue());
style.fillGradientMode = FillGradientMode.RADIAL;
themeLabel.backStyle = style;
TextStyle textStyle = new TextStyle();
textStyle.backColor = new Color(java.awt.Color.BLUE.getRed(), java.awt.Color.BLUE.getGreen(), java.awt.Color.BLUE.getBlue());
textStyle.fontWidth = 50000;
textStyle.fontHeight = 50000;
textStyle.align = TextAlignment.MIDDLECENTER;
themeLabel.uniformStyle = textStyle;
DatasetVectorInfo datasetVectorInfo = new DatasetVectorInfo();
datasetVectorInfo.name = "China_Capital_pt";
datasetVectorInfo.type = DatasetType.POINT;
datasetVectorInfo.dataSourceName = "China";
UGCThemeLayer themelayer = new UGCThemeLayer();
themelayer.theme = themeLabel;
themelayer.datasetInfo = datasetVectorInfo;
themelayer.visible = true;
themelayer.displayFilter = "NAME = '" + capitalName + "'";
defaultMapParameter.layers.get(0).subLayers.add(true, themelayer);
defaultMapParameter.rectifyType = RectifyType.BYCENTERANDMAPSCALE;
defaultMapParameter.center = result.location;
defaultMapParameter.viewer = new Rectangle(0,0,512,512);
defaultMapParameter.scale =0.00000003;//0.00000003;
MapImage mapImage = this.mapProvider.getMapImage(defaultMapParameter, outputOption);
return mapImage.imageUrl;
}
/**
* 设置组件上下文,通过组件上下文可以得到该业务组件所用的服务提供者。
* <p>
* Set the component context, and get the service provider of the business component through the component context.
* </p>
*/
public void setComponentContext(ComponentContext context) {
AddressMatchConfig config = context.getConfig(AddressMatchConfig.class);
String dataConfigPath = config.addressMatchDataPath;
this.initDataInfo(dataConfigPath);
this.mapName = config.mapName;
MapProvider tempMapProvider = context.getProvider(MapProvider.class, null);
this.mapProvider = tempMapProvider;
}
private void initDataInfo(String dataFilePath) {
// 加载地址匹配数据信息。
// 地址匹配信息从文件addressmatchDatas 中读取。
// Load address matching data information.
// Read address matching information from the addressmatchDatas file.
//InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("addressMatchDatas");
try {
FileInputStream stream=new FileInputStream(dataFilePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "utf-8"));
String dataLine = reader.readLine();
boolean firstLine = true;
while (dataLine != null) {
if (!firstLine) {
datas.add(dataLine);
} else {
firstLine = false;
}
dataLine = reader.readLine();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
地址匹配资源 AddressMatchResource 的具体实现过程如下:
package com.supermap.sample.rest.resources.impl;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import com.supermap.sample.components.AddressMatchResult;
import com.supermap.services.InterfaceContext;
import com.supermap.sample.components.AddressMatch;
import com.supermap.services.rest.HttpException;
import com.supermap.services.rest.Template;
import com.supermap.services.rest.commontypes.Component;
import com.supermap.services.rest.resources.JaxrsResourceBase;
/**
* 地址匹配资源实现类
* <p>
* The implementation class of the AddressMatch resource.
* </p>
* @author Administrator
*
*/
@Path("/addressmatch")
// 申明该资源需要使用的业务组件
//Declare the business component that needs to be used
@Component(interfaceClass = AddressMatch.class)
public class AddressMatchResource extends JaxrsResourceBase {
@GET
@Template(name = "matchaddressForm.ftl")
public Map<String, String> getGetForm(@Context HttpServletRequest request) {
String url = request.getRequestURL().toString();
Map<String,String> variables = new HashMap<String,String>();
variables.put("url", url);
return variables;
}
@GET
@Path("{keyWord}")
@Template(name = "matchaddress.ftl")
public AddressMatchResult[] addressMatch(
@PathParam("keyWord") String keyWord,
@Context HttpServletRequest request) {
if (keyWord == null) {
throw new HttpException(400, "Argument keyWord can not be null");
}
try {
keyWord = URLDecoder.decode(keyWord, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 获取REST 服务的接口上下文
// Get the interface context of the REST service
InterfaceContext interfaceContext = this.getInterfaceContext();
// 从服务接口中获取地址匹配业务组件,默认获取第一个业务组件。
// Get the business component from the service interface context. The first business component will be got by default.
AddressMatch addressMatchComponent = interfaceContext.getComponents(
AddressMatch.class).get(0);
AddressMatchResult[] results = addressMatchComponent.match(keyWord);
this.replacePort(results ,request);
return results;
}
private void replacePort(AddressMatchResult[] results,HttpServletRequest request){
if(results == null || results.length == 0){
return;
}
String port = String.valueOf(request.getServerPort());
String ip=request.getServerName();
for(AddressMatchResult result : results){
if(result != null && result.imageUrl != null ){
result.imageUrl = result.imageUrl.replace("{port}", port);
result.imageUrl = result.imageUrl.replace("{ip}", ip);
}
}
}
}
resourceFiles=addressMatchResources.xml
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!-- 地址匹配资源 -->
<resource>
<configID>addressmatch</configID>
<implementClass>com.supermap.sample.rest.resources.impl.AddressMatchResource</implementClass>
</resource>
</resources>
<!-- 地址匹配组件 -->
<component class="com.supermap.sample.components.impl.AddressMatchImpl" interfaceNames="restjsr" name="address-sample" providers="ugcMapProvider-China400">
<config class="com.supermap.sample.components.AddressMatchConfig">
<mapName>China</mapName>
<addressMatchDataPath>../../../samples/data/addressMatchDatas</addressMatchDataPath>
</config>
</component>
capital ; smx; smy
北京;12958399.4681885;4852082.42975164
成都;11584427.2984845;3588485.98582577
启动 SuperMap iServer,在服务首页可看到已发布的领域服务:address-sample/restjsr,访问资源:http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch,可以进行地址匹配的查询操作。
单击地址匹配按钮后,可以打开查询结果包括匹配的地址信息和匹配的地址坐标,资源:http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch/%E5%8C%97%E4%BA%AC。
点击北京,可以看到在地图显示的结果。