1. 今日大纲

  1. 实现首页的大广告位功能
  2. 实现内容管理系统
    1. 首页的大广告

      1. 什么是大广告

JS效果:

  1. 点击下面的序号选择查询哪个广告
  2. 自动切换
  3. 点击图片查询具体的页面

以上是由前端团队来开发。

  1. 数据结构

说明:必须提供6条数据,才能显示效果。

  1. 如何实现?

方案一:

  1. 在后台系统中创建一张表,存储大广告位的广告数据
  2. 在后台系统中对该表进行CRUD
  3. 后台系统对外提供接口服务
  4. 前台系统调用后台系统的提供的接口服务,即可获取到数据
  5. 前台系统获取到数据后,封装成前端所需要的数据结构,功能即可实现

方案二:

  1. 将首页显示的广告都抽象的看作是内容
  2. 在后台系统中创建一张内容表
  3. 创建一个内容分类表用于区分内容的分类
  4. 后台系统对内容表以及分类表进行CRUD
  5. 对外提供接口服务
  6. 前端系统通过接口获取数据,进行封装,即可实现
  1. 内容管理系统(CMS)

  1. 内容分类管理

    1. 表结构

      1. 内容分类表

  1. 内容表

应该有的字段:

  1. 图片
  2. 连接
  3. 标题
  4. 子标题

表结构中字段是否添加索引判断依据是什么? -- 字段是否是查询条件或者是排序条件。

是否将所有的字段都添加索引,来加快查询? -- 不行的

  1. 索引会占用存储空间,索引越多,使用的存储空间越多
  2. 插入数据,存储索引也会消耗时间,索引越多,插入数据的速度越慢
    1. 实现

      1. 创建pojo、mapper、service、controller

略。

  1. 内容分类管理

创建根节点:

  1. 分类列表查询

效果:

  1. 节点的右键菜单

定义菜单:

右键触发菜单显示:

具体的菜单事件:

  1. 新增事件

JS实现:

按下回车,编辑完成事件:

后台实现:

Controller:

  1. 重命名

JS实现:

后端实现:

  1. 删除

JS实现:

过滤器:

后端实现:

Controller:

Service:

public void deleteAll(ContentCategory contentCategory) {

List<Object> ids = new ArrayList<Object>();

ids.add(contentCategory.getId());

// 递归查找该节点下的所有子节点id

this.findAllSubNode(ids, contentCategory.getId());

super.deleteByIds(ids, ContentCategory.class, "id");

// 判断该节点是否还有兄弟节点,如果没有,修改父节点的isParent为false

ContentCategory record = new ContentCategory();

record.setParentId(contentCategory.getParentId());

List<ContentCategory> list = super.queryListByWhere(record);

if (null == list || list.isEmpty()) {

ContentCategory parent = new ContentCategory();

parent.setId(contentCategory.getParentId());

parent.setIsParent(false);

super.updateSelective(parent);

}

}

private void findAllSubNode(List<Object> ids, Long pid) {

ContentCategory record = new ContentCategory();

record.setParentId(pid);

List<ContentCategory> list = super.queryListByWhere(record);

for (ContentCategory contentCategory : list) {

ids.add(contentCategory.getId());

// 判断该节点是否为父节点,如果是,继续调用该方法查找子节点

if (contentCategory.getIsParent()) {

// 开始递归

findAllSubNode(ids, contentCategory.getId());

}

}

}

  1. 存在的问题(TODO)

在Controller中实现数据库的操作,不在同一个事务中,需要将所有的操作移动至Service中完成。

  1. 内容管理

    1. 功能

  1. 选择内容分类加载数据

  1. 新增内容

校验,必须选中内容分类才能创建内容数据:

新增内容页面:

  1. 点击提交事件

  1. 后端实现

  1. 测试

  1. 查询内容列表

    1. JS实现

  1. Controller实现

  1. Service

  1. Mapper

  1. Mapper.xml

  1. 开启驼峰映射

<settings>

<!-- 开启驼峰自动映射 -->

<setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

  1. 在Spring和Mybatis的整合文件中读取Mapper.xml

  1. 效果

  1. 对外的接口服务

将ContentController拷贝到api包下,对外提供接口服务:

实现:

@RequestMapping("api/content")

@Controller

public class ApiContentController {

@Autowired

private ContentService contentService;

/**

* 根据内容分类id查询分类列表

*

* @param categoryId

* @param page

* @param rows

* @return

*/

@RequestMapping(method = RequestMethod.GET)

public ResponseEntity<EasyUIResult> queryListByCategoryId(@RequestParam("categoryId") Long categoryId,

@RequestParam(value = "page", defaultValue = "1") Integer page,

@RequestParam(value = "rows", defaultValue = "10") Integer rows) {

try {

EasyUIResult easyUIResult = this.contentService.queryListByCategoryId(categoryId, page, rows);

return ResponseEntity.ok(easyUIResult);

} catch (Exception e) {

e.printStackTrace();

}

return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);

}

}

测试:

  1. 访问接口服务的方式

方式有2种:

  1. js访问
    1. 有跨域 -- jsonp解决
    2. 无跨域 -- ajax解决
  2. Java代码访问
    1. Httpclient
    1. Httpclient

  1. 导入依赖

  1. DoGET

  1. 带有参数的GET请求

  1. DoPOST

  1. 带有参数的POST请求

public static void main(String[] args) throws Exception {

// 创建Httpclient对象

CloseableHttpClient httpclient = HttpClients.createDefault();

// 创建http POST请求

HttpPost httpPost = new HttpPost("http://www.oschina.net/search");

// 伪装成浏览器

httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36");

个post参数,一个是scope、一个是q

List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);

parameters.add(new BasicNameValuePair("scope", "project"));

parameters.add(new BasicNameValuePair("q", "java"));

parameters.add(new BasicNameValuePair("fromerr", "7nXH76r7"));

// 构造一个form表单式的实体

UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);

// 将请求实体设置到httpPost对象中

httpPost.setEntity(formEntity);

CloseableHttpResponse response = null;

try {

// 执行请求

response = httpclient.execute(httpPost);

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();

}

}

  1. 连接管理器

注意

  1. 定期关闭无效连接

public class ClientEvictExpiredConnections {

public static void main(String[] args) throws Exception {

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// 设置最大连接数

cm.setMaxTotal(200);

// 设置每个主机地址的并发数

cm.setDefaultMaxPerRoute(20);

new IdleConnectionEvictor(cm).start();

}

public static class IdleConnectionEvictor extends Thread {

private final HttpClientConnectionManager connMgr;

private volatile boolean shutdown;

public IdleConnectionEvictor(HttpClientConnectionManager connMgr) {

this.connMgr = connMgr;

}

@Override

public void run() {

try {

while (!shutdown) {

synchronized (this) {

wait(5000);

// 关闭失效的连接

connMgr.closeExpiredConnections();

}

}

} catch (InterruptedException ex) {

// 结束

}

}

public void shutdown() {

shutdown = true;

synchronized (this) {

notifyAll();

}

}

}

}

  1. 设置请求参数

  1. Httpclient和Spring的整合

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"

xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd

    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

<!-- 定义连接管理器 -->

<bean id="httpClientConnectionManager"

class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">

<property name="maxTotal" value="${http.maxTotal}" />

<property name="defaultMaxPerRoute" value="${http.defaultMaxPerRoute}" />

</bean>

<!-- httpclient的构建器 -->

<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder">

<property name="connectionManager" ref="httpClientConnectionManager" />

</bean>

<!-- 定义Httpclient对象 -->

<!-- 该对象是多例的 -->

<bean class="org.apache.http.impl.client.CloseableHttpClient"

factory-bean="httpClientBuilder" factory-method="build" scope="prototype">

</bean>

<!-- 请求参数的构建器 -->

<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">

<!-- 创建连接的最长时间 -->

<property name="connectTimeout" value="${http.connectTimeout}" />

<!-- 从连接池中获取到连接的最长时间 -->

<property name="connectionRequestTimeout" value="${http.connectionRequestTimeout}" />

<!-- 数据传输的最长时间 -->

<property name="socketTimeout" value="${http.socketTimeout}" />

<!-- 提交请求前测试连接是否可用 -->

<property name="staleConnectionCheckEnabled" value="${http.staleConnectionCheckEnabled}" />

</bean>

<!-- 定义请求参数对象 -->

<bean class="org.apache.http.client.config.RequestConfig"

factory-bean="requestConfigBuilder" factory-method="build" />

<!-- 定期关闭无效连接 -->

<bean class="com.taotao.web.httpclient.IdleConnectionEvictor">

<constructor-arg index="0" ref="httpClientConnectionManager" />

</bean>

</beans>

  1. 封装ApiService

package com.taotao.web.service;

import java.io.IOException;

import java.net.URISyntaxException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import org.apache.http.NameValuePair;

import org.apache.http.ParseException;

import org.apache.http.client.ClientProtocolException;

import org.apache.http.client.config.RequestConfig;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.CloseableHttpResponse;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.client.methods.HttpPost;

import org.apache.http.client.utils.URIBuilder;

import org.apache.http.impl.client.CloseableHttpClient;

import org.apache.http.message.BasicNameValuePair;

import org.apache.http.util.EntityUtils;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.beans.factory.BeanFactoryAware;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import com.taotao.web.httpclient.HttpResult;

@Service

public class ApiService implements BeanFactoryAware{

@Autowired

private RequestConfig requestConfig;

private BeanFactory beanFactory;

/**

* 指定GET请求,返回:null,请求失败,String数据,请求成功

*

* @param url

* @return

* @throws ClientProtocolException

* @throws IOException

*/

public String doGet(String url) throws ClientProtocolException, IOException {

// 创建http GET请求

HttpGet httpGet = new HttpGet(url);

httpGet.setConfig(requestConfig);

CloseableHttpResponse response = null;

try {

// 执行请求

response = getHttpClient().execute(httpGet);

if (response.getStatusLine().getStatusCode() == 200) {

return EntityUtils.toString(response.getEntity(), "UTF-8");

}

} finally {

if (response != null) {

response.close();

}

}

return null;

}

/**

* 带有参数的GET请求,返回:null,请求失败,String数据,请求成功

*

* @param url

* @param params

* @return

* @throws ClientProtocolException

* @throws IOException

* @throws URISyntaxException

*/

public String doGet(String url, Map<String, String> params) throws ClientProtocolException, IOException,

URISyntaxException {

URIBuilder builder = new URIBuilder(url);

for (Map.Entry<String, String> entry : params.entrySet()) {

builder.setParameter(entry.getKey(), entry.getValue());

}

return this.doGet(builder.build().toString());

}

/**

* 带有参数的POST请求

*

* @param url

* @param params

* @return

* @throws ParseException

* @throws IOException

*/

public HttpResult doPost(String url, Map<String, String> params) throws ParseException, IOException {

// 创建http POST请求

HttpPost httpPost = new HttpPost(url);

httpPost.setConfig(requestConfig);

if (null != params) {

// 设置post参

List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);

for (Map.Entry<String, String> entry : params.entrySet()) {

parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));

}

// 构造一个form表单式的实体

UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);

// 将请求实体设置到httpPost对象中

httpPost.setEntity(formEntity);

}

CloseableHttpResponse response = null;

try {

// 执行请求

response = getHttpClient().execute(httpPost);

return new HttpResult(response.getStatusLine().getStatusCode(), EntityUtils.toString(

response.getEntity(), "UTF-8"));

} finally {

if (response != null) {

response.close();

}

}

}

/**

* 没有参数的POST请求

*

* @param url

* @return

* @throws ParseException

* @throws IOException

*/

public HttpResult doPost(String url) throws ParseException, IOException {

return this.doPost(url, null);

}

private CloseableHttpClient getHttpClient(){

//通过Bean工厂获取bean,保证HttpClient对象是多例

return this.beanFactory.getBean(CloseableHttpClient.class);

}

@Override

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

this.beanFactory = beanFactory;

}

}

  1. 实现大广告

    1. 访问后台系统接口获取数据

  1. 将json数据保存到模型数据中

  1. 通过EL表达式输出到页面

  1. 测试

效果:

  1. 实现小广告

    1. 分析

  1. 实现

    1. Controller

  1. Service

  1. 效果

作业:实现淘淘快报。

  1. 优化实现

淘淘商城_day04_课堂笔记的更多相关文章

  1. 淘淘商城_day11_课堂笔记

    今日大纲 发布前的准备 实施发布 一部分是由我来发布 一部分是由你们来发布 讲解分布式部署架构 测试 功能测试 压力测试 项目实战的准备以及分组 分组 抽取功能 讲解所需要开发的功能 项目部署上线流程 ...

  2. 淘淘商城_day01_课堂笔记

    今日大纲 聊聊电商行业 电商行业发展 11.11 2015双11: 2016年: 预测:2017年的双11交易额将达到:1400亿 电商行业技术特点 淘淘商城简介 淘淘商城的前身 电商行业的概念 B2 ...

  3. 淘淘商城_day02_课堂笔记

    今日大纲 学习Nginx的使用 实现商品的管理 新增商品 查询商品列表 编辑商品 删除商品 上架和下架商品 学习nginx 开发阶段中的环境 开发环境:自己的电脑 测试环境:提供给测试人员使用的环境 ...

  4. 淘淘商城_day10_课堂笔记

    今日大纲 Dubbo入门学习 使用dubbo优化单点登录系统 系统间服务调用方式 浏览器直接访问 浏览器发起请求,通过ajax或jsonp方式请求: Httpclient方式 系统与系统之间通过Htt ...

  5. 淘淘商城_day09_课堂笔记

    今日大纲 实现购物车 基于Mysql实现读写分离 购物车 需求描述 用户可以在登录状态下将商品添加到购物车 用户可以在未登录状态下将商品添加到购物车 用户可以使用购物车一起结算下单 用户可以查询自己的 ...

  6. 淘淘商城_day08_课堂笔记

    今日大纲 问题,如何实现商品数据的同步? 学习MQ(消息队列) 搭建RabbitMQ的环境 学习RabbitMQ的队列 学习Spring-Rabbit 使用RabbitMQ完成商品数据的同步 如何实现 ...

  7. 淘淘商城_day07_课堂笔记

    今日大纲 讲解订单系统 基于订单系统完成下单功能的开发 使用Solr完成商品的搜索功能 订单系统 说明:订单系统只是做讲解,不做开发. 导入taotao-order 表结构 订单表: 订单商品表: 疑 ...

  8. 淘淘商城_day05_课堂笔记

    今日大纲 学习Redis 使用Redis完成项目中缓存需求 实现商品详情页功能 缓存的需求 大广告位数据无需每次查询后台系统的接口,可以在前台系统添加缓存,提高访问首页的速度. 商品类目的数据也可以缓 ...

  9. 淘淘商城_day06_课堂笔记

    今日大纲 实现单点登录系统 基于单点登录系统实现,用户的注册和登录 商品数据同步问题 问题 后台系统中将商品修改,前台系统没有进行数据的同步,导致前端系统不能够实时显示最新的数据. 解决 后台系统中商 ...

随机推荐

  1. base关键字

    base关键字      专门用来在子类访问父类成员 base.标识符:“.”调用父类同名属性.同名函数.构造函数 ()父类person public class Person { public Pe ...

  2. [ios2]iOS 使用subversion管理iOS源代码 【转】

    使用subversion管理iOS源代码 1.安装和配置subversion服务器 在windows 服务器上安装VisualSVN-Server,下载地址http://www.visualsvn.c ...

  3. IE条件注释,嗅探低版本IE用户,并引导升级

    一.科普IE条件注释 IE条件注释功能是条件注释是IE特有的一种功能,能对IE系列产品进行单独的XHTML代码处理,注意,主要是针对XHTML,而非CSS.条件注释功能非常强大,可以进行true和fa ...

  4. 安装vsftp流程整理

    昨天装个FTP,发现之前写的一篇操作日志太简陋了,重新整理了下记在这儿 # 安装 VSFTP yum -y install vsftpd # 创建FTP日志文件路径 touch /var/log/vs ...

  5. servlet笔记,配置与 http相关

    tomcat配置环境变量:        JAVA_HOME= 指向你的jdk的主目录(bin目录的上一层) server.xml: <Context path="/myweb2&qu ...

  6. Ch2 空间配置器(allocator) ---笔记

    2.1 空间配置器的标准接口 allocator的必要接口: allocator::value_type allocator::pointer allocator::const_pointer all ...

  7. ffmpeg的安装--opencv视频处理必备

    安装yasm(ffmpeg必备)wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gztar xzvf yasm-1. ...

  8. mac下virtualbox配置全网通

    mac下virtualbox实现主机和虚拟机.虚拟机和外网互访的方案 全局添加Host-Only网络 Adapter IPv4 Address:192.168.56.1 IPv4 Network Ma ...

  9. Ubuntu14.04 bind9配置

    apt-get install bind9 配置域名: cn.archive.ubuntu.com 对应IP: 10.60.233.244 vim /etc/bind/name.conf.defaul ...

  10. apache 配置静态文件缓存和开启gzip压缩

    1,设置文件静态缓存3天: 在httpd.conf 里添加如下代码: #文件静态缓存配置 <IfModule expires_module> #打开缓存 ExpiresActive on ...