AEM dropdown select by servlet
转载自:AEM - Touch UI dropdown from JSON file/Servlet
自己查了一下午资料,不如别人给的一份有用。
代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.adobe.cq.commerce.common.ValueMapDecorator;
import com.adobe.granite.ui.components.ds.DataSource;
import com.adobe.granite.ui.components.ds.EmptyDataSource;
import com.adobe.granite.ui.components.ds.SimpleDataSource;
import com.adobe.granite.ui.components.ds.ValueMapResource;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES;
@Component(service = Servlet.class,
property = {
Constants.SERVICE_ID + "=" + "Dynamic DataSource Servlet",
SLING_SERVLET_RESOURCE_TYPES + "=" + "/apps/aemtutorials/dropdowns"//如果路径不同,则不会触发该Servlet
})
public class DynamicDataSourceServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1L;
Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
throws ServletException, IOException {
try {
ResourceResolver resolver = request.getResourceResolver();
Resource currentResource = request.getResource();
// set fallback
request.setAttribute(DataSource.class.getName(), EmptyDataSource.instance());
//Get json path through datasource options
String jsonStr = null;
Resource datasource = currentResource.getChild("datasource");
Object options = datasource.getValueMap().get("options");
Resource jsonResource = resolver.getResource(options.toString()+"/jcr:content");
jsonStr = getJsonFromFile(jsonResource);//Json to String
Gson gson = new Gson();
TypeToken<List<Option>> token = new TypeToken<List<Option>>(){};
List<Option> optionList = gson.fromJson(jsonStr, token.getType());
List<Resource> optionResourceList = new ArrayList<Resource>();
Iterator<Option> oi = optionList.iterator();
while (oi.hasNext()) {
Option opt = oi.next();
ValueMap vm = getOptionValueMap(opt);//Option to ValueMap
optionResourceList
.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm));
}
DataSource ds = new SimpleDataSource(optionResourceList.iterator());
request.setAttribute(DataSource.class.getName(), ds);
} catch (IOException io) {
logger.info("Error fetching JSON data ");
io.printStackTrace();
} catch (Exception e) {
logger.info("Error in Getting Drop Down Values ");
e.printStackTrace();
}
}
private ValueMap getOptionValueMap(Option opt) {
ValueMap vm = new ValueMapDecorator(new HashMap<String, Object>());
vm.put("value", opt.getValue());
vm.put("text", opt.getText());
if (opt.isSelected()) {
vm.put("selected", true);
}
if (opt.isDisabled()) {
vm.put("disabled", true);
}
return vm;
}
private String getJsonFromFile(Resource jsonResource)
throws RepositoryException, ValueFormatException, PathNotFoundException, IOException {
String json = null;
if (!ResourceUtil.isNonExistingResource(jsonResource)) {
Node cfNode = jsonResource.adaptTo(Node.class);
InputStream in = cfNode.getProperty("jcr:data").getBinary().getStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
json = sb.toString();
reader.close();
}
return json;
}
private class Option {
String text;
String value;
boolean selected;
boolean disabled;
public String getText() {
return text;
}
public String getValue() {
return value;
}
public boolean isSelected() {
return selected;
}
public boolean isDisabled() {
return disabled;
}
}
}
XML:
<social
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/select"
fieldLabel="Social Media"
name="./social">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/aemtutorials/dropdowns"
dropdownSelector="fontList"
options="/content/dam/xxx/font.json"/>
- 注意Java代码最上边
/apps/aemtutorials/dropdowns这个路径要与XML的sling:resourceType相同,实际路径好像没什么意义,只要一样就能将组件与他关联起来。打开组件设置就能触发该servlet - XML中的options是记录json文件地址,到时候要在Java中获取该地址去拿json
- 整体思路应该是先将两者关联-->获取JSON-->JSON格式转来转去-->最后request.setAttribute就能被组件获取到了
- 看看JSON都转了些什么:
Resource jsonResource = resolver.getResource(options.toString()+"/jcr:content");//拿到JSON结点的ResourcejsonStr = getJsonFromFile(jsonResource);//Json to String//Resource转String,通过流等方法List<Option> optionList = gson.fromJson(jsonStr, token.getType());//String转List<Option> Option自己定义的ValueMap vm = getOptionValueMap(opt);//Option to ValueMap 将List<Option>迭代,每个Option变成ValueMapoptionResourceList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm));//ValueMap变成List<Resource>DataSource ds = new SimpleDataSource(optionResourceList.iterator());//List<Resource>变成DataSource
为什么只要resourceType相同就可以触发呢?
- 对比:除了resourceType,其实还有paths属性,只要设置对了paths属性,比如/bin/asdf(必须得在bin或apps等这种下面,不然会被forbidden),当你打开网址localhost:4502/bin/asdf就可以触发该servlet了。
- 所以!只要你打开某个组件中resourceType为xxx的就可以触发该servlet了!
- 我又思考了一下,上面代码的各种转换应该就是转换为一个个节点,可能是替代了datasource。
知识离开了脑子,就只是一堆文字

浙公网安备 33010602011771号