(1)搭建前台系统。
(2)完成首页导航菜单。(学习jsonp)
(3)完成CMS内容管理系统。
(4)完成首页大广告位投放。(学习Httpclient)
[if !supportLists]1 [endif]搭建前台系统
[if !supportLists]1.1 [endif]前台系统架构
[if !vml]
[endif]
在互联网系统开发当中,我们一般都是采用了分层的方式来架构系统,即:
(1)门户层(门户系统):网站的入口
i、渲染视图,提供用户访问的页面。
ii、不查询数据库,数据来自对远程服务(接口)的调用。
(2)服务层:基于restful,以接口的形式对外提供公共的服务。
i、连接数据库,返回json格式的数据。
[if !supportLists]1.1.1 [endif]分层架构的好处
(1)、有利于系统的维护和拓展。
(2)、有利于SOA服务治理的基础。
[if !supportLists]1.2 [endif]搭建服务层系统
[if !supportLists]1.2.1 [endif]系统简介
基于RESTful实现。以接口的形式,对外提供公共的服务。(比如购物车、导航菜单、搜索、订单等等)
RESTful是一种接口设计理念,即:
(1)不同的请求方式,对应不同的业务类型:
GET :查询
POST :添加
PUT :更新
DELETE:删除
(2)返回json格式数据。
[if !supportLists]1.2.2 [endif]技术选择
核心框架:Spring+SpringMVC+Mybatis-plus
数据库:MySQL
前端框架:无
[if !supportLists]1.2.3 [endif]配置步骤
思路:(1)创建项目,导入jar依赖。
(2)整合SSM框架。
[if !supportLists]1.2.3.1 [endif]第一步:创建maven项目(war)模型
注意:(1)项目继承ego-project。
(2)使用maven module创建项目
[if !vml]
[endif]
[if !supportLists]1.2.3.2 [endif]第二步:导入jar依赖
导包说明:
(1)ego-base子工程
(2)Spring核心包
(3)SpringMVC相关包
(4)AOP相关包
(5)JDBC、事物相关包
(6)Mybatis-plus及整合包
(7)JSON依赖包
导入插件:Tomcat插件(开发阶段,启动项目,对外发布接口)
8081
[if !supportLists]1.2.3.3 [endif]第三步:创建web.xml文件
说明:可以从ego-manager工程中拷贝,修改
"1.0"encoding="UTF-8"?>
http://xmlns.jcp.org/xml/ns/javaee/web-app_2_5.xsd ">
/rest/*
[if !supportLists]1.2.3.4 [endif]第四步:整合SSM框架
整合中所需要的配置文件,均可从ego-manager工程中拷贝,修改局部的配置即可。
[if !supportLists]1.2.3.4.1 [endif]Step1:Spring整合SpringMVC
创建spring-mvc.xml文件,做如下配置:
"1.0"encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
[if !supportLists]1.2.3.4.2 [endif]Step2:mybatis-plus整合spring
在这里,我们一定要有一个概念:任何持久层框架和Spring的整合,都是为了使用Spring的事物代理。
(1)创建resource.properties文件,配置数据库连接信息如下:
#配置数据源
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/ego
db.username=root
db.password=gzsxt
(2)创建spring-data.xml文件,配置框架整合。
"1.0"encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
[if !supportLists]1.2.3.5 [endif]第五步:整合测试
在这里我们使用静态数据(category.json),来模拟导航菜单接口的实现。
(1)拷贝category.json文件到webapp目录下。
[if !vml]
[endif]
(2)更新项目、安装到本地仓库(updata、maven clean、maven install)
(3)启动项目
[if !vml]
[endif]
查看控制台,启动成功!!!
[if !vml]
[endif]
(4)浏览器访问,地址:http://localhost:8081/category.json,整合成功!!!
[if !vml]
[endif]
[if !supportLists]1.3 [endif]搭建门户系统
[if !supportLists]1.3.1 [endif]系统简介
简单来说就是网站的入口,提供用户浏览、下单的操作页面。
门户系统不直接调用数据库,而是通过服务系统提供的接口获取数据。电商、互联网行业开发都是面向服务开发。
[if !supportLists]1.3.2 [endif]技术选择
核心框架:Spring+SpringMVC
数据库:无
前端技术:jquery、ajax、css+div、easyui等
[if !supportLists]1.3.3 [endif]配置步骤
思路:(1)创建项目
(2)框架整合
[if !supportLists]1.3.3.1 [endif]第一步:创建maven项目(war模型)
注意:(1)继承ego-project工程
(2)使用maven module创建子系统
[if !vml]
[endif]
[if !supportLists]1.3.3.2 [endif]第二步:导入jar依赖
在门户系统中,不直接查询数据库,所以不需要导入数据库相关的jar包。
在门户系统中,用户能够搜索、浏览商品,提交订单等,所以需要添加jsp视图相关依赖。
http://maven.apache.org/xsd/maven-4.0.0.xsd">
8082
[if !supportLists]1.3.3.3 [endif]第三步:创建web.xml文件
可以从ego-rest工程拷贝,修改
"1.0"encoding="UTF-8"?>
">
[if !supportLists]1.3.3.4 [endif]第四步:导入jsp页面、静态资源
说明:(1)静态资源放在/webapp目录
(2)jsp放到/WEB-INF/JSP目录下
[if !vml]
[endif]
[if !supportLists]1.3.3.5 [endif]第五步:Spring整合SpringMVC
从ego-rest工程拷贝,修改部分配置即可。
"1.0"encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
[if !supportLists]1.3.3.6 [endif]第六步:整合测试
需求:访问门户系统首页。
(1)创建PageController类
package cn.gzsxt.portal.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/index")
public String showIndex(){
return "index";
}
}
(2)更新项目、安装到本地仓库。(update、clean、install)
(3)启动项目
[if !vml]
[endif]
(4)访问首页,地址:http://localhost:8082
[if !vml]
[endif]
前台系统搭建成功!!!
[if !supportLists]2 [endif]首页导航菜单实现
说明:首页导航菜单,是通过异步加载实现的。
好处:只有当展开导航菜单时,才会发送请求,从而节约cpu资源。
[if !supportLists]2.1 [endif]实现流程
[if !vml]
[endif]
需要解决的问题:
(1)在rest系统中发布接口,封装导航菜单成json格式数据。
(2)在portal系统中,远程请求接口(跨域请求)。
[if !supportLists]2.2 [endif]跨越请求
[if !supportLists]2.2.1 [endif]什么是跨域(两个不同系统之间的访问、调用)
(1)域名不同,即两个不同的应用。
[if !vml]
[endif]
(2)域名相同,但是端口不同,即同一个应用中的不同子系统。
[if !vml]
[endif]
[if !supportLists]2.2.2 [endif]Ajax跨域请求的缺陷
在ego-rest系统使用静态数据,模拟Ajax的跨域问题。
[if !supportLists]2.2.2.1 [endif]第一步:在ego-rest中添加category.json文件。(已实现)
[if !supportLists]2.2.2.2 [endif]第二步:在ego-portal中发送ajax请求
(1)创建testJsonp.jsp页面
<%@pagelanguage="java"contentType="text/html;
charset=UTF-8"
pageEncoding="UTF-8"%>
HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
function testajax(){
$.ajax({
url:"http://localhost:8081/category.json",
type:"GET",
success:function (data) {
$("#text").val(JSON.stringify(data));
}
});
}
(2)修改PageController,新增访问非首页的方法。
@RequestMapping("/{page}")
public String showPage(@PathVariable("page")String page){
return page;
}
[if !supportLists]2.2.2.3 [endif]第三步:测试Ajax跨越
(1)重启启动ego-portal系统,访问testJsonp.jsp
[if !vml]
[endif]
(2)点击按钮,发送异步请求
[if !vml]
[endif]
测试发现,Ajax跨越请求失败了。
[if !supportLists]2.2.3 [endif]解决方案:jsonp跨域
在前面的测试中,我们发现Ajax跨越请求时,json数据被浏览器禁用了。
原因:浏览器禁止远程加载Json数据。(浏览器安全机制)
如何解决呢?
答:使用Jsonp方式。
[if !supportLists]2.2.3.1 [endif]Jsonp原理
Jsonp实现的前提:
浏览器允许跨越加载同源数据。
即在JavaScript脚本中发送请求,就可以远程加载js格式数据。
请求原理:
(1)异步请求的时候,加上一个名为callback的回调函数
(2)在接口中,将返回的json格式数据,伪装成js脚本格式。
(3)得到js格式数据后,提取里面的json数据。
[if !vml]
[endif]
[if !supportLists]2.2.3.2 [endif]测试Jsonp
(1)修改testJsonp.jsp,指定异步请求为jsonp方式。
function testajax(){
$.ajax({
url:"http://localhost:8081/category.json",
type:"GET",
dataType:"jsonp",
//jsonp请求
jsonp:"callbackFunction",
//请求参数名
jsonpCallback:"showData",
//回调函数名称
success:function (data) {
$("#text").val(JSON.stringify(data));
}
});
}
(2)在ego-rest工程中,修改category.json文件,将返回数据包装成js脚本。
[if !vml]
[endif]
(3)再次发送ajax异步请求,使用jsonp方式
[if !vml]
[endif]
结论:(1)jsonp是ajax技术中的一种异步请求方式。
(2)jsonp能实现跨越请求。
(3)jsonp跨越时,需要指定一个回调函数,并使用该函数将返回的数据伪装成js脚本。
(4)获取返回的js脚本后,jsonp自动提取其中的json数据。
[if !supportLists]2.3 [endif]首页导航菜单实现
思路:
(1)在rest工程中,开发接口,返回js格式数据。(参考category.json)
(2)在portal工程中,修改jsonp请求路径。请求rest接口。
[if !supportLists]2.3.1 [endif]第一部分:在rest工程中开发导航菜单接口
[if !supportLists]2.3.1.1 [endif]第一步:定义导航菜单POJO
导航菜单结构分析。(使用JsonViewer工具查看category.json)
[if !vml]
[endif]
结论:(1)需要定义两个POJO:菜单POJO、父目录节点POJO
(2)导航菜单的数据,是一次加载出来的。
创建菜单Menu类。(ego-base中创建)
package cn.gzsxt.base.pojo;
import java.util.List;
/**
*自定义导航菜单
*@authorccnulyq
*
*/
public class Menu {
private List> data; //目录节点
public List> getData() {
return data;
}
public void setData(List> data) {
this.data = data;
}
public Menu() {
super();
}
}
创建父目录节点MenuNode类
package cn.gzsxt.base.pojo;
import java.util.List;
/**
*自定义目录节点结构
*@authorccnulyq
*
*/
public class MenuNode {
private String u; //目录的链接
private String n; //目录的名称
private List> i; //当请目录的子目录
public MenuNode() {
super();
}
//
补全get、set方法
}
(3)重新编译ego-base工程,安装到本地仓库。(maven clean、maven install)
[if !supportLists]2.3.1.2 [endif]第二步:创建ItemCatService接口及其实现类
package cn.gzsxt.rest.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.gzsxt.base.mapper.ItemCatMapper;
import cn.gzsxt.base.pojo.ItemCat;
import cn.gzsxt.base.vo.Menu;
import cn.gzsxt.base.vo.MenuNode;
import cn.gzsxt.rest.service.ItemCatService;
@Service
public class ItemCatServiceImpl implements ItemCatService{
@Autowired
private ItemCatMapper itemCatMapper;
@Override
public Menu initMenu() {
Menumenu = new Menu();
//从返回值Menu的形式上来看,就是把一级目录查询出来即可。因此定义一个查询方法,通过parent_id=0查询一级目录
Listnodes = getNodesByParantId(0L);
menu.setData(nodes);
return menu;
}
//根据父目录的id,查询子目录
private List getNodesByParantId(long parentId) {
Mapparams = new HashMap<>();
params.put("parent_id", parentId);
ListselectByMap = itemCatMapper.selectByMap(params);
Listnodes = new ArrayList<>();
MenuNodenode = null;
for (ItemCat itemCat : selectByMap) {
if(1==itemCat.getIsParent()){
node = new MenuNode();
node.setU("/products/"+itemCat.getId()+".html");
//u :
"/products/1.html"
node.setN(""+itemCat.getName()+""); //n : "图书、音像、电子书刊"
node.setI(getNodesByParantId(itemCat.getId()));
nodes.add(node);
}else{
nodes.add("/products/"+itemCat.getId()+".html|"+itemCat.getName()); //[3] : "/products/6.html|多媒体图书"
}
}
return nodes;
}
}
[if !supportLists]2.3.1.3 [endif]第三步:创建ItemCatController类
说明:需要将返回值,包装成js脚本数据。
(1)方式一:手动封装
package cn.gzsxt.rest.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.utils.JsonUtils;
import cn.gzsxt.base.vo.Menu;
import cn.gzsxt.rest.service.ItemCatService;
@Controller
public class ItemCatController {
@Autowired
private ItemCatService catService;
/*
*jsonp方法下,返回值,要使用回调函数来伪装js脚本
* @return
*/
@RequestMapping(value="/item/all",produces=MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
@ResponseBody
public String getMenu(String callback){
Menumenu = catService.initMenu();
StringjsonMenu= JsonUtils.objectToJson(menu);
StringjsMenu = callback+"("+jsonMenu+")";
return jsMenu;
}
}
(2)方式二:使用MappingJacksonValue对象封装
//使用MappingJacksonValue对象包装返回结果,并设置jsonp的回调方法
@RequestMapping("/item/all")
@ResponseBody
public MappingJacksonValue
queryAll(String callback) {
//查询分类列表
Menumenu = catService.getMenu();
//包装jsonp
MappingJacksonValuejacksonValue = new MappingJacksonValue(menu);
//设置包装的回调方法名
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
[if !supportLists]2.3.1.4 [endif]第四步:测试接口
在浏览器访问。
地址:http://localhost:8081/rest/item/all?callback=category.getDataService
[if !vml]
[endif]
[if !supportLists]2.3.2 [endif]第二部分:在portal工程中调用导航菜单接口
[if !supportLists]2.3.2.1 [endif]第一步:指定请求方式为jsonp
(1)修改lib-v1.js文件,指定导航菜单接口地址。
[if !vml]
[endif]
(2)修改lib-v1.js文件,指定请求方式为jsonp。
[if !vml]
[endif]
[if !supportLists]2.3.2.2 [endif]第二步:测试导航菜单
(1)重启portal工程
(2)访问首页,请求导航菜单
[if !vml]
[endif]
导航菜单开发成功!!!