1 商城首页
1.1 工程搭建
创建taotao-portal-web工程,web.xml拦截<url-pattern>*.html</url-pattern>
,css/js等文件放到webapp下将不被拦截,因此不需要在springmvc.xml中配拦截器
1.2 首页展示
一般不直接展示,通过controller forward到jsp上。web.xml中配置首页<welcome-file>index.html</welcome-file>
,如果只访问域名不加后缀,系统找不到该文件,将被拦截器拦截
@Controller
public class IndexController {
@RequestMapping("/index")
public String showIndex(Model model) {
return "index";
}
}
2 CMS系统实现
2.1 项目分析
内容信息从数据库中获得,需要一个内容分类表和一个内容表,内容分类表存储树形结构的数据,内容表存储图片/链接/标题/价格/大文本类型。
创建一个内容服务系统
Taotao-content:聚合工程打包方式pom
|--taotao-content-interface jar
|--taotao-content-Service war
2.2 内容分类管理
2.2.1 内容分类展示
功能分析
请求的url:/content/category/list
请求的参数:id,当前节点的id(第一次请求是没有参数,需要给默认值“0”)
响应数据:List<EasyUITreeNode>(@ResponseBody)
Json数据。
[{id:1,text:节点名称,state:open(closed)},
{id:2,text:节点名称2,state:open(closed)},
{id:3,text:节点名称3,state:open(closed)}]
<div>
<ul id="contentCategory" class="easyui-tree"></ul>
</div>
...
<script type="text/javascript">
$(function(){
$("#contentCategory").tree({
url : '/content/category/list',
animate: true,
method : "GET",
onContextMenu: function(e,node){
e.preventDefault();
$(this).tree('select',node.target);
$('#contentCategoryMenu').menu('show',{
left: e.pageX,
top: e.pageY
});
},
业务逻辑:
1、取查询参数id,parentId
2、根据parentId查询tb_content_category,查询子节点列表。
3、得到List<TbContentCategory>
4、把列表转换成List<EasyUITreeNode>
DAO层
使用逆向工程
在common项目中创建返回结构的POJO EasyUITreeNode
public class EasyUITreeNode implements Serializable{
private long id;
private String text;
private String state;
public long getId() {
return id;
}
...
}
Service层
创建ContentCategoryServiceImpl,参数:long parentId,返回值:List<EasyUITreeNode>
@Service
public class ContentCategoryServiceImpl implements ContentCategoryService {
@Autowired
private TbContentCategoryMapper contentCategoryMapper;
@Override
public List<EasyUITreeNode> getContentCategoryList(long parentId) {
// 1、取查询参数id,parentId
// 2、根据parentId查询tb_content_category,查询子节点列表。
TbContentCategoryExample example = new TbContentCategoryExample();
//设置查询条件
Criteria criteria = example.createCriteria();
criteria.andParentIdEqualTo(parentId);
//执行查询
// 3、得到List<TbContentCategory>
List<TbContentCategory> list = contentCategoryMapper.selectByExample(example);
// 4、把列表转换成List<EasyUITreeNode>ub
List<EasyUITreeNode> resultList = new ArrayList<>();
for (TbContentCategory tbContentCategory : list) {
EasyUITreeNode node = new EasyUITreeNode();
node.setId(tbContentCategory.getId());
node.setText(tbContentCategory.getName());
node.setState(tbContentCategory.getIsParent()?"closed":"open");
//添加到列表
resultList.add(node);
}
return resultList;
}
}
使用dubbo发布服务,注意端口要与common-service项目区分开
<!-- 配置包扫描器,扫描所有带@Service注解的类 -->
<context:component-scan base-package="com.taotao.content.service"/>
<!-- 发布dubbo服务 -->
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="taotao-content" />
<!-- 注册中心的地址 -->
<dubbo:registry protocol="zookeeper" address="192.168.25.175:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20881" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.taotao.content.service.ContentCategoryService" ref="contentCategoryServiceImpl" timeout="300000"/>
表现层
引用服务:taotao-manager-web项目添加依赖taotao-content-interface,在springmvc.xml文件中,添加服务引用<dubbo:reference interface="com.taotao.content.service.ContentCategoryService" id="contentCategoryService" />
创建ContentCategoryController
@Controller
@RequestMapping("/content/category")
public class ContentCategoryController {
@Autowired
private ContentCategoryService contentCategoryService;
@RequestMapping("/list")
@ResponseBody
public List<EasyUITreeNode> getContentCatList(
@RequestParam(value="id", defaultValue="0") Long parentId) {
List<EasyUITreeNode> list = contentCategoryService.getContentCategoryList(parentId);
return list;
}
}
2.2.2 新增节点
功能分析
请求的url:/content/category/list
请求的参数:parentId name
响应的结果: json数据,TaotaoResult,其中包含一个对象,对象有id属性,新生产的内容分类id
<div>
<ul id="contentCategory" class="easyui-tree">
</ul>
</div>
<div id="contentCategoryMenu" class="easyui-menu" style="width:120px;" data-options="onClick:menuHandler"> //添加onClick事件
<div data-options="iconCls:'icon-add',name:'add'">添加</div> //右击菜单内容
<div data-options="iconCls:'icon-remove',name:'rename'">重命名</div>
<div class="menu-sep"></div>
<div data-options="iconCls:'icon-remove',name:'delete'">删除</div>
</div>
<script type="text/javascript">
$(function(){
$("#contentCategory").tree({
url : '/content/category/list',
animate: true,
method : "GET",
onContextMenu: function(e,node){ //右击展示菜单事件,传入事件及该节点
e.preventDefault();
$(this).tree('select',node.target); //当前节点变成选中状态
$('#contentCategoryMenu').menu('show',{ //菜单的位置
left: e.pageX,
top: e.pageY
});
},
onAfterEdit : function(node){ //编辑结束触发事件
var _tree = $(this);
if(node.id == 0){
// 新增节点id为0
$.post("/content/category/create",{parentId:node.parentId,name:node.text},function(data){
if(data.status == 200){ //返回结果中包含status
_tree.tree("update",{
target : node.target,
id : data.data.id
});
}else{
$.messager.alert('提示','创建'+node.text+' 分类失败!');
}
});
}else{
$.post("/content/category/update",{id:node.id,name:node.text});
}
}
});
});
function menuHandler(item){ //item表示选中哪一项
var tree = $("#contentCategory");
var node = tree.tree("getSelected");
if(item.name === "add"){
tree.tree('append', { //{}中内容为新节点定义
parent: (node?node.target:null),
data: [{
text: '新建分类',
id : 0,
parentId : node.id
}]
});
var _node = tree.tree('find',0); //找id为0的节点
tree.tree("select",_node.target).tree('beginEdit',_node.target); //选中节点,变成可编辑状态
}else if(item.name === "rename"){
tree.tree('beginEdit',node.target);
}else if(item.name === "delete"){
$.messager.confirm('确认','确定删除名为 '+node.text+' 的分类吗?',function(r){
if(r){
$.post("/content/category/delete/",{parentId:node.parentId,id:node.id},function(){
tree.tree("remove",node.target);
});
}
});
}
}
</script>
业务逻辑:
1、接收两个参数:parentId、name
2、向tb_content_category表中插入数据。
a) 创建一个TbContentCategory对象
b) 补全TbContentCategory对象的属性
c) 向tb_content_category表中插入数据
3、判断父节点的isparent是否为true,不是true需要改为true。
4、需要主键返回。
5、返回TaotaoResult,其中包装TbContentCategory对象
DAO层
可以使用逆向工程。需要添加主键返回,在TbContentCategoryMapper.xml中,在inser及insertSelctive中添加<selectKey>
标签
<insert id="insert" parameterType="com.taotao.pojo.TbContentCategory" >
<selectKey keyProperty="id" resultType="long" order="AFTER">
SELECT LAST_INSERT_ID();
</selectKey>
Service层
ContentCategoryServiceImpl类添加addContentCategory方法,参数:parentId/name,返回值:TaotaoResult,其中包装TbContentCategory对象
@Override
public TaotaoResult addContentCategory(Long parentId, String name) {
//创建一个pojo对象
TbContentCategory contentCategory = new TbContentCategory();
//补全对象的属性
contentCategory.setParentId(parentId);
contentCategory.setName(name);
//状态。可选值:1(正常),2(删除)
contentCategory.setStatus(1);
//排序,默认为1
contentCategory.setSortOrder(1);
contentCategory.setIsParent(false);
contentCategory.setCreated(new Date());
contentCategory.setUpdated(new Date());
//插入到数据库
contentCategoryMapper.insert(contentCategory);
//判断父节点的状态
TbContentCategory parent = contentCategoryMapper.selectByPrimaryKey(parentId);
if (!parent.getIsParent()) {
//如果父节点为叶子节点应该改为父节点
parent.setIsParent(true);
//更新父节点
contentCategoryMapper.updateByPrimaryKey(parent);
}
//返回结果
return TaotaoResult.ok(contentCategory);
}
表现层
请求的url:/content/category/create
请求的参数: parentId/name
响应的结果:json数据,TaotaoResult
ContentCategoryController类添加addContentCategory方法
@RequestMapping("/content/category/create")
@ResponseBody
public TaotaoResult addContentCategory(Long parentId, String name) {
TaotaoResult result = contentCategoryService.addContentCategory(parentId, name);
return result;
}
2.2.3 新增内容
功能分析
提交表单请求的url:/content/save
参数:表单的数据。使用pojo接收TbContent
返回值:TaotaoResult(json数据)
业务逻辑:
1、把TbContent对象属性补全。
2、向tb_content表中插入数据。
3、返回TaotaoResult
//content.jsp中,指定工具栏事件 toolbar:contentListToolbar
...
<div data-options="region:'center'" style="padding:5px">
<table class="easyui-datagrid" id="contentList" data-options="toolbar:contentListToolbar,singleSelect:false,collapsible:true,pagination:true,method:'get',pageSize:20,url:'/content/query/list',queryParams:{categoryId:0}">
<thead>
<tr>
<th data-options="field:'id',width:30">ID</th>
...
var contentListToolbar = [{
text:'新增',
iconCls:'icon-add',
handler:function(){
var node = $("#contentCategoryTree").tree("getSelected");
if(!node || !$("#contentCategoryTree").tree("isLeaf",node.target)){
$.messager.alert('提示','新增内容必须选择一个内容分类!');
return ;
}
TT.createWindow({
url : "/content-add"
});
}
},{
text:'编辑',
iconCls:'icon-edit',
handler:function(){
...
//content-add.jsp中提交表单
var contentAddPage = {
submitForm : function (){
if(!$('#contentAddForm').form('validate')){
$.messager.alert('提示','表单还未填写完成!');
return ;
}
contentAddEditor.sync();
$.post("/content/save",$("#contentAddForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','新增内容成功!');
$("#contentList").datagrid("reload");
TT.closeCurrentWindow();
}
});
},
DAO层
使用逆向工程
Service层
创建ContentServiceImpl类,添加addContent方法,参数:TbContent,返回值:TaotaoResult
@Service
public class ContentServiceImpl implements ContentService {
@Autowired
private TbContentMapper contentMapper;
@Override
public TaotaoResult addContent(TbContent content) {
//补全属性
content.setCreated(new Date());
content.setUpdated(new Date());
//插入数据
contentMapper.insert(content);
return TaotaoResult.ok();
}
}
发布服务<dubbo:service interface="com.taotao.content.service.ContentService" ref="contentServiceImpl" timeout="300000"/>
表现层
引用服务<dubbo:reference interface="com.taotao.content.service.ContentService" id="contentService" />
创建ContentController
@Controller
public class ContentController {
@Autowired
private ContentService contentService;
@RequestMapping("/content/save")
@ResponseBody
public TaotaoResult addContent(TbContent content) {
TaotaoResult result = contentService.addContent(content);
return result;
}
}
2.2.4 首页轮播图展示
功能分析
只需要动态生成一个json数据,轮播图就可以动态展示,Json数据格式:
[
{
"srcB": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg",
"height": 240,
"alt": "",
"width": 670,
"src": "http://image.taotao.com/images/2015/03/03/2015030304360302109345.jpg",
"widthB": 550,
"href": "http://sale.jd.com/act/e0FMkuDhJz35CNt.html?cpdad=1DLSUE",
"heightB": 240
}
]
DAO层
从tb_content表中取数据,根据内容分类id查询列表。可以使用逆向工程。
web项目创建一个pojo转换成页面需要的json数据格式
public class Ad1Node {
private String srcB;
private String height;
private String alt;
private String width;
private String src;
private String widthB;
private String href;
private String heightB;
}
Service层
ContentServiceImpl类添加getContentByCid方法,参数:long categoryId,返回值:List<TbContent>。
@Override
public List<TbContent> getContentList(long cid) {
//根据cid查询内容列表
TbContentExample example = new TbContentExample();
//设置查询条件
Criteria criteria = example.createCriteria();
criteria.andCategoryIdEqualTo(cid);
//执行查询
List<TbContent> list = contentMapper.selectByExample(example);
return list;
}
表现层
Taotao-portal-web中实现,引用服务<dubbo:reference interface="com.taotao.content.service.ContentService" id="contentService" />
在resource.properties文件中添加内容
AD1_CATEGORY_ID=89
AD1_WIDTH=670
AD1_WIDTH_B=550
AD1_HEIGHT=240
AD1_HEIGHT_B=240
在首页展示之前,对数据进行处理,然后展示首页,需要在IndexController中实现。
@Controller
public class IndexController {
@Autowired
private ContentService contentService;
@Value("${AD1_CID}")
private Long AD1_CID;
@Value("${AD1_HEIGHT}")
private Integer AD1_HEIGHT;
@Value("${AD1_WIDTH}")
private Integer AD1_WIDTH;
@Value("${AD1_HEIGHT_B}")
private Integer AD1_HEIGHT_B;
@Value("${AD1_WIDTH_B}")
private Integer AD1_WIDTH_B;
@RequestMapping("/index")
public String showIndex(Model model) {
//取轮播图的内容信息
List<TbContent> contentList = contentService.getContentList(AD1_CID);
//转换成Ad1NodeList
List<Ad1Node> ad1List = new ArrayList<>();
for (TbContent tbContent : contentList) {
Ad1Node node = new Ad1Node();
node.setAlt(tbContent.getTitle());
node.setHeight(AD1_HEIGHT);
node.setHeightB(AD1_HEIGHT_B);
node.setWidth(AD1_WIDTH);
node.setWidthB(AD1_WIDTH_B);
node.setHref(tbContent.getUrl());
node.setSrc(tbContent.getPic());
node.setSrcB(tbContent.getPic2());
//添加到列表
ad1List.add(node);
}
//把数据传递给页面。
model.addAttribute("ad1", JsonUtils.objectToJson(ad1List));
return "index";
}
}
网友评论