一、网站前台分析
1.1 网站前台有哪些页面
- 网站首页
- 商家(店铺)首页
- 商品详细页
- 商品搜索页
- 购物车列表页
- 购物选项选择页
- 支付页
- 用户注册页
- 用户登陆页
- 用户中心页等
1.2 网站首页广告
- 首页海报(轮播图)
- 今日推荐
- 猜你喜欢
- 楼层广告
1.3 数据库表结构分析
tb_content_category 广告分类表
字段 | 类型 | 长度 | 含义 |
---|---|---|---|
id | Bigint | 主键 | |
name | Varchar | 255 | 广告分类名称 |
tb_content 广告表
字段 | 类型 | 长度 | 含义 |
---|---|---|---|
id | Bigint | 主键 | |
category_id | Bigint | 广告分类ID | |
title | varchar | 200 | 广告标题 |
url | varchar | 500 | 广告链接 |
pic | varchar | 300 | 图片地址 |
status | varchar | 1 | 状态 |
sort_order | int | 1 | 排序 |
二、运营商后台-广告类型及广告管理
2.1 需求分析
实现广告类型表与广告表的增删改查
广告管理页 显示广告类别名称
2.2 准备工作
2.2.1 构建工程
构建工程
- youlexuan_content_interface
- 引入依赖 youlexuan_pojo,youlexuan_dao
- 创建包 com.zql.content.service
- youlexuan_content_service (WAR)
- 引入依赖参见 youlexuan_sellergoods_service
- 引入 tomcat 插件配置 ,指定tomcat的运行端口为9002
- 为 youlexuan_content_service 工程添加web.xml
- 添加spring相关配置文件
- 创建包 com.zql.content.service.impl
- 构建子工程 youlexuan_content_interface
(1) 在youlexuan_parent 下面构建子工程 youlexuan_content_interface
(2)引入依赖 youlexuan_pojo
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_pojo</artifactId>
<version>1.0</version>
</dependency>
(3)创建包 com.zql.content.service(看上面总结构图)
-
构建子工程 youlexuan_content-service
(1) 在youlexuan_parent下面构建子工程 youlexuan_content-service(类似上面1/(1)构建)
(2)拷贝 youlexuan_sellergoods_service下面 pom.xml依赖并做修改
- 修改 youlexuan_sellergoods_interface 为 youlexuan_content_interface
- 修改tomcat的运行端口为9002
<packaging>war</packaging>
<properties>
<webVersion>3.0</webVersion>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_common</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_dao</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_content_interface</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>9002</port>
</configuration>
</plugin>
</plugins>
</build>
(3) 为 youlexuan_content_service 工程添加web.xml
- 拷贝 youlexuan_sellergoods_service 下面的webapp / WEB-INF / web.xml
- 拷贝 youlexuan_sellergoods_service下面的 spring / applicationContext_service.xml,需要事务也可以拷贝过来,并做下面①②③修改
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext_*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
注意:我们目前有两个服务工程,当两个工程同时启动时会发生端口冲突,因为连接dubbo注册中心的端口默认是20880。所以我们需要配置一下youlexuan_content_service工程的dubbo端口
(4) 创建包 com.zql.content.service.impl(见上面总结构图)
2.2.2 将前面生成代码拷入工程
附加操作 👇🏾👇🏾
下载生成代码 资源 并解压拷贝(或用IDEA打开直接对应拷贝)
在 youlexuan_manager_web下的pom.xml中引入 youlexuan_content_interface
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_content_interface</artifactId>
<version>1.0</version>
</dependency>
修改youlexuan_manager_web下面的 resources / spring / springmvc.xml扫描包路径
测试运行广告分类管理 和广告管理页面
- 整体安装工程 youlexuan_parent
- 开启 content_service
- 开启 sellerGoods_service
- 开启 manager_web
- 访问
http://localhost:9101/login.html
广告图片没有找到解决 👉🏾👉🏾 七、广告图片未找到
重启 manager_web,访问如下所示 (测试crud都OK):
2.3 广告管理
2.3.1 广告管理类别名称,状态,图片 显示
- 在youlexuan_manager_web 下的 js /controller / contentController.js 引入
contentCategoryService
- 在youlexuan_manager_web 下的 js /controller / contentController.js 中增加方法
//广告管理显示广告类别
$scope.contentCategory = [];
$scope.status = ['禁用','启用'];
$scope.findAllContentCategory= function () {
contentCategoryService.findAll().success(function (response) {
for (var i=0; i < response.length; i++) {
$scope.contentCategory[response[i].id]= response[i].name;
}
});
}
- 修改 content.html
最终显示:
2.3.2 编辑窗口广告状态框显示
修改新建广告 按钮,弹出新增框前,初始化广告状态为1 ng-click="entity={status:'1'}"
修改为如下所示:
2.3.3 编辑窗口状态广告类别显示
//加载广告分类列表
$scope.contentCategoryList = response;
<tr>
<td>广告类别</td>
<td><select class="form-control" ng-model="entity.categoryId" ng-options="item.id as item.name for item in contentCategoryList"></select></td>
</tr>
2.3.4 编辑窗口图片显示
<tr>
<td>图片绝对路径</td>
<td><input type="file" id="file">
<button ng-click="uploadFile()">上传</button>
<img src="{{entity.pic}}" height="100px" width="200px">
</td>
</tr>
2.3.5 广告图片上传
拷贝 youlexuan_shop_web 下面到 youlexuan_manager_web
- 拷贝 resources / conf 到 youlexuan_manager_web下面对应位置
- 拷贝 youlexuan_shop_web 中的ContentCategoryController.java 到 youlexuan_manager_web 对应位置
- 修改 youlexuan_manager_web 下面 springmvc.xml,如下添加
<context:property-placeholder location="classpath:conf/application.properties"></context:property-placeholder>
<!-- 配置文件上传多媒体解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5000242880"></property>
</bean>
- 拷贝 youlexuan_shop_web 下的 uploadService.js 到youlexuan_manager对应下面
- 拷贝下面代码到 youlexuan_manager_web下的 contentController.js 内,并做修改
//上传图片
$scope.uploadFile = function () {
uploadService.uploadFile().success(function (response) {
if(response.success){ //如果上传成功,就取出url
$scope.entity.pic = response.message;//设置文件地址
}else{
alert(response.message);
}
}).error(function () {
alert("上传发生错误");
})
};
记得引入 uploadService
👇🏾👇🏾
- 在 content.html 中引入
uploadService
,如下 js
<script type="text/javascript" src="../js/service/uploadService.js"></script>
最终显示 :重新启动 manager_web,刷新网页显示
上传成功如下(下载 👉🏾图片素材可多添几张) 👇🏾👇🏾
三、网站首页-广告展示
3.1 需求分析
修改首页,当其轮播广告图根据后台设置的广告列表动态产生。
3.2 准备工作
3.2.1 工程搭建
创建war子模块 youlexuan_portal_web ,此工程为网站前台的入口,参照其它war模块编写配置文件。不需要添加SpringSecurity框架
(1)导入下面依赖到 pom.xml中
<packaging>war</packaging>
<properties>
<webVersion>3.0</webVersion>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- dubbo相关 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.zql</groupId>
<artifactId>youlexuan_content_interface</artifactId>
<version>1.0</version>
</dependency>
<!-- 增加pagehelper类、mybatis类,因为Service使用了,不导入会报序列化错 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<path>/</path>
<port>9103</port>
</configuration>
</plugin>
</plugins>
</build>
(2)创建 web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
(3)resources 下面创建 spring / springmvc.xml
导入 springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.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.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com.zql"/>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
<property name="features">
<array>
<value>WriteMapNullValue</value>
<value>WriteDateUseDateFormat</value>
</array>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 引用dubbo 服务 -->
<dubbo:application name="youlexuan_portal_web" />
<dubbo:registry address="zookeeper://192.168.188.180:2181"/>
<dubbo:annotation package="com.zql" />
</beans>
3.2.2 前端
(1)拷贝资源:(资源 \ 静态原型 \ 网站前台 )目录下的index.html以及相关目录拷贝到youlexuan_portal_web \webapp 下面
(2)在youlexuan_shop_web \webapp \ js文件夹拷贝 base.js 和 base_pagination.js 到 youlexuan_portal_web \webapp \ js下面,并在下面创建service 和controller文件夹
启动 sellerGoods-service,content_service,portal_web(根据前面创建即可)
访问: http://localhost:9103/index.html
3.3 后端代码
3.3.1 服务接口层
在youlexuan_content_interface 工程 ContentService 接口增加方法定义
/**
* 根据广告类型ID查询列表
* @param
* @return
*/
public List<TbContent> findByCategoryId(Long categoryId);
3.3.2 服务实现层
在youlexuan_content_service工程 ContentServiceImpl类增加方法
//根据广告类型ID查询列表
public List<TbContent> findByCategoryId(Long categoryId){
//根据广告分类ID查询广告列表
TbContentExample tbContentExample = new TbContentExample();
Criteria criteria = tbContentExample.createCriteria();
criteria.andCategoryIdEqualTo(categoryId);
criteria.andStatusEqualTo("1");//开启状态
tbContentExample.setOrderByClause("sort_order");排序
return contentMapper.selectByExample(tbContentExample);
}
3.3.3 控制层
在youlexuan_portal_web创建控制器类 ContentController
package com.zql.portal.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.zql.content.service.ContentService;
import com.zql.pojo.TbContent;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author:Daniel
* @Version 1.0
*/
@RestController
@RequestMapping("/content")
public class ContentController {
@Reference
private ContentService contentService;
//根据广告分类ID查询广告列表
@RequestMapping("/findByCategoryId")
public List<TbContent> findByCategoryId(Long categoryId){
return contentService.findByCategoryId(categoryId);
}
}
3.4 前端代码
3.4.1 服务层
在youlexuan_portal_web工程创建contentService.js
app.service("contentService",function($http){
//根据分类ID查询广告列表
this.findByCategoryId=function(categoryId){
return $http.get("content/findByCategoryId.do?categoryId="+categoryId);
}
});
3.4.2 控制层
在youlexuan_portal_web创建 contentController.js
//广告控制层(运营商后台)
app.controller("contentController",function($scope,contentService){
$scope.findByCategoryId=function(categoryId){
contentService.findByCategoryId(categoryId).success(
function(response){
$scope.list=response;
}
);
}
});
3.4.3 页面
(1)修改youlexuan_portal_web工程的 index.html 引入JS,并在body上添加指令
<script type="text/javascript" src="plugins/angularjs/angular.min.js"> </script>
<script type="text/javascript" src="js/base.js"> </script>
<script type="text/javascript" src="js/service/contentService.js"> </script>
<script type="text/javascript" src="js/controller/contentController.js"> </script>
<body ng-app="youlexuan" ng-controller="contentController" ng-init="findByCategoryId(1)">
(2)修改首页轮播图(部分代码及截图)
<!--banner轮播-->
<div id="myCarousel" data-ride="carousel" data-interval="2000" class="sui-carousel slide">
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="{{$index==0?'active':''}}" ng-repeat="item in list"></li>
</ol>
<div class="carousel-inner">
<div class="{{$index==0?'active':''}} item" ng-repeat="item in list">
<a href="{{item.url}}">
<img src="{{item.pic}}" style="width:730px;height:454px" />
</a>
</div>
</div><a href="#myCarousel" data-slide="prev" class="carousel-control left">‹</a><a href="#myCarousel" data-slide="next" class="carousel-control right">›</a>
</div>
最终显示: http://localhost:9103/index.html
即可看到首页效果
四、SpringDataRedis 简介
4.1 项目常见问题思考
我们目前的系统已经实现了广告后台管理和广告前台展示,但是对于首页每天有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪。那如何解决呢?
通常的做法有两种:
- 一种是数据缓存;
- 一种是网页静态化。
今天讨论第一种解决方案。
4.2 Redis
redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写。企业开发通常采用Redis来实现缓存。同类的产品还有Memcache 、MongoDB等。
4.3 Jedis
Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis。
4.4 Spring Data Redis
Spring-data-redis是spring大家族的一部分,提供了在spring应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
spring-data-redis针对jedis提供了如下功能:
- 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
- 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
4.5 Spring Data Redis入门小Demo
4.5.1准备工作
新建一台虚拟机安装Redis环境
(具体安装步骤参见 (六、Redis的安装和图形工具的连接))
(1)构建Maven工程 spring-data-redis
(2)引入Spring相关依赖、引入JUnit依赖
(3)引入Jedis和SpringDataRedis依赖
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<junit.version>4.12</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
</dependencies>
(4)在src/main/resources下创建properties文件夹,建立redis_config.properties
redis.host=192.168.188.180
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
redis.total=100
(5)在src/main/resources下创建spring文件夹 ,创建applicationContext_redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="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.xsd">
<!-- 加载属性文件-->
<context:property-placeholder location="classpath:properties/redis_config.properties"/>
<!-- 配置redis连接池相关属性-->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
<property name="maxTotal" value="${redis.total}"/>
</bean>
<!-- 配置redis连接工厂-->
<bean id="RedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" value="${redis.pass}"/>
<property name="database" value="${redis.database}"/>
<!--连接池的属性 -->
<property name="poolConfig" ref="poolConfig"/>
</bean>
<!-- RedisTemplate-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="RedisConnectionFactory"/>
</bean>
</beans>
- maxIdle :最大空闲数
- maxWaitMillis:连接时的最大等待毫秒数
- testOnBorrow:在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的;
(6) 在 test / java 下创建 RedisTest.java 进行测试(搭建好测试看下面)
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @Author:Daniel
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext-redis.xml")
public class RedisTest {
@Autowired
private RedisTemplate redisTemplate;
}
4.5.2 值类型操作
//值类型操作
@Test
public void TestValue(){
redisTemplate.boundValueOps("age").set(23);
}
@Test
public void getValue(){
int age = (int)redisTemplate.boundValueOps("age").get();
System.out.println(age);
}
@Test
public void deleteValue(){
redisTemplate.delete("age");
}
4.5.3 Set 类型操作
//Set 类型操作
@Test
public void TestSet(){
redisTemplate.boundSetOps("nameSet").add("Daniel");
redisTemplate.boundSetOps("nameSet").add("Amy");
redisTemplate.boundSetOps("nameSet").add("Stella");
redisTemplate.boundSetOps("nameset").add("Andy");
redisTemplate.boundSetOps("nameSet").add("Nancy");
}
@Test
public void getSet(){
Set me = redisTemplate.boundSetOps("nameSet").members();
System.out.println(me);
}
//删除某一个值
@Test
public void deleteSet(){
redisTemplate.boundSetOps("nameSet").remove("Daniel");
}
//删除整个集合
@Test
public void deleSet(){
redisTemplate.delete("nameSet");
}
4.5.4 List类型操作
创建测试类TestList
(1)右压栈
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
/**
* @Author:Daniel
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext-redis.xml")
public class TestList {
@Autowired
private RedisTemplate redisTemplate;
//右压栈:后添加的对象排在后边
@Test
public void rightList(){
redisTemplate.boundListOps("nameList").rightPush("Daniel");
redisTemplate.boundListOps("nameList").rightPush("hollw");
redisTemplate.boundListOps("nameList").rightPush("Jenny");
redisTemplate.boundListOps("nameList").rightPush("Wendy");
}
//显示右压栈集合
@Test
public void rightGetList(){
List nameList = redisTemplate.boundListOps("nameList").range(1, 10);
System.out.println(nameList);
}
//左压栈:后添加的对象排在前边
@Test
public void leftList(){
redisTemplate.boundListOps("aeg").leftPush("文树");
redisTemplate.boundListOps("aeg").leftPush("上湾");
redisTemplate.boundListOps("aeg").leftPush("下湾");
redisTemplate.boundListOps("aeg").leftPush("街道");
}
//显示左压栈集合
@Test
public void leftGetList(){
List aeg = redisTemplate.boundListOps("aeg").range(0, 10);
System.out.println(aeg);
}
//(3)根据索引查询元素
@Test
public void listByIndex(){
String aeg = (String)redisTemplate.boundListOps("aeg").index(2);
System.out.println(aeg);
}
//(4)移除某个元素的值
@Test
public void removeB(){
// 第一个参数 要删除元素的个数 (0全部删除) 第二个参数 元素值
redisTemplate.boundListOps("aeg").remove(1,"Daniel");
}
}
4.5.5 Hash 类型操作
创建测试类 TestHash
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import java.util.Set;
/**
* @Author:Daniel
* @Version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/applicationContext-redis.xml")
public class estHash {
@Autowired
private RedisTemplate redisTemplate;
//存入值
@Test
public void setValue(){
redisTemplate.boundHashOps("namHash").put("a","Daniel");
redisTemplate.boundHashOps("namHash").put("b","Wendy");
redisTemplate.boundHashOps("namHash").put("c","Kendra");
redisTemplate.boundHashOps("namHash").put("d","GuoGuo");
redisTemplate.boundHashOps("namHash").put("e","Jhowll");
}
//提取所有的KEY
@Test
public void getKey(){
Set namHash = redisTemplate.boundHashOps("namHash").keys();
System.out.println(namHash);
}
//提取所有的值
@Test
public void getValue(){
List namHash = redisTemplate.boundHashOps("namHash").values();
System.out.println(namHash);
}
//(4)根据KEY提取值
@Test
public void getValueByKey(){
String o = (String)redisTemplate.boundHashOps("namHash").get("d");
System.out.println(o);
}
//(5)根据KEY移除值
@Test
public void removeValueByKey(){
redisTemplate.boundHashOps("namHash").delete("c");
}
}
(1)存入值
案例结构
五、网站首页-缓存广告数据
5.1 需求分析
现在我们首页的广告每次都是从数据库读取,这样当网站访问量达到高峰时段,对数据库压力很大,并且影响执行效率。我们需要将这部分广告数据缓存起来。
5.2 读取缓存
5.2.1 公共组件层
因为缓存对于我们整个的系统来说是通用功能。广告需要用,其它数据可能也会用到,所以我们将配置放在公共组件层(youlexuan_common)中较为合理。
(1)youlexuan_common 引入依赖
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
(2)创建配置文件
将 资源 中的 redis_config.properties 和applicationContext-redis.xml 拷贝至youlexuan-common
注意:applicationContext-redis.xml 不需要再加载属性配置文件。
(3)youlexuan_content_service 依赖 youlexuan_common(注:pom中应该已有)
5.2.2后端服务实现层
修改 youlexuan_content_service的 ContentServiceImpl
@Autowired
private RedisTemplate redisTemplate;
//根据广告类型ID查询列表
public List<TbContent> findByCategoryId(Long categoryId){
List<TbContent> contentList = (List<TbContent>)redisTemplate.boundHashOps("content").get(categoryId);
if(contentList != null){
return contentList;
}
//根据广告分类ID查询广告列表
TbContentExample tbContentExample = new TbContentExample();
Criteria criteria = tbContentExample.createCriteria();
criteria.andCategoryIdEqualTo(categoryId);
criteria.andStatusEqualTo("1");//开启状态
tbContentExample.setOrderByClause("sort_order");排序
contentList = contentMapper.selectByExample(tbContentExample);
redisTemplate.boundHashOps("content").put(categoryId,contentList);//存入缓存
return contentList;
}
5.3 更新缓存
当广告数据发生变更时,需要将缓存数据清除,这样再次查询才能获取最新的数据
5.3.1 新增广告后清除缓存
修改youlexuan_content_service工程ContentServiceImpl.java 的add方法
/**
* 增加
*/
@Override
public void add(TbContent content) {
//清除缓存
redisTemplate.boundHashOps("content").delete(content.getCategoryId());
contentMapper.insert(content);
}
5.3.2 修改广告后清除缓存
考虑到用户可能会修改广告的分类,这样需要把原分类的缓存和新分类的缓存都清除掉。
/**
* 修改
*/
@Override
public void update(TbContent content){
//查询修改前的分类Id
Long categoryId = contentMapper.selectByPrimaryKey(content.getId()).getCategoryId();
redisTemplate.boundHashOps("content").delete(categoryId);
contentMapper.updateByPrimaryKey(content);
//如果分类ID发生了修改,清除修改后的分类ID的缓存
if(categoryId.longValue() != content.getCategoryId().longValue()){
redisTemplate.boundHashOps("content").delete(content.getCategoryId());
}
}
5.3.3 删除广告后清除缓存
/**
* 批量删除
*/
@Override
public void delete(Long[] ids) {
for(Long id:ids){
//清除缓存
Long categoryId = contentMapper.selectByPrimaryKey(id).getCategoryId();//广告分类ID
redisTemplate.boundHashOps("content").delete(categoryId);
contentMapper.deleteByPrimaryKey(id);
}
}
(1) 测试:清除 redis 工具缓存
(2)安装 youlexuan_common,启动 content_service,portal_web
浏览器访问: http://localhost:9103/index.html
已存入下列redis中了,再次访问变得相对快了很多!
当前 youlexuan 所有完整代码