我们已经建立好了所需要的工程,所以,我们来梳理下我们的业务的流程,首先会通过浏览器去请求响应的页面,index.html,这个一部表面上是有protal工程实现完成,但是实际上我们是攻过门户工程请求的rest工程发布的服务来完成的,所以应该首先了解一下我们的整个的请求工程;这以后其实浏览器会调用Ajac
x服务查询商品的分类列表,返回json数据(由rest调用服务得到)。
1.主体的服务流程:
首先,我们将上节中的资源导入到正确的位置,防止因为控制器拦截造成资源访问不到的问题,其次我们通过js以及前端的jsp页面了解到,与商品类目相关的功能的js为lib.js所以我们在里面找到了与本节内容相关的js代码:
可以看到这里是category方法,这个方法中定义了,发布服务的位置,可以看到,请求的内容为主机服务器8082端口的category.json数据,所以也就对应于我们的protal门户工程webapp下面的category.json文件,所以让我们启动一下看一下其返回内容:
可以看到返回了对应json文件中的内容了,但是这样可是比较乱,但是,总能看到开头,有一个category.getDataService函数,这个写法稍后讲解。
2.测试和实现
也就是说上面的函数中,我们提供一个服务的发布地址,我们就可以去到里面的内容,一般为json数据,因为涉及到传递给前端调用,所以需要了解一下具体的数据的格式问题,在这里我们可以使用json数据查看的工具等,例如jsonViewer,其处理后的接送数据的结构如下:
可以明显的看到结构,其中包含了多层结构,对于多层结构读取较好的方式就是递归或者是迭代循环读取,其中,u代表url,n代表name,i代表所需要查找的对应商品为:item。所以我们要把这样结构的一个json数据返回给前端使用。
收到这里如果我们直接将这个数据传递给前端是没问题的,因为我们使用的是测试数据,并且已经处理好了,同时这个信息也在端口为8082的服务器上,但是,我们需要的是我们的rest工程来发布服务,而protal工程仅用来调用服务,所以这时候就涉及到跨域请求的问题:
一般的在一个端口,或者一个服务器中的同一个工程中完全可以使用Ajax进行请求json数据的操作,但是我们现在是在两个不同的端口,8081端口用来发布服务,所以我们需要解决这个跨域问题:
首先,Ajax会请求js,将请求的js数据传递到rest工程中,实际上浏览器再js请求中是允许通过script标签的src进行跨域请求,可以在请求的结果中添加方法名,在再请求页面的页面中定义方法,这时响应的js就会被写做一个方法进行返回,结构如上图所示,然后再将js代码执行,取出里面的数据就可以获得json结构的数据将数据返回给前端。
这个问题解决了,问题是我们的分类数据都出存在数据库中,那我们如何返回其内容呢。
POJO类
设计一个pojo类,用来存储从数据库中获取到的数据,这个pojo类仅是用在protal和rest服务中,所以这个不属于公共的pojo所以可以放置在rest服务中即可,这个主要是存放的服务的内容:
public class CartResult {
private List<?> data;
public List<?> getData() {
return data;
}
public void setData(List<?> data) {
this.data = data;
}
}
这个仅仅是将整理好的json数据组织好,封装在List列表中。
CatNode类是放置获取的节点的内容:
public class CatNode {
@JsonProperty("n")
private String name;
@JsonProperty("u")
private String url;
@JsonProperty("i")
private List<?> item;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public List<?> getItem() {
return item;
}
public void setItem(List<?> item) {
this.item = item;
}
}
Service类
@Service
public class ItemCatServiceImpl implements ItemCatService{
@Autowired
private TbItemCatMapper itemCatMapper;
@Override
public CartResult queryAllCategory() {
CartResult cartResult = new CartResult();
//查询分类列表
cartResult.setData(getItemCatList(0));
return cartResult;
}
private List<?> getItemCatList(long parentId){
TbItemCatExample example = new TbItemCatExample();
Criteria criteria = example.createCriteria();
criteria.andParentIdEqualTo(parentId);
List<TbItemCat> list = itemCatMapper.selectByExample(example);
List resultList = new ArrayList();
int count = 0;
for (TbItemCat tbItemCat : list) {
//判断是否为父节点
if (tbItemCat.getIsParent()) {
CatNode catNode = new CatNode();
if(parentId ==0){
catNode.setName("<a href= '/products/" + tbItemCat.getId() + ".html'>"+tbItemCat.getName() +"</a>");
}else{
catNode.setName(tbItemCat.getName());
}
catNode.setUrl("/products/ "+tbItemCat.getId()+".html");
//递归调用
catNode.setItem(getItemCatList(tbItemCat.getId()));
resultList.add(catNode);
count ++;
//第一层仅取14条记录,
if(parentId ==0 && count >=14){
break;
}
}else{
resultList.add("/products/"+tbItemCat.getId()+".html|" + tbItemCat.getName());
}
}
return resultList;
}
}
这一部分涉及到将得到的数据库中的内容取出来拼装成json格式的数据,反馈给前端。
Controller层:
@Controller
public class ItemCatController {
@Autowired
private ItemCatService itemCatService;
@RequestMapping(value="/itemcat/list", produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
@ResponseBody
public String getItemCatList(String callback){
System.out.println("come in");
CartResult catResult = itemCatService.queryAllCategory();
//把pojo拼装成字符串
String json = JsonUtils.objectToJson(catResult);
//拼装返回值
String result = callback + "(" + json + ")";
return result;
}
}
而这时候,我们需要将刚才前端配置的服务地址修改为rest服务端口了:
可以看到,我们帆布服务的地址为8081端口,同时当请求的时候,会调用一个回掉函数category.getDataService方法读取json内容,其中起初利用这个方法解决了跨域的问题,启动rest工程和protal工程测试一下:
可以看到,展示成功。