Defining REST resource based on JAX-RS |
For illustration, here we take pseudo address matching (read matches for a keyword from a txt file) as a domain function. A new resource is created based on the pseudo matching function component, a keyword is given, and the matches are displayed on the map. The expected resource is as follows:
Resource name: addressMatchRoot,addressMatch
Resource URI: ../services/address-sample/restjsr/adressmatch
Output formats: XML, JSON and RJSON
URI parameters:
Name | Type | Description |
keyWord |
String |
The Chinese address input by the user. |
The overall procedures for the domain resource creation and usage are as follows:
Implement the implementaion class for the business component--AddressMatchImpl, and the address matching resource AddressMatchResource.
The module configuration file addressmatchRest, the JAX-RS resource configuration file addressMatchResources.xml, the SuperMap iServer service configuration file iserver-services.xml and data file addressMatchDatas are added respectively. Add module configuration file addressmatchRest, JAX-RS configuration file addressMatchResources.xml, SuperMap iServer service configuration file iserver-services.xml, and data file addressMatchDatas.
Restart the SuperMap iServer service, and access the created domain service http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch.
The sample project is in %SuperMap iServer_HOME%\samples\code\DSSE_JSR. Compile the project to create a jar package (see dsse_jsr.jar) and place it in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib. Then restart SuperMap iServer server, you can perform Resource access.
The AddressMatchImpl is designed and implemented to provide the "pseudo address matching function" as the service component. The AddressMatchImpl uses the map service component of the SuperMap iServer to implement the label display. The function is exposed as REST resources through the JAX-RS service interfaces. The implementation class of the REST resource is AddressMatchResource.
Load the address matching data information, which is read from the file addressmatchDatas.
Get the address matching result according to the fuzzy matching of the specified Chinese address.
Make a map according to the address matching result.
Set the component context, and get the service provider of the business component from the component context.
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();
}
}
}
Determine the resource path ../addressmatch and declare the business component to be used by the resource--com.supermap.services.components.AddressMatch. The resource URI is http://supermapiserver:8090/iserver/services/address-sample/restjsr/addressmatch;
Specify the resource page template as matchaddressForm.ftl through @Template. That is to say, the template will be opened after using the above URI. For more information on template file tools, see FreeMarker variable provided by iServer;
Define the access path of the query result resource addressMatch as /{keyWord}, and specify the results page template as matchaddress.ftl;
Get the address matching business component from the service interface. By default, the first business component will be got.
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>
<!-- Address matching resource -->
<resource>
<configID>addressmatch</configID>
<implementClass>com.supermap.sample.rest.resources.impl.AddressMatchResource</implementClass>
</resource>
</resources>
<!-- Address matching component -->
<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
Beijing;12958399.4681885;4852082.42975164
Chengdu;11584427.2984845;3588485.98582577
Start SuperMap iServer, you can see published domain service address-sample/restjsr on the home page. You can perform address matching operation by accessing http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch.
Click match to display the result, including the address information and the coordinates. Resource: http://localhost:8090/iserver/services/address-sample/restjsr/addressmatch/%E5%8C%97%E4%BA%AC.
Click Beijing to see the map below.