在application.properties中
# 服务端口 server.port=8004 # 服务名 spring.application.name=service-cms # mysql数据库连接 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=root #返回json的全局时间格式 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 #配置mapper xml文件的路径 mybatis-plus.mapper-locations=classpath:com/atguigu/cmsservice/mapper/xml/*.xml #mybatis日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
CREATE TABLE `crm_banner` ( `id` CHAR(19) NOT NULL DEFAULT '' COMMENT 'ID', `title` VARCHAR(20) DEFAULT '' COMMENT '标题', `image_url` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '图片地址', `link_url` VARCHAR(500) DEFAULT '' COMMENT '链接地址', `sort` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT '排序', `is_deleted` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除', `gmt_create` DATETIME NOT NULL COMMENT '创建时间', `gmt_modified` DATETIME NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`title`) ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='首页banner表'; # # Data for table "crm_banner" # INSERT INTO `crm_banner` VALUES ('1194556896025845762','test1','https://online-teach-file.oss-cn-beijing.aliyuncs.com/cms/2019/11/14/297acd3b-b592-4cfb-a446-a28310369675.jpg','/course',1,0,'2019-11-13 18:05:32','2019-11-18 10:28:22'), ('1194607458461216769','test2','https://online-teach-file.oss-cn-beijing.aliyuncs.com/cms/2019/11/13/8f80790d-d736-4842-a6a4-4dcb0d684d4e.jpg','/teacher',2,0,'2019-11-13 21:26:27','2019-11-14 09:12:15');
@Test public void run() { // 1、创建代码生成器 AutoGenerator mpg = new AutoGenerator(); // 2、全局配置 GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir("D:\\尚硅谷在线教育项目\\在线教育--谷粒学院\\项目源码\\day10\\后端代码\\后端代码\\guli_parent\\service\\service_cms" + "/src/main/java"); gc.setAuthor("smile"); gc.setOpen(false); //生成后是否打开资源管理器 gc.setFileOverride(false); //重新生成时文件是否覆盖 //UserServie gc.setServiceName("%sService"); //去掉Service接口的首字母I gc.setIdType(IdType.ID_WORKER_STR); //主键策略 gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型 gc.setSwagger2(true);//开启Swagger2模式 mpg.setGlobalConfig(gc); // 3、数据源配置 DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8"); dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("199866"); dsc.setDbType(DbType.MYSQL); mpg.setDataSource(dsc); // 4、包配置 PackageConfig pc = new PackageConfig(); pc.setModuleName("educms"); //模块名 //包 com.atguigu.eduservice pc.setParent("com.blb"); //包 com.atguigu.eduservice.controller pc.setController("controller"); pc.setEntity("domain"); pc.setService("service"); pc.setMapper("mapper"); mpg.setPackageInfo(pc); // 5、策略配置 StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("crm_banner"); strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略 strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀 strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略 strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作 strategy.setRestControllerStyle(true); //restful api风格控制器 strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符 mpg.setStrategy(strategy); // 6、执行 mpg.execute(); }
controller层
@RestController @CrossOrigin @RequestMapping("/educms/banneradmin") public class BannerAdminController { @Autowired private CrmBannerService crmBannerService; //1.分页查询banner @GetMapping("/pageBanner/{page}/{limit}") public R pageBanner(@PathVariable long page,@PathVariable long limit) { Page<CrmBanner> crmBannerPage = new Page<>(page,limit); crmBannerService.page(crmBannerPage,null); return R.ok().data("items",crmBannerPage.getRecords()).data("total",crmBannerPage.getTotal()); } //添加banner @PostMapping("/addbanner") public R addBanner(@RequestBody CrmBanner crmBanner) { crmBannerService.save(crmBanner); return R.ok(); } //根据id查询banner @GetMapping("/get/{id}") public R getBanner(@PathVariable String id) { CrmBanner crmBanner = crmBannerService.getById(id); return R.ok().data("item",crmBanner); } //修改banner @PutMapping("/update") public R updateBanner(@RequestBody CrmBanner banner) { crmBannerService.updateById(banner); return R.ok(); } //根据id删除banner @DeleteMapping("/delete/{id}") public R deleteBanner(@PathVariable("id") String id) { crmBannerService.removeById(id); return R.ok(); } }
@RestController @RequestMapping("/educms/bannerfront") @CrossOrigin public class BannerFrontController { @Autowired private CrmBannerService bannerService; //查询所有banner @GetMapping("/getAllBanner") public R getAllBanner() { List<CrmBanner> list= bannerService.selectAllBanner(); return R.ok().data("list",list); } }
service层的编写
@Service public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService { @Override public List<CrmBanner> selectAllBanner() { List<CrmBanner> list = baseMapper.selectList(null); return list; } }
在service_edu的module下在controller层创建一个名为IndexFrontController的controller,实现热门课程和名师的查询
创建一个IndexFrontController类
@RestController @RequestMapping("/eduservice/indexfront") @CrossOrigin public class IndexFrontController { @Autowired private EduCourseService eduCourseService; @Autowired private EduTeacherService eduTeacherService; @GetMapping("/index") public R index() { //查询前八门热门课程 List<EduCourse> courseList =eduCourseService.getFrontClass(); //查询前四名讲师 List<EduTeacher> teacherList= eduTeacherService.getFrontTeacher(); return R.ok().data("courseList",courseList).data("teacherList",teacherList); } }
service实现
EduCourseServiceImpl
//查询前八门热门课程 @Override public List<EduCourse> getFrontClass() { QueryWrapper<EduCourse> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("id"); wrapper.last("limit 8"); List<EduCourse> list = baseMapper.selectList(wrapper); return list; }
EduTeacherServiceImpl
@Service public class EduTeacherServiceImpl extends ServiceImpl<EduTeacherMapper, EduTeacher> implements EduTeacherService { @Override public List<EduTeacher> getFrontTeacher() { QueryWrapper<EduTeacher> wrapper = new QueryWrapper<>(); wrapper.orderByDesc("id"); wrapper.last("limit 4"); List<EduTeacher> list = baseMapper.selectList(wrapper); return list; } }
npm install axios
import axios from 'axios' //创建axios实例 const service = axios.create({ baseURL: 'http://localhost:9001',//api的base_url timeout:20000 //请求超时时间 }) export default service
import request from '@/utils/request.js' export default{ //查询前两条banner数据 getListBanner(){ return request({ url: '/educms/bannerfront/getAllBanner', method: 'GET' }) } }
created(){ //调用查询banner的方法 this.getBannerList() }, methods:{ //查询banner数据 getBannerList() { banner.getListBanner() .then(response => { this.bannerList=response.data.data.list }) } }
<div class="swiper-wrapper"> <div v-for="banner in bannerList" :key="banner.id" class="swiper-slide" style="background: #040B1B;"> <a target="_blank" :href="banner.linkUrl"> <img :src="banner.imageUrl" :alt="banner.title"> </a> </div>
import request from '@/utils/request.js' export default{ //查询热门课程和名师 getIndexData(){ return request({ url: '/eduservice/indexfront/index', method: 'GET' }) } }
//获得热门课程和名师 getHotCourseTeacher() { index.getIndexData() .then(response=>{ this.eduList=response.data.data.courseList this.teacherList=response.data.data.teacherList }) }
//热门课程 <ul class="of" id="bna"> <li v-for="course in eduList" :key="course.id"> <div class="cc-l-wrap"> <section class="course-img"> <img :src="course.cover" class="img-responsive" :alt="course.title" > <div class="cc-mask"> <a href="#" title="开始学习" class="comm-btn c-btn-1">开始学习</a> </div> </section> <h3 class="hLh30 txtOf mt10"> <a href="#" :title="course.title" class="course-title fsize18 c-333">{{course.title}}</a> </h3> <section class="mt10 hLh20 of"> <span class="fr jgTag bg-green" v-if="Number(course.price) === 0"> <i class="c-fff fsize12 f-fA">免费</i> </span> <span class="fl jgAttr c-ccc f-fA"> <i class="c-999 f-fA">{{course.buyCount}}人学习</i> | <i class="c-999 f-fA">{{course.viewCount}}评论</i> </span> </section> </div> </li> </ul> //名师 <ul class="of"> <li v-for="teacher in teacherList" :key="teacher.id"> <section class="i-teach-wrap"> <div class="i-teach-pic"> <a href="/teacher/1" :title="teacher.name"> <img :alt="teacher.name" :src="teacher.avatar"> </a> </div> <div class="mt10 hLh30 txtOf tac"> <a href="/teacher/1" :title="teacher.name" class="fsize18 c-666">{{teacher.name}}</a> </div> <div class="hLh30 txtOf tac"> <span class="fsize14 c-999">{{teacher.career}}</span> </div> <div class="mt15 i-q-txt"> <p class="c-999 f-fA" >{{teacher.intro}}</p> </div> </section> </li> </ul>
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- spring2.X集成redis所需common-pool2--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.0</version> </dependency>
@Configuration //配置类 @EnableCaching //开启缓存 public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setConnectionFactory(factory); //key序列化方式 template.setKeySerializer(redisSerializer); //value序列化 template.setValueSerializer(jackson2JsonRedisSerializer); //value hashmap序列化 template.setHashValueSerializer(jackson2JsonRedisSerializer); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化(解决乱码的问题),过期时间600秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } }
由于首页中数据变化不是很频繁,而且首页访问量较大,所有我们有必要把首页接口的数据缓存到redis缓存中,减少数据库的压力和提高访问速度
改造service-cms莫快递首页banner接口
缓存@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。查看源码,属性值如下:
缓存@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
查看源码,属性值如下:
(3)缓存@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
查看源码,属性值如下:
在application.properties中添加redis配置
spring.redis.host=localhost spring.redis.port=6379 spring.redis.database= 0 spring.redis.timeout=1800000 spring.redis.lettuce.pool.max-active=20 spring.redis.lettuce.pool.max-wait=-1 #最大阻塞等待时间(负数表示没限制) spring.redis.lettuce.pool.max-idle=5 spring.redis.lettuce.pool.min-idle=0
Redis添加
在CrmBannerServiceImpl接口中添加redis
@Service public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService { @Cacheable(value = "banner",key = "'selectIndexList'") @Override public List<CrmBanner> selectAllBanner() { //根据id降序排序查询前两条数据 QueryWrapper<CrmBanner> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("id"); //用last方法实现SQL语句的拼接 queryWrapper.last("limit 2"); List<CrmBanner> list = baseMapper.selectList(queryWrapper); return list; } }