1. Homepage data banner display (Backend)
1.1 create sub module service in service_cms
1.2 create profile
In application.properties
# Service port server.port=8004 # service name spring.application.name=service-cms # mysql database connection 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 #Returns the global time format of json spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 #The path to the configuration mapper xml file mybatis-plus.mapper-locations=classpath:com/atguigu/cmsservice/mapper/xml/*.xml #mybatis log mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
1.3 create database tables. Generating code generators using tables
1.3.1 SQL statement of database
CREATE TABLE `crm_banner` ( `id` CHAR(19) NOT NULL DEFAULT '' COMMENT 'ID', `title` VARCHAR(20) DEFAULT '' COMMENT 'title', `image_url` VARCHAR(500) NOT NULL DEFAULT '' COMMENT 'Picture address', `link_url` VARCHAR(500) DEFAULT '' COMMENT 'Link address', `sort` INT(10) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'sort', `is_deleted` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Logical deletion 1( true)Deleted, 0( false)Not deleted', `gmt_create` DATETIME NOT NULL COMMENT 'Creation time', `gmt_modified` DATETIME NOT NULL COMMENT 'Update time', PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`title`) ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='home page banner surface'; # # 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');
1.3.2 code generator
@Test public void run() { // 1. Create code generator AutoGenerator mpg = new AutoGenerator(); // 2. Global configuration GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir("D:\\Shang Silicon Valley online education project\\Online education--Grain College\\Project source code\\day10\\Back end code\\Back end code\\guli_parent\\service\\service_cms" + "/src/main/java"); gc.setAuthor("smile"); gc.setOpen(false); //Open Explorer after build gc.setFileOverride(false); //Whether the file is overwritten during regeneration //UserServie gc.setServiceName("%sService"); //Remove the initial I of the Service interface gc.setIdType(IdType.ID_WORKER_STR); //Primary key policy gc.setDateType(DateType.ONLY_DATE);//Defines the date type in the generated entity class gc.setSwagger2(true);//Turn on Swagger2 mode mpg.setGlobalConfig(gc); // 3. Data source configuration 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. Package configuration PackageConfig pc = new PackageConfig(); pc.setModuleName("educms"); //Module name //Package com.atguigu.eduservice pc.setParent("com.blb"); //Package com.atguigu.eduservice.controller pc.setController("controller"); pc.setEntity("domain"); pc.setService("service"); pc.setMapper("mapper"); mpg.setPackageInfo(pc); // 5. Policy configuration StrategyConfig strategy = new StrategyConfig(); strategy.setInclude("crm_banner"); strategy.setNaming(NamingStrategy.underline_to_camel);//Naming policy for mapping database tables to entities strategy.setTablePrefix(pc.getModuleName() + "_"); //Remove table prefix when generating entities strategy.setColumnNaming(NamingStrategy.underline_to_camel);//Naming policy for mapping database table fields to entities strategy.setEntityLombokModel(true); // lombok model @ accessories (chain = true) setter chain operation strategy.setRestControllerStyle(true); //restful api style controller strategy.setControllerMappingHyphenStyle(true); //Hump to hyphen in url mpg.setStrategy(strategy); // 6. Execute mpg.execute(); }
1.4 preparation of banner interface
1.4.1. Compilation of background administrator interface
controller layer
@RestController @CrossOrigin @RequestMapping("/educms/banneradmin") public class BannerAdminController { @Autowired private CrmBannerService crmBannerService; //1. Paging query 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()); } //Add banner @PostMapping("/addbanner") public R addBanner(@RequestBody CrmBanner crmBanner) { crmBannerService.save(crmBanner); return R.ok(); } //Query banner by id @GetMapping("/get/{id}") public R getBanner(@PathVariable String id) { CrmBanner crmBanner = crmBannerService.getById(id); return R.ok().data("item",crmBanner); } //Modify banner @PutMapping("/update") public R updateBanner(@RequestBody CrmBanner banner) { crmBannerService.updateById(banner); return R.ok(); } //Delete banner by id @DeleteMapping("/delete/{id}") public R deleteBanner(@PathVariable("id") String id) { crmBannerService.removeById(id); return R.ok(); } }
- Preparation of banner interface for foreground display
controller layer
@RestController @RequestMapping("/educms/bannerfront") @CrossOrigin public class BannerFrontController { @Autowired private CrmBannerService bannerService; //Query all banner s @GetMapping("/getAllBanner") public R getAllBanner() { List<CrmBanner> list= bannerService.selectAllBanner(); return R.ok().data("list",list); } }
Writing of service layer
@Service public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService { @Override public List<CrmBanner> selectAllBanner() { List<CrmBanner> list = baseMapper.selectList(null); return list; } }
1.4.2 compilation of popular courses and famous teachers
Under the module of service_edu, create a controller named IndexFrontController in the controller layer to query popular courses and famous teachers
Create an IndexFrontController class
@RestController @RequestMapping("/eduservice/indexfront") @CrossOrigin public class IndexFrontController { @Autowired private EduCourseService eduCourseService; @Autowired private EduTeacherService eduTeacherService; @GetMapping("/index") public R index() { //Query the top eight popular courses List<EduCourse> courseList =eduCourseService.getFrontClass(); //Query the top four lecturers List<EduTeacher> teacherList= eduTeacherService.getFrontTeacher(); return R.ok().data("courseList",courseList).data("teacherList",teacherList); } }
service implementation
EduCourseServiceImpl
//Query the top eight popular courses @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; } }
2. Homepage data banner display (front end)
2.1 preparation of front page
- Use the command to download the axios dependency npm install axios
- Encapsulating axios
Create a utils folder and create request.sj under the folder
The code in request.js
import axios from 'axios' //Create an axios instance const service = axios.create({ baseURL: 'http://Localhost: 9001 ', / / base_url of API timeout:20000 //Request timeout }) export default service
2.2 banner data display on home page
- Create an aip folder, create a js file in the api folder, and define the path to call the interface
banner.js
import request from '@/utils/request.js' export default{ //Query the first two banner data getListBanner(){ return request({ url: '/educms/bannerfront/getAllBanner', method: 'GET' }) } }
- Call the interface on the page to get the data for display
Call in pages/index.vue
Create bannerList array
Call of banner data
created(){ //Call the method to query the banner this.getBannerList() }, methods:{ //Query banner data getBannerList() { banner.getListBanner() .then(response => { this.bannerList=response.data.data.list }) } }
- Change of rotation chart data
The rotation chart data is changed into the data transmitted from the background
<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>
- nginx routing configuration
Add the address forwarding of the background interface
2.3 display of popular courses and famous teachers
- Add route
Create a file named index.js in the api folder
import request from '@/utils/request.js' export default{ //Query popular courses and famous teachers getIndexData(){ return request({ url: '/eduservice/indexfront/index', method: 'GET' }) } }
- Call the interface on the page to get the data for display
Call in pages/index.vue
Create eduList array and teacherList array
Access interface
//Get popular courses and famous teachers getHotCourseTeacher() { index.getIndexData() .then(response=>{ this.eduList=response.data.data.courseList this.teacherList=response.data.data.teacherList }) }
- Popular courses and famous teachers cycle array display
//Popular courses <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 =" start learning "class =" comm-btn c-btn-1 "> start learning</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">free</i> </span> <span class="fl jgAttr c-ccc f-fA"> <i class="c-999 f-fA">{{course.buyCount}}Human learning</i> | <i class="c-999 f-fA">{{course.viewCount}}comment</i> </span> </section> </div> </li> </ul> //Famous teacher <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>
3. Home page data plus redis
3.1 redis features
- Store based on key value
- Multiple data structures are supported: string, list, hash, set, zset
- It supports persistence and can be stored in memory or hard disk
- Support expiration time and transaction
Generally speaking, it is not particularly important to put the data that is frequently queried and not frequently modified into redis as a cache
3.2 project integration redis
- Introducing dependencies into common's pom
<!-- redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- spring2.X integrate redis what is needed common-pool2--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.0</version> </dependency>
- Add redis configuration information to the service_base
Put it under the com.atguigu.servicebase package
Create a RedisConfig class
@Configuration //Configuration class @EnableCaching //Enable cache 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 serialization method template.setKeySerializer(redisSerializer); //value serialization template.setValueSerializer(jackson2JsonRedisSerializer); //value hashmap serialization template.setHashValueSerializer(jackson2JsonRedisSerializer); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer<String> redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //Solve the problem of query cache conversion exception ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // Configure serialization (solve the problem of garbled code), and the expiration time is 600 seconds 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; } }
3.3 add redis cache in the interface
Because the data in the home page does not change very frequently and the home page has a large number of visits, it is necessary to cache the data of the home page interface into the redis cache to reduce the pressure on the database and improve the access speed
Transform the banner interface of service CMS home page
3.3.1 redis caches annotations in Spring Boot
-
Cache @ Cacheable
Cache the returned results according to the method. In the next request, if the cache exists, directly read the cache data and return; if the cache does not exist, execute the method and store the returned results in the cache. It is generally used in query methods. View the source code, and the attribute values are as follows:
-
Cache @ CachePut
The method using this annotation flag will be executed every time and the results will be stored in the specified cache. Other methods can directly read the cached data from the response cache without querying the database. It is generally used for adding new methods.
View the source code. The attribute values are as follows:
(3) Cache @ CacheEvict
The method using this annotation flag will empty the specified cache. It is generally used in update or delete methods
View the source code. The attribute values are as follows:
Add redis configuration in application.properties
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 #Maximum blocking waiting time (negative number indicates no limit) spring.redis.lettuce.pool.max-idle=5 spring.redis.lettuce.pool.min-idle=0
Redis add
Add redis in the CrmBannerServiceImpl interface
@Service public class CrmBannerServiceImpl extends ServiceImpl<CrmBannerMapper, CrmBanner> implements CrmBannerService { @Cacheable(value = "banner",key = "'selectIndexList'") @Override public List<CrmBanner> selectAllBanner() { //Sort and query the first two pieces of data in descending order by id QueryWrapper<CrmBanner> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("id"); //Splicing SQL statements with last method queryWrapper.last("limit 2"); List<CrmBanner> list = baseMapper.selectList(queryWrapper); return list; } }