1.搭建前台系统
1.1.前台系统架构
在互联网系统开发当中,我们一般都是采用了分层的方式来架构系统,即:
(1)门户层(门户系统):网站的入口
i、渲染视图,提供用户访问的页面。
ii、不查询数据库,数据来自对远程服务(接口)的调用。
(2)服务层:基于restful,以接口的形式对外提供公共的服务。
i、连接数据库,返回json格式的数据。
1.1.1.分层架构的好处
(1)、有利于系统的维护和拓展。
(2)、有利于SOA服务治理的基础。
1.2.搭建服务层系统
1.2.1.系统简介
基于RESTful实现。以接口的形式,对外提供公共的服务。(比如购物车、导航菜单、搜索、订单等等)
RESTful是一种接口设计理念,即:
(1)不同的请求方式,对应不同的业务类型:
GET :查询
POST :添加
PUT :更新
DELETE: 删除
(2)返回json格式数据。
1.2.2.技术选择
核心框架:Spring+SpringMVC+Mybatis-plus
数 据 库:MySQL
前端框架:无
1.2.3.配置步骤
思路:
(1)创建项目,导入jar依赖。
(2)整合SSM框架。
1.2.3.1.第一步:创建maven项目(war)模型
注意:(1)项目继承ego-project。
(2)使用maven module创建项目
1.2.3.2.第二步:导入jar依赖
导包说明:
(1)ego-base子工程
(2)Spring核心包
(3)SpringMVC相关包
(4)AOP相关包
(5)JDBC、事物相关包
(6)Mybatis-plus及整合包
(7)JSON依赖包
导入插件:Tomcat插件(开发阶段,启动项目,对外发布接口)
4.0.0
cn.gzsxt.ego
ego-project
1.0
cn.gzsxt.ego
ego-rest
1.0
war
cn.gzsxt.ego
ego-base
1.0
org.springframework
spring-context
org.springframework
spring-jdbc
org.springframework
spring-aspects
org.springframework
spring-webmvc
org.mybatis
mybatis-spring
mysql
mysql-connector-java
com.alibaba
druid
com.fasterxml.jackson.core
jackson-databind
org.apache.tomcat.maven
tomcat7-maven-plugin
8081
/
UTF-8
1.2.3.3.第三步:创建web.xml文件
说明:可以从ego-manager工程中拷贝,修改
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
characterEncodingFilter
/*
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-*.xml
1
dispatcherServlet
/rest/*
1.2.3.4.第四步:整合SSM框架
整合中所需要的配置文件,均可从ego-manager工程中拷贝,修改局部的配置即可。
1.2.3.4.1.Step1:Spring整合SpringMVC
创建spring-mvc.xml文件,做如下配置:
1.2.3.4.2.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.2.3.5.第五步:整合测试
在这里我们使用静态数据(category.json),来模拟导航菜单接口的实现。
(1)拷贝category.json文件到webapp目录下。
(2)更新项目、安装到本地仓库(updata、maven clean、maven install)
(3)启动项目
查看控制台,启动成功!!!
(4)浏览器访问,地址:http://localhost:8081/category.json,整合成功!!!
1.3.搭建门户系统
1.3.1.系统简介
简单来说就是网站的入口,提供用户浏览、下单的操作页面。
门户系统不直接调用数据库,而是通过服务系统提供的接口获取数据。电商、互联网行业开发都是面向服务开发。
1.3.2.技术选择
核心框架:Spring+SpringMVC
数 据 库:无
前端技术:jquery、ajax、css+div、easyui等
1.3.3.配置步骤
思路:
(1)创建项目
(2)框架整合
1.3.3.1.第一步:创建maven项目(war模型)
注意:
(1)继承ego-project工程
(2)使用maven module创建子系统
1.3.3.2.第二步:导入jar依赖
在门户系统中,不直接查询数据库,所以不需要导入数据库相关的jar包。
在门户系统中,用户能够搜索、浏览商品,提交订单等,所以需要添加jsp视图相关依赖。
4.0.0
cn.gzsxt.ego
ego-parent
1.0
cn.gzsxt.ego
ego-portal
1.0
war
cn.gzsxt.ego
ego-base
1.0
jstl
jstl
javax.servlet
servlet-api
provided
javax.servlet
jsp-api
provided
org.springframework
spring-context
org.springframework
spring-webmvc
com.fasterxml.jackson.core
jackson-databind
org.apache.tomcat.maven
tomcat7-maven-plugin
8082
/
UTF-8
1.3.3.3.第三步:创建web.xml文件
可以从ego-rest工程拷贝,修改
index.html
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
characterEncodingFilter
/*
dispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-*.xml
1
dispatcherServlet
*.html
1.3.3.4.第四步:导入jsp页面、静态资源
说明:
(1)静态资源放在/webapp目录
(2)jsp放到/WEB-INF/JSP目录下
1.3.3.5.第五步:Spring整合SpringMVC
从ego-rest工程拷贝,修改部分配置即可。
1.3.3.6.第六步:整合测试
需求:访问门户系统首页。
(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)启动项目
(4)访问首页,地址:http://localhost:8082
前台系统搭建成功!!!
2.首页导航菜单实现
说明:首页导航菜单,是通过异步加载实现的。
好处:只有当展开导航菜单时,才会发送请求,从而节约cpu资源。
2.1.实现流程
需要解决的问题:
(1)在rest系统中发布接口,封装导航菜单成json格式数据。
(2)在portal系统中,远程请求接口(跨域请求)。
2.2.跨越请求
2.2.1.什么是跨域(两个不同系统之间的访问、调用)
(1)域名不同,即两个不同的应用。
(2)域名相同,但是端口不同,即同一个应用中的不同子系统。
2.2.2.Ajax跨域请求的缺陷
在ego-rest系统使用静态数据,模拟Ajax的跨域问题。
2.2.2.1.第一步:在ego-rest中添加category.json文件。(已实现)
2.2.2.2.第二步:在ego-portal中发送ajax请求
(1)创建testJsonp.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Insert title here
(2)修改PageController,新增访问非首页的方法。
@RequestMapping("/{page}")
public String showPage(@PathVariable("page")String page){
return page;
}
2.2.2.3.第三步:测试Ajax跨越
(1)重启启动ego-portal系统,访问testJsonp.jsp
(2)点击按钮,发送异步请求
测试发现,Ajax跨越请求失败了。
2.2.3.解决方案:jsonp跨域
在前面的测试中,我们发现Ajax跨越请求时,json数据被浏览器禁用了。
原因:浏览器禁止远程加载Json数据。(浏览器安全机制)
如何解决呢?
答:使用Jsonp方式。
2.2.3.1.Jsonp原理
Jsonp实现的前提:
浏览器允许跨越加载同源数据。
即在JavaScript脚本中发送请求,就可以远程加载js格式数据。
请求原理:
(1)异步请求的时候,加上一个名为callback的回调函数
(2)在接口中,将返回的json格式数据,伪装成js脚本格式。
(3)得到js格式数据后,提取里面的json数据。
2.2.3.2.测试Jsonp
(1)修改testJsonp.jsp,指定异步请求为jsonp方式。
(2)在ego-rest工程中,修改category.json文件,将返回数据包装成js脚本。
(3)再次发送ajax异步请求,使用jsonp方式
结论:
(1)jsonp是ajax技术中的一种异步请求方式。
(2)jsonp能实现跨越请求。
(3)jsonp跨越时,需要指定一个回调函数,并使用该函数将返回的数据伪装成js脚本。
(4)获取返回的js脚本后,jsonp自动提取其中的json数据。
2.3.首页导航菜单实现
思路:
(1)在rest工程中,开发接口,返回js格式数据。(参考category.json)
(2)在portal工程中,修改jsonp请求路径。请求rest接口。
2.3.1.第一部分:在rest工程中开发导航菜单接口
2.3.1.1.第一步:定义导航菜单POJO
导航菜单结构分析。(使用JsonViewer工具查看category.json)
结论:
(1)需要定义两个POJO:菜单POJO、父目录节点POJO
(2)导航菜单的数据,是一次加载出来的。
创建菜单Menu类。(ego-base中创建)
package cn.gzsxt.base.pojo;
import java.util.List;
/**
* 自定义导航菜单
* @author ccnulyq
*
*/
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;
/**
* 自定义目录节点结构
* @author ccnulyq
*
*/
public class MenuNode {
private String u; //目录的链接
private String n; //目录的名称
private List> i; //当请目录的子目录
public MenuNode() {
super();
}
// 补全get、set方法
}
(3)重新编译ego-base工程,安装到本地仓库。(maven clean、maven install)
2.3.1.2.第二步:创建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() {
Menu menu = new Menu();
//从返回值Menu的形式上来看,就是把一级目录查询出来即可。因此定义一个查询方法,通过parent_id=0查询一级目录
List nodes = getNodesByParantId(0L);
menu.setData(nodes);
return menu;
}
//根据父目录的id,查询子目录
private List getNodesByParantId(long parentId) {
Map params = new HashMap<>();
params.put("parent_id", parentId);
List selectByMap = itemCatMapper.selectByMap(params);
List nodes = new ArrayList<>();
MenuNode node = 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;
}
}
2.3.1.3.第三步:创建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){
Menu menu = catService.initMenu();
String jsonMenu = JsonUtils.objectToJson(menu);
String jsMenu = callback+"("+jsonMenu+")";
return jsMenu;
}
}
(2)方式二:使用MappingJacksonValue对象封装
//使用MappingJacksonValue对象包装返回结果,并设置jsonp的回调方法
@RequestMapping("/item/all")
@ResponseBody
public MappingJacksonValue queryAll(String callback) {
//查询分类列表
Menu menu = catService.getMenu();
//包装jsonp
MappingJacksonValue jacksonValue = new MappingJacksonValue(menu);
//设置包装的回调方法名
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
2.3.1.4.第四步:测试接口
在浏览器访问。
地址:http://localhost:8081/rest/item/all?callback=category.getDataService
2.3.2.第二部分:在portal工程中调用导航菜单接口
2.3.2.1.第一步:指定请求方式为jsonp
(1)修改lib-v1.js文件,指定导航菜单接口地址。
(2)修改lib-v1.js文件,指定请求方式为jsonp。
2.3.2.2.第二步:测试导航菜单
(1)重启portal工程
(2)访问首页,请求导航菜单
导航菜单开发成功!!!
3.CMS系统
3.1.概念
CMS系统即为内容管理系统。(Content Management System)
所谓的内容,就是出现在网页中的图片、文字、链接等。CMS系统就是用来维护网页中的内容的,实现网页中的内容动态、可变。
比如广告位的投放,秒杀栏、排行榜实时更新等,都需要通过CMS系统来实现。
3.2.CMS系统实现
3.2.1.思路
(1)、将网页中的内容分类
按照网页的特性分类,然后将每一类网页划分成一个一个独立的区域。
(2)在每一个内容分类下管理、维护各自的内容列表。
3.2.2.数据库表关系
CMS系统主要涉及两种表:
(1)内容分类表:tb_content_category(作用:定位)
(2)内容表:tb_content
表之间的对应关系为1-N
3.2.3.内容分类实现
3.2.3.1.需求
在后台管理页面,点击内容分类管理菜单,初始化内容分类树结构。该树结构可以添加、修改、删除节点。
3.2.3.2.思路
(1)初始化内容分类导航树。(这里使用easyui-tree)
(2)对异步树进行维护。(添加节点、删除节点、更新节点)
3.2.3.3.第一部分:初始化内容分类导航树
3.2.3.3.1.第一步:初始化easyui异步树插件
3.2.3.3.2.第二步:确定代码结构
|
Controller
|
表现层,负责交互、绑定参数、响应视图
|
|
Service
|
业务层,负责业务逻辑实现(封装树结构)
|
|
Mapper
|
持久层,逆向工程生成,不需要开发。
|
3.2.3.3.3.第三步:确定请求响应格式
|
请求路径
|
/content/category/list
|
|
请求方式
|
GET请求
|
|
请求参数
|
id=nodeId(首次加载生成一级目录时,默认id=0)
|
|
响应格式
|
List (id,text,state:open|closed)
|
3.2.3.3.4.第四步:创建ContentCategory类
在公共工程ego-base中创建。
package cn.gzsxt.base.pojo;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
@TableName(value="tb_content_category")
public class ContentCategory {
@TableId(value="id",type=IdType.AUTO)
private Long id;
@TableField(value="parent_id")
private Long parentId;
private String name;
private int status;
@TableField(value="sort_order")
private int sortOrdert;
@TableField(value="is_parent")
private byte isParent;
private Date created;
private Date updated;
public ContentCategory() {
super();
}
// 补全get、set方法
}
3.2.3.3.5.第五步:创建ContentCategoryMapper接口
在公共工程ego-base中创建。
package cn.gzsxt.base.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import cn.gzsxt.base.pojo.ContentCategory;
public interface ContentCategoryMapper extends BaseMapper{
}
3.2.3.3.6.第六步:创建ContentCategoryService接口及其实现类
package cn.gzsxt.manager.service.impl;
import java.util.ArrayList;
import java.util.Date;
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 org.springframework.transaction.annotation.Transactional;
import cn.gzsxt.base.mapper.ContentCategoryMapper;
import cn.gzsxt.base.pojo.ContentCategory;
import cn.gzsxt.base.vo.EUTreeNode;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentCategoryService;
@Service
public class ContentCategoryServiceImpl implements ContentCategoryService{
@Autowired
private ContentCategoryMapper mapper;
@Override
public List selectByParentId(Long parentId) {
//定义返回值
List nodes = new ArrayList<>();
//封装查询条件,执行查询
Map columnMap = new HashMap<>();
columnMap.put("parent_id", parentId);
List selectByMap = mapper.selectByMap(columnMap);
EUTreeNode node = null;
for (ContentCategory c : selectByMap) {
node = new EUTreeNode();
node.setId(c.getId());
node.setText(c.getName());
//三目运算符
node.setState(1==c.getIsParent()?"closed":"open");
nodes.add(node);
}
return nodes;
}
}
3.2.3.3.7.第七步:创建ContentCategoryController类
package cn.gzsxt.manager.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.vo.EUTreeNode;
import cn.gzsxt.manager.service.ContentCategoryService;
@Controller
@RequestMapping("/content/category")
public class ContentCategoryController {
@Autowired
private ContentCategoryService service;
@RequestMapping(value="/list",method=RequestMethod.GET)
@ResponseBody
public List selectByParentId(@RequestParam(name="id",defaultValue="0")Long parentId){
return service.selectByParentId(parentId);
}
}
3.2.3.3.8.第八步:测试
(1)重新编译ego-manager工程。(clean、install)
(2)重新启动ego-manager。
(3)访问内容分类管理
3.2.3.4.第二部分:添加内容分类节点
3.2.3.4.1.第一步:前端js实现
3.2.3.4.2.第二步:确定代码结构
|
Controller
|
视图层,接收参数,将新增加的节点响应出去
|
|
Service
|
业务层,新增节点、更新父节点
|
|
Mapper
|
持久层,逆向工程生成,不需要开发。
|
3.2.3.4.3.第三步:确定请求响应格式
|
请求路径
|
/content/category/create
|
|
请求方式
|
POST
|
|
请求参数
|
parentId:node.parentId, name:node.text
|
|
响应格式
|
{status:200,data:node} (EgoResult类型)
|
3.2.3.4.4.第四步:修改ContentCategoryService及其实现类,新增save方法
注意:先在ContentCategoryService接口中定义save方法
@Transactional(rollbackFor=Exception.class)
@Override
public EgoResult save(Long parentId, String name) {
ContentCategory temp = new ContentCategory();
temp.setParentId(parentId);
temp.setName(name);
temp.setIsParent((byte) 0);
temp.setSortOrdert(1);
temp.setCreated(new Date());
temp.setStatus(1);
temp.setUpdated(temp.getCreated());
//mybatis-plus保存对象的时候,已经实现了对象的id自动同步。前提:数据库id是自增。
mapper.insert(temp);
/*
* 判断当前添加节点的父节点是否是目录节点。
*
* 如果不是,则要修改其状态为父目录结构
*/
ContentCategory category = mapper.selectById(parentId);
if(0==category.getIsParent()){
category.setIsParent((byte) 1);
mapper.updateById(category);
}
return EgoResult.ok(temp);
}
3.2.3.4.5.第五步:修改ContentCategoryController类,定义新增内容分类接口
@RequestMapping(value="/create",method=RequestMethod.POST)
@ResponseBody
public EgoResult create(Long parentId,String name){
EgoResult result = catService.save(name, parentId);
return result;
}
3.2.3.4.6.第六步:测试
(1)重新编译ego-base工程。(clean、install)
(2)重新启动ego-manager。
(3)新增内容分类节点。
3.2.3.5.第三部分:更新内容分类
3.2.3.5.1.第一步:前端js实现
3.2.3.5.2.第二步:确定请求响应格式
|
请求路径
|
/content/category/updata
|
|
请求方式
|
POST
|
|
请求参数
|
id:node.id, name:node.text
|
|
响应格式
|
{status:200,data:node} (EgoResult类型)
|
3.2.3.5.3.第三步:修改ContentCategoryService及其接口,新增update方法。
注意:先在service接口中定义方法。
@Override
public EgoResult updateNode(String name, Long id) {
ContentCategory contentCat = new ContentCategory();
contentCat.setName(name);
contentCat.setId(id);
contentCatMapper.updateById(contentCat);
return EgoResult.ok();
}
3.2.3.5.4.第四步:修改ContentController类,定义更新的接口
@RequestMapping(value="/update",method=RequestMethod.POST)
@ResponseBody
public EgoResult updateNode(Long id,String name){
EgoResult result = catService.updateNode(name, id);
return result;
}
3.2.3.5.5.第五步:测试
(1)重新编译ego-manager工程。(clean、install)
(2)重新启动ego-manager。
(3)更新内容分类节点。
3.2.3.6.第四部分:删除内容分类
3.2.3.6.1.第一步:前端js实现
3.2.3.6.2.第二步:确定请求响应格式
|
请求路径
|
/content/category/delete
|
|
请求方式
|
POST
|
|
请求参数
|
id:node.id, parentId:node.parentId
|
|
响应格式
|
{status:200,data:node} (EgoResult类型)
|
3.2.3.6.3.第三步:修改ContentCategoryService及其实现类,新增delete方法
@Transactional
@Override
public EgoResult deleteNode(Long id, Long parentId) {
// 第一步:判断parent_id是否有值
if (parentId == null) {
parentId = contentCategoryMapper.selectById(id).getParentId();
}
// 第二步:判断该节点是否是它的父节点的最后一个节点。如果是。那么需要将它的父节点修改为叶节点
EntityWrapper wrapper = new EntityWrapper<>();
wrapper.eq("parent_id", parentId);
//过滤只查询有效的状态
wrapper.eq("status", 1);
List categories = contentCategoryMapper.selectList(wrapper);
if (categories.size() == 1) {
ContentCategory parentCategory = contentCategoryMapper.selectById(parentId);
// 父节点修改为叶节点
parentCategory.setIsParent((byte) 0);
parentCategory.setUpdated(new Date());
contentCategoryMapper.updateById(parentCategory);
}
// 第三步:修改当前节点的状态值,修改为删除状态
ContentCategory category = contentCategoryMapper.selectById(id);
category.setStatus(2);
category.setUpdated(new Date());
contentCategoryMapper.updateById(category);
return EgoResult.ok();
}
3.2.3.6.4.第四步:修改ContentCategoryController类,定义delete接口
@RequestMapping(value="/delete",method=RequestMethod.POST)
@ResponseBody
public EgoResult deleteNode(Long id,Long parentId){
EgoResult result = catService.deleteNode(id, parentId);
return result;
}
3.2.4.内容管理实现
3.2.4.1.需求
根据内容分类id,查询数据库表tb_content,获取内容列表。
内容分类树使用easyui-tree组件,内容列表使用easyui-datagrid组件。
3.2.4.2.思路
(1)实现内容列表查询。
(2)在内容分类节点下,维护内容列表。
3.2.4.3.第一部分:内容列表实现
3.2.4.3.1.第一步:加载easyui-datagrid插件
(1)初始化分类导航树(后台java已实现,见2.2.1.3.2章节)
(2)选中内容分类节点
(3)查询该节点下的内容列表
3.2.4.3.2.第二步:确定代码结构
|
Controller
|
获取分类ID,分页信息,响应列表数据
|
|
Service
|
分页查询逻辑
|
|
Mapper
|
逆向工程生成,不需要开发
|
3.2.4.3.3.第三步:确定请求响应结构
|
请求路径
|
/content/query/list
|
|
请求方式
|
GET
|
|
请求参数
|
{categoryId:0 , page:1 , rows:20}
|
|
响应格式
|
{total:20,rows:dataList} (参见ego-base中的EUDataGridRestult类)
|
3.2.4.3.4.第四步:创建Content类
在ego-base工程中创建!
package cn.gzsxt.base.pojo;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
@TableName(value="tb_content")
public class Content {
@TableId(value="id",type=IdType.AUTO)
private Long id;
@TableField(value="category_id")
private long categoryId;
private String title;
@TableField(value="sub_title")
private String subTitle;
@TableField(value="title_desc")
private String titleDesc;
private String url;
private String pic;
private String pic2;
private String content;
private Date created;
private Date updated;
public Content() {
super();
}
// 补全get、set方法
}
3.2.4.3.5.第五步:创建ContentMapper接口
在ego-base工程中创建!
package cn.gzsxt.base.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import cn.gzsxt.base.pojo.Content;
public interface ContentMapper extends BaseMapper{
}
3.2.4.3.6.第六步:创建ContentService接口及其实现类
package cn.gzsxt.manager.service.impl;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import cn.gzsxt.base.mapper.ContentMapper;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.vo.EUDataGridResult;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService{
@Autowired
private ContentMapper mapper;
@Override
public EUDataGridResult listByCatIdAndPage(Long categoryId, int page, int rows) {
EUDataGridResult result = new EUDataGridResult();
/*
* offset 偏移量 即limit函数中的start
* limit 容量
*/
RowBounds rowBounds = new RowBounds((page-1)*rows, rows);
EntityWrapper wrapper = new EntityWrapper<>();
wrapper.eq("category_id", categoryId);
List selectPage = mapper.selectPage(rowBounds, wrapper);
Integer count = mapper.selectCount(wrapper);
result.setTotal(count);
result.setRows(selectPage);
return result;
}
}
3.2.4.3.7.第七步:创建ContentController类
package cn.gzsxt.manager.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.vo.EUDataGridResult;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentService;
@Controller
@RequestMapping("/content")
public class ContentController {
@Autowired
private ContentService service;
@RequestMapping(value="/query/list")
@ResponseBody
public EUDataGridResult selectByCatIdAndPage(Long categoryId,Integer page,Integer rows){
EUDataGridResult result = service.listByCatIdAndPage(categoryId, page, rows);
return result;
}
}
3.2.4.3.8.第八步:测试
(1)重新编译ego-manager工程。(clean、install)
(2)重新启动ego-manager。
(3)查看内容列表。成功!!!
3.2.4.4.第二部分:新增内容
3.2.4.4.1.第一步:前端js实现
3.2.4.4.2.第二步:确定代码结构
|
Controller
|
接收表单数据,响应保存结果
|
|
Service
|
保存逻辑实现
|
|
Mapper
|
逆向工程生成
|
3.2.4.4.3.第三步:确定请求响应格式
|
请求路径
|
/content/save
|
|
请求方式
|
POST
|
|
请求参数
|
Content类
|
|
响应格式
|
{status:200} (EgoResult类型)
|
3.2.4.4.4.第四步:修改ContentService接口及其实现类,新增save方法
@Override
public EgoResult addContent(Content content) throws Exception {
//把图片信息保存至数据库
content.setCreated(new Date());
content.setUpdated(new Date());
//把内容信息添加到数据库
mapper.insert(content);
return EgoResult.ok();
}
3.2.4.4.5.第五步:修改ContentController类,定义save接口
@RequestMapping("/save")
@ResponseBody
public EgoResult addContent(Content content) throws Exception {
EgoResult result = service.addContent(content);
return result;
}
3.2.4.5.第三部分:更新内容
3.2.4.5.1.第一步:前端js实现
3.2.4.5.2.第二步:确定请求响应格式
|
请求路径
|
/content/edit
|
|
请求方式
|
POST
|
|
请求参数
|
Content类
|
|
响应格式
|
{status:200} (EgoResult类型)
|
3.2.4.5.3.第三步:修改ContentService接口及其实现类,新增update方法
@Override
public EgoResult update(Content content) {
mapper.updateById(content);
return EgoResult.ok();
}
3.2.4.5.4.第四步:修改ContentController类,新增update接口
@RequestMapping("/edit")
@ResponseBody
public EgoResult update(Content Content){
EgoResult result = service.update(Content);
return result;
}
3.2.4.6.第四部分:删除内容
3.2.4.6.1.第一步:前端js实现
获取所有要删除的内容的id,封装到数组中。
3.2.4.6.2.第二步:确定请求响应格式
|
请求路径
|
/content/delete
|
|
请求方式
|
POST
|
|
请求参数
|
Ids[]:{1,2,3} 数组类型
|
|
响应格式
|
{status:200} (EgoResult类型)
|
3.2.4.6.3.第三步:修改ContentService接口及其实现类,新增delete方法
@Override
public EgoResult delete(Integer[] ids) {
List idss = Arrays.asList(ids);
mapper.deleteBatchIds(idss);
return EgoResult.ok();
}
3.2.4.6.4.第四步:修改ContentController类,新增delete接口
@RequestMapping("/delete")
@ResponseBody
public EgoResult delete(Integer[] ids){
EgoResult result = service.delete(ids);
return result;
}
4.首页大广告实现
4.1.需求
访问门户系统首页,在大广位区域展示大广告位对应的内容。
4.2.实现流程
(1)、在CMS系统中维护大广告位的内容。
(2)、在REST系统中查询大广告位的内容列表,以接口的形式对外提供服务。
(3)、在portal门户系统中远程访问REST系统。
11.第一部分:REST系统接口实现
需求:
根据内容分类id,查询tb_content表,获得大广告位内容列表。
4.3.1.第一步:确定代码结构
|
Controller
|
定义接口规则(请求路径、请求方式、参数、响应值类型)
|
|
Service
|
定义查询逻辑
|
|
Mapper
|
查询数据库
|
4.3.2.第二步:定义接口规则
|
请求路径
|
/rest/content/category/{cid}
|
|
请求方式
|
GET
|
|
请求参数
|
/{cid} 路径变量
|
|
响应类型
|
EgoResult
|
|
示例
|
demo
|
4.3.3.第三步:创建ContentService接口及其实现类
package cn.gzsxt.rest.service.impl;
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.ContentMapper;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.utils.JsonUtils;
import cn.gzsxt.rest.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService{
@Autowired
private ContentMapper mapper;
@Override
public EgoResult getContentByCatId(Long catId) {
Map columnMap = new HashMap<>();
columnMap.put("category_id", catId);
List list = mapper.selectByMap(columnMap);
return EgoResult.ok(list);
}
}
4.3.4.第四步:创建ContentController类
@RestController
@RequestMapping("/content")
public class ContentController {
@Autowired
private ContentService contentService;
@RequestMapping("/category/{cid}")
public EgoResult getContentList(@PathVariable Long cid) {
EgoResult result = contentService.getContentByCatId(cid);
return result;
}
}
4.4.第二部分:远程接口调用方式HttpClient
问题:现在我们已经开发好了接口了,那该如何调用这个接口呢?
答:使用Httpclient客户端。
4.4.1.Httpclient简介
4.4.1.1.什么是httpclient
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
下载地址:http://hc.apache.org/
4.4.1.2.httpclient作用
在java代码中,发送Http请求。通常用来实现远程接口调用。
4.4.2.HttpClient测试
说明:在ego-base中测试
在ego-base工程中添加httpclient的pom依赖。
org.apache.httpcomponents
httpclient
4.4.2.1.执行GET请求
public static void doGet(){
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet("http://www.oschina.net/");
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpclient.execute(httpGet);
System.out.println(response.getStatusLine());
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println("内容长度:" + content.length());
}
}catch(Exception e){
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
4.4.2.2.执行GET带参数
public static void doGetParam(){
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
// 定义请求的参数
URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "数据库").build();
System.out.println(uri);
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
}catch(Exception e){
e.printStackTrace();
}finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.4.2.3.执行post请求
public static void doPost(){
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
// 创建http POST请求
HttpPost httpPost = new HttpPost("http://www.oschina.net/");
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
}catch(Exception e){
e.printStackTrace();
}finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.4.2.4.执行post带参数
public static void doPostParam() throws Exception{
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
// 创建http POST请求
HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
// 设置2个post参数,一个是scope、一个是q
List parameters = new ArrayList();
parameters.add(new BasicNameValuePair("scope", "project"));
parameters.add(new BasicNameValuePair("q", "java"));
// 构造一个form表单式的实体
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
// 将请求实体设置到httpPost对象中
httpPost.setEntity(formEntity);
CloseableHttpResponse response = null;
try {
// 执行请求
response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
httpclient.close();
}
}