加入Spring-chache缓存处理

master
barney 2 years ago
parent 4c3cdd2eba
commit d2f7468acd
  1. 9
      pom.xml
  2. 3
      src/main/java/cc/bnblogs/Application.java
  3. 27
      src/main/java/cc/bnblogs/common/DefaultImages.java
  4. 52
      src/main/java/cc/bnblogs/config/CacheConfig.java
  5. 6
      src/main/java/cc/bnblogs/config/ExceptionConfig.java
  6. 2
      src/main/java/cc/bnblogs/controller/AdminController.java
  7. 34
      src/main/java/cc/bnblogs/controller/IndexController.java
  8. 5
      src/main/java/cc/bnblogs/mapper/ArticleMapper.java
  9. 4
      src/main/java/cc/bnblogs/mapper/NavigationMapper.java
  10. 18
      src/main/java/cc/bnblogs/mapper/TagMapper.java
  11. 3
      src/main/java/cc/bnblogs/pojo/Article.java
  12. 3
      src/main/java/cc/bnblogs/pojo/Banner.java
  13. 3
      src/main/java/cc/bnblogs/pojo/Category.java
  14. 3
      src/main/java/cc/bnblogs/pojo/Comment.java
  15. 3
      src/main/java/cc/bnblogs/pojo/Friends.java
  16. 3
      src/main/java/cc/bnblogs/pojo/Navigation.java
  17. 3
      src/main/java/cc/bnblogs/pojo/Tag.java
  18. 16
      src/main/java/cc/bnblogs/service/ArticleService.java
  19. 13
      src/main/java/cc/bnblogs/service/BannerService.java
  20. 8
      src/main/java/cc/bnblogs/service/FriendsService.java
  21. 17
      src/main/java/cc/bnblogs/service/NavigationService.java
  22. 20
      src/main/java/cc/bnblogs/service/TagService.java
  23. 11
      src/main/resources/application.yml
  24. 25
      src/main/resources/ehcache-spring.xml
  25. 8
      src/main/resources/templates/admin/article.html
  26. 2
      src/main/resources/templates/admin/common.html
  27. 4
      src/main/resources/templates/admin/write.html
  28. 139
      src/main/resources/templates/common.html
  29. 33
      src/main/resources/templates/index.html
  30. 27
      src/test/java/cc/bnblogs/test/ImageTest.java

@ -59,6 +59,15 @@
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!--引入springboot-cache的依赖及ehcache的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
</dependencies>
<build>

@ -2,11 +2,14 @@ package cc.bnblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/16
*/
@EnableCaching
@SpringBootApplication
public class Application {
public static void main(String[] args) {

@ -0,0 +1,27 @@
package cc.bnblogs.common;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.thymeleaf.util.StringUtils;
import java.util.List;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/20
*/
@Component
@Data
@ConfigurationProperties(prefix = "default-images")
public class DefaultImages {
private List<String> images;
public String cover(String imgUrl) {
if (StringUtils.isEmptyOrWhitespace(imgUrl)) {
// 返回一张随机图
return images.get((int)(Math.random() * images.size()));
}
return imgUrl;
}
}

@ -0,0 +1,52 @@
package cc.bnblogs.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.util.StringUtils;
import java.io.Serializable;
import java.util.Arrays;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/20
*/
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> new BlogCacheKey(target.getClass().getName(), method.getName(), params);
}
static class BlogCacheKey implements Serializable {
private final String className;
private final String methodName;
private final Object[] params;
private final int hashCode;
public BlogCacheKey(String className, String methodName, Object[] params) {
this.className = className;
this.methodName = methodName;
this.params = params;
String sign = className + "_" + methodName + "_" + Arrays.deepHashCode(params);
this.hashCode = sign.hashCode();
}
@Override
public int hashCode() {
return this.hashCode;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof BlogCacheKey)) return false;
BlogCacheKey other = (BlogCacheKey) obj;
if (this.hashCode == other.hashCode) return true;
return StringUtils.equals(this.className, other.className)
&& StringUtils.equals(this.methodName, other.methodName)
&& Arrays.deepEquals(this.params, other.params);
}
}
}

@ -1,6 +1,7 @@
package cc.bnblogs.config;
import cc.bnblogs.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ -9,12 +10,15 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author zfp@bnblogs.cc
* @createTime: 2022/10/19
*/
@Slf4j
@ControllerAdvice
public class ExceptionConfig {
@ResponseBody
@ExceptionHandler(Exception.class)
public Result<String> defaultException() {
public Result<String> defaultException(Exception e) {
e.printStackTrace();
log.error(e.getMessage(),e);
return Result.error();
}
}

@ -74,7 +74,7 @@ public class AdminController {
Article article = Objects.isNull(id) ? Article.builder().allowComment(1).build() : articleService.detail(id);
model.addAttribute("categories",categories);
model.addAttribute("article",article);
model.addAttribute("title", Objects.isNull(article.getId()) ? "创建新文章" : "编辑文章<" + article.getTitle() + '>');
model.addAttribute("pageTitle", Objects.isNull(article.getId()) ? "创建新文章" : "编辑文章---" + article.getTitle());
return "admin/write";
}
}

@ -1,7 +1,10 @@
package cc.bnblogs.controller;
import cc.bnblogs.service.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
/**
@ -10,9 +13,38 @@ import org.springframework.web.bind.annotation.PathVariable;
*/
@Controller
public class IndexController {
private final FriendsService friendsService;
private final NavigationService navigationService;
private final TagService tagService;
private final ArticleService articleService;
private final BannerService bannerService;
public IndexController(FriendsService friendsService, NavigationService navigationService,
TagService tagService, ArticleService articleService, BannerService bannerService) {
this.friendsService = friendsService;
this.navigationService = navigationService;
this.tagService = tagService;
this.articleService = articleService;
this.bannerService = bannerService;
}
@ModelAttribute
private void indexModel(Model model) {
// todo 可以在这里定义这个controller公用的model的属性
model.addAttribute("friends",friendsService.list());
model.addAttribute("navigations",navigationService.show());
model.addAttribute("tags",tagService.show((int)tagService.count()));
model.addAttribute("hots",articleService.hotList(5));
}
// 前台访问路由
@GetMapping("/")
public String index() {
public String index(Model model) {
model.addAttribute("banners",bannerService.list());
return "index";
}

@ -3,10 +3,15 @@ package cc.bnblogs.mapper;
import cc.bnblogs.pojo.Article;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/17
*/
public interface ArticleMapper extends JpaRepository<Article,Integer>, JpaSpecificationExecutor<Article>{
@Query(value = "select * from blog_article where type=1 and status=1 order by views limit ?1", nativeQuery = true)
List<Article> hotList(int limit);
}

@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import javax.transaction.Transactional;
import java.util.List;
/**
* @author zfp@bnblogs.cc
@ -21,4 +22,7 @@ public interface NavigationMapper extends JpaRepository<Navigation,Integer> {
@Modifying
@Query("update Navigation set ordered = ?2 where id = ?1")
void ordered(Integer id, Integer ordered);
List<Navigation> findAllByEnableOrderByOrderedAsc(Boolean enable);
}

@ -2,10 +2,26 @@ package cc.bnblogs.mapper;
import cc.bnblogs.pojo.Tag;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import javax.persistence.criteria.CriteriaBuilder;
import java.util.List;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/17
*/
public interface TagMapper extends JpaRepository<Tag,Integer> {
public interface TagMapper extends JpaRepository<Tag, Integer> {
@Query(value = "SELECT * FROM blog_tag\n" +
"WHERE\n" +
" id >= ( SELECT FLOOR(\n" +
" RAND() \n" +
" * (\n" +
" (SELECT MAX( id ) FROM blog_tag ) -\n" +
" (SELECT MIN( id ) FROM blog_tag )\n" +
" ) \n" +
" + ( SELECT MIN( id ) FROM blog_tag ))\n" +
" ) \n" +
"ORDER BY id LIMIT ?1",nativeQuery = true)
List<Tag> findRandom(int limit);
}

@ -3,6 +3,7 @@ package cc.bnblogs.pojo;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@ -16,7 +17,7 @@ import java.util.List;
@Builder
@Entity
@Table(name = "blog_article")
public class Article {
public class Article implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author zfp@bnblogs.cc
@ -17,7 +18,7 @@ import javax.persistence.*;
@Builder
@Entity
@Table(name = "blog_banner")
public class Banner {
public class Banner implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author zfp@bnblogs.cc
@ -17,7 +18,7 @@ import javax.persistence.*;
@NoArgsConstructor
@AllArgsConstructor
@Table(name="blog_category")
public class Category {
public class Category implements Serializable {
/**
* 分类id(主键)
* 主键自增

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
@ -18,7 +19,7 @@ import java.util.Date;
@Builder
@Entity
@Table(name = "blog_comment")
public class Comment {
public class Comment implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author zfp@bnblogs.cc
@ -17,7 +18,7 @@ import javax.persistence.*;
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "blog_friends")
public class Friends {
public class Friends implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author zfp@bnblogs.cc
@ -17,7 +18,7 @@ import javax.persistence.*;
@Builder
@Entity
@Table(name = "blog_navigation")
public class Navigation {
public class Navigation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author zfp@bnblogs.cc
@ -17,7 +18,7 @@ import javax.persistence.*;
@Entity
@Builder
@Table(name = "blog_tag")
public class Tag {
public class Tag implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@ -7,6 +7,9 @@ import cc.bnblogs.mapper.TagMapper;
import cc.bnblogs.pojo.Article;
import cc.bnblogs.pojo.Category;
import cc.bnblogs.utils.UpdateUtil;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
@ -29,6 +32,7 @@ import java.util.stream.Collectors;
* @createTime: 2022/10/17
*/
@Service
@CacheConfig(cacheNames = {"blog-cache"})
public class ArticleService {
private final TagMapper tagMapper;
private final ArticleMapper articleMapper;
@ -67,6 +71,7 @@ public class ArticleService {
* 保存文章
* @param article 待保存的文章对象
*/
@CacheEvict(allEntries = true)
@Transactional(rollbackFor = {Exception.class})
public void save(Article article) {
// 修改更新时间
@ -109,6 +114,7 @@ public class ArticleService {
* 根据id删除文章对象
* @param id 待删除文章的id
*/
@CacheEvict(allEntries = true)
public void delete(Integer id) {
articleMapper.deleteById(id);
}
@ -142,4 +148,14 @@ public class ArticleService {
return PageHelper.<Article>builder().rows(articlePage.getContent()).total(articlePage.getTotalElements()).build();
}
/**
* 获取一定数量热门文章
* @param limit 最大文章数
* @return 返回热门文章
*/
@Cacheable
public List<Article> hotList(int limit) {
return articleMapper.hotList(limit);
}
}

@ -2,6 +2,9 @@ package cc.bnblogs.service;
import cc.bnblogs.mapper.BannerMapper;
import cc.bnblogs.pojo.Banner;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@ -12,6 +15,7 @@ import java.util.List;
* @createTime: 2022/10/17
*/
@Service
@CacheConfig(cacheNames = {"blog-cache"})
public class BannerService {
private final BannerMapper bannerMapper;
@ -25,6 +29,7 @@ public class BannerService {
* 按照ordered字段升序排序
* @return 轮播图列表
*/
@Cacheable
public List<Banner> list() {
return bannerMapper.findAll(Sort.by(Sort.Direction.ASC,"ordered"));
}
@ -50,6 +55,7 @@ public class BannerService {
* 保存轮播图
* @param banner 待保存的轮播图对象
*/
@CacheEvict(allEntries = true)
public void save(Banner banner) {
bannerMapper.save(banner);
}
@ -58,10 +64,17 @@ public class BannerService {
* 根据id删除轮播图对象
* @param id 待删除轮播图的id
*/
@CacheEvict(allEntries = true)
public void delete(Integer id) {
bannerMapper.deleteById(id);
}
/**
* 轮播图排序
* @param id 轮播图id
* @param ordered 轮播图顺序
*/
@CacheEvict(allEntries = true)
public void order(Integer id, Integer ordered) {
bannerMapper.ordered(id,ordered);
}

@ -2,6 +2,9 @@ package cc.bnblogs.service;
import cc.bnblogs.mapper.FriendsMapper;
import cc.bnblogs.pojo.Friends;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
@ -10,6 +13,7 @@ import java.util.List;
* @author zfp@bnblogs.cc
* @createTime: 2022/10/17
*/
@CacheConfig(cacheNames = {"blog-cache"})
@Service
public class FriendsService {
@ -23,6 +27,7 @@ public class FriendsService {
* 获取所有友链
* @return 友链列表
*/
@Cacheable
public List<Friends> list() {
return friendsMapper.findAll();
}
@ -48,6 +53,8 @@ public class FriendsService {
* 保存友链
* @param friends 带保存的友链对象
*/
// 发生增删操作时删除缓存
@CacheEvict(allEntries = true)
public void save(Friends friends) {
friendsMapper.save(friends);
}
@ -56,6 +63,7 @@ public class FriendsService {
* 根据id删除友链对象
* @param id 待删除友链的id
*/
@CacheEvict(allEntries = true)
public void delete(Integer id) {
friendsMapper.deleteById(id);
}

@ -2,6 +2,9 @@ package cc.bnblogs.service;
import cc.bnblogs.mapper.NavigationMapper;
import cc.bnblogs.pojo.Navigation;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
@ -12,6 +15,7 @@ import java.util.List;
* @createTime: 2022/10/19
*/
@Service
@CacheConfig(cacheNames = {"blog-cache"})
public class NavigationService {
private final NavigationMapper navigationMapper;
@ -49,6 +53,8 @@ public class NavigationService {
* 保存导航条
* @param navigation 待保存的导航条对象
*/
@CacheEvict(allEntries = true)
public void save(Navigation navigation) {
navigationMapper.save(navigation);
}
@ -57,6 +63,7 @@ public class NavigationService {
* 根据id删除导航条对象
* @param id 待删除导航条的id
*/
@CacheEvict(allEntries = true)
public void delete(Integer id) {
navigationMapper.deleteById(id);
}
@ -66,7 +73,17 @@ public class NavigationService {
* @param id 导航条id
* @param ordered 导航条顺序值
*/
@CacheEvict(allEntries = true)
public void order(Integer id, Integer ordered) {
navigationMapper.ordered(id,ordered);
}
/**
* 首页展示的导航条(只显示enable=true)
* @return 显示的导航条
*/
@Cacheable
public List<Navigation> show() {
return navigationMapper.findAllByEnableOrderByOrderedAsc(true);
}
}

@ -2,6 +2,9 @@ package cc.bnblogs.service;
import cc.bnblogs.mapper.TagMapper;
import cc.bnblogs.pojo.Tag;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
@ -11,6 +14,7 @@ import java.util.List;
* @createTime: 2022/10/17
*/
@Service
@CacheConfig(cacheNames = {"blog-cache"})
public class TagService {
private final TagMapper tagMapper;
@ -23,6 +27,7 @@ public class TagService {
* 获取所有标签
* @return 标签列表
*/
@Cacheable
public List<Tag> list() {
return tagMapper.findAll();
}
@ -31,6 +36,7 @@ public class TagService {
* 获取标签总数
* @return 标签总数
*/
@Cacheable
public long count() {
return tagMapper.count();
}
@ -40,6 +46,7 @@ public class TagService {
* @param id 标签id
* @return id对应的标签对象
*/
public Tag detail(Integer id) {
return tagMapper.findById(id).orElse(null);
}
@ -48,6 +55,8 @@ public class TagService {
* 保存标签
* @param tag 待保存的标签对象
*/
@CacheEvict(allEntries = true)
public void save(Tag tag) {
tagMapper.save(tag);
}
@ -56,7 +65,18 @@ public class TagService {
* 根据id删除标签对象
* @param id 待删除标签的id
*/
@CacheEvict(allEntries = true)
public void delete(Integer id) {
tagMapper.deleteById(id);
}
/**
* 随机返回多个标签
* @param limit 标签数量
* @return 标签云
*/
@Cacheable
public List<Tag> show(int limit) {
return tagMapper.findRandom(limit);
}
}

@ -30,6 +30,10 @@ spring:
servlet:
multipart:
max-file-size: 20MB
cache:
type: ehcache
ehcache:
config: classpath:/ehcache-spring.xml
logging:
file:
@ -69,3 +73,10 @@ website:
footer: '© 2020-2022 <a href="https://hugo.bnblogs.cc">barney</a> <a target="_blank" href="https://beian.miit.gov.cn">赣ICP备2022002184号-1</a>
<a style="margin-left: 10px" target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11011402012109"><img style="vertical-align: top;" src="https://imagebed-1252410096.cos.ap-nanjing.myqcloud.com/2046/d4ab98835b8842c88eededac6e7c9e35.png">
赣公网安备 36092202000146号</a>'
default-images:
images:
- /static/image/1.jpg
- /static/image/2.jpg
- /static/image/3.jpg
- /static/image/4.jpg
- /static/image/5.jpg

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
<!-- 磁盘缓存位置 -->
<diskStore path="./cache"/>
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
<!-- timeToIdleSeconds:发呆秒数,发呆期间未访问缓存立即过期,当eternal为false时,这个属性才有效,0为不限制 -->
<!-- timeToLiveSeconds:总存活秒数,当eternal为false时,这个属性才有效,0为不限制 -->
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 -->
<!--
默认缓存
无过期时间,但 3600 秒内无人访问缓存立即过期
-->
<cache name="blog-cache"
maxElementsInMemory="1000"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="true">
</cache>
</ehcache>

@ -112,6 +112,14 @@
return `<a href="javascript:void(0)" data-id="${value.id}" id="selected-category">${value.name}</a>`;
}
},
{
title: '文章类型',
field: 'type',
align: 'center',
formatter: value => {
return value===1 ? "文章": "页面";
}
},
{
title: '浏览量',
field: 'views',

@ -47,7 +47,7 @@
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">退出登录</a></li>
<li><a href="#">网站前台</a></li>
<li><a th:href="@{/}">网站前台</a></li>
</ul>
</div>
</div>

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head th:replace="admin/common::header(~{::title},~{::link},~{::style})">
<title th:text="${title}"></title>
<title th:text="${pageTitle}"></title>
<link rel="stylesheet" href="/static/plugin/editormd/css/editormd.min.css">
<style>
#selected-tags {
@ -54,7 +54,7 @@
<body>
<th:block th:include="admin/common::nav('article')"></th:block>
<div class="container lw-main" style="margin-top: 0">
<div style="padding-left: 10px;font-weight: bold;font-size: 25px;margin-bottom: 15px" th:text="${title}"></div>
<div style="padding-left: 10px;font-weight: bold;font-size: 25px;margin-bottom: 15px" th:text="${pageTitle}"></div>
<div class="row">
<form id="form-data" class="form-horizontal">
<div class="col-md-9">

@ -21,7 +21,7 @@
<nav class="lw-md-show">
<div class="lw-container lw-header lw-posr ">
<div class="lw-logo lw-fl">
<a href="/">
<a th:href="@{/}">
<img th:src="${@webSite.logo eq null or @webSite.logo.length() <= 0}? '/static/image/logo.png': ${@webSite.logo}"
alt="Barney's Blog"
style="width: 70px;height: 70px;"
@ -40,13 +40,12 @@
class="fa fa-envelope" aria-hidden="true"></i></a>
</div>
<div class="lw-nav lw-posa">
<a href="/"><i class="fa fa-home" aria-hidden="true"></i>首页</a>
<a href="#">技术分享</a>
<a href="#">闲言碎语</a>
<a href="#">个人随笔</a>
<a href="#"><i class="fa fa-users" aria-hidden="true"></i>友情链接</a>
<a href="#"><i class="fa fa-user" aria-hidden="true"></i>关于我</a>
<a href="#"><i class="fa fa-edit" aria-hidden="true"></i>留言板</a>
<a th:href="@{/}"><i class="fa fa-home" aria-hidden="true"></i>首页</a>
<!--/*@thymesVar id="navigations" type="java.util.List<cc.bnblogs.pojo.Navigation>"*/-->
<a th:each="navigation:${navigations}" th:href="${navigation.link}" th:target="${navigation.linkMode} ? '_blank' : ''" >
<i th:if="${navigation.icon.length() > 0}" th:class="${'fa fa-'+navigation.icon}"></i>
<th:block th:text="${navigation.name}"></th:block>
</a>
<a href="javascript:void(0)" class="lw-fr lw-search-btn" style="padding: 0;">
<i class="fa fa-search" aria-hidden="true"></i>
</a>
@ -84,54 +83,20 @@
<div class="lw-right-item lw-right-hot">
<h4><i class="fa fa-fire lw-mr5" aria-hidden="true"></i>热门文章</h4>
<ul class="lw-hot-list">
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-danger lw-posa">1</span>
<img src="/static/image/1.jpg" alt="">
</div>
<p class="lw-hot-title">Freewind主题编辑器展示</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 65580 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-warning lw-posa">2</span>
<img src="/static/image/2.jpg" alt="">
</div>
<p class="lw-hot-title">Conda虚拟环境使用</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 56283 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-info lw-posa">3</span>
<img src="/static/image/3.jpg" alt="">
</div>
<p class="lw-hot-title">纯 CSS 图片碎裂动画教程</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 52213 </p>
</a>
</li>
<li>
<a href="#">
<div class="lw-hot-img">
<span class="label label-default lw-posa">4</span>
<img src="/static/image/4.jpg" alt="">
</div>
<p class="lw-hot-title">Spring Boot 3.0 M1 发布</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 23132 </p>
</a>
</li>
<li>
<a href="#">
<!--/*@thymesVar id="hots" type="java.util.List<cc.bnblogs.pojo.Article>"*/-->
<li th:each="hot,it:${hots}">
<a th:href="@{/{id}.html(id=${hot.id})}" target="_blank">
<div class="lw-hot-img">
<span class="label label-default lw-posa">5</span>
<img src="/static/image/5.jpg" alt="">
<span class="label label-danger lw-posa" th:if="${it.index eq 0}">1</span>
<span class="label label-warning lw-posa" th:if="${it.index eq 1}">2</span>
<span class="label label-info lw-posa" th:if="${it.index eq 2}">3</span>
<span class="label label-default lw-posa" th:if="${it.index > 2}" th:text="${it.index+1}"></span>
<img th:src="${@defaultImages.cover(hot.cover)}" alt="">
</div>
<p class="lw-hot-title">异步上传文件显示进度条</p>
<p class="lw-hot-info"><i class="fa-solid fa-fire-flame-curved"></i> 12322 </p>
<p class="lw-hot-title" th:text="${hot.title}"></p>
<p class="lw-hot-info"><i class="fa fa-eye lw-mr5"></i>
<th:block th:text="${hot.views}"></th:block>
</p>
</a>
</li>
</ul>
@ -139,74 +104,16 @@
<div class="lw-right-item lw-tag-cloud">
<h4><i class="fa fa-tags lw-mr5" aria-hidden="true"></i>标签云</h4>
<a href="https://www.kevinlu98.cn/tag/freewind/" title="freewind">
freewind</a>
<a href="https://www.kevinlu98.cn/tag/typecho/" title="typecho">
typecho</a>
<a href="https://www.kevinlu98.cn/tag/%E6%8F%92%E4%BB%B6/" title="插件">
插件</a>
<a href="https://www.kevinlu98.cn/tag/emlog/" title="emlog">
emlog</a>
<a href="https://www.kevinlu98.cn/tag/java/" title="java">
java</a>
<a href="https://www.kevinlu98.cn/tag/%E4%B8%BB%E9%A2%98/" title="主题">
主题</a>
<a href="https://www.kevinlu98.cn/tag/%E8%87%AA%E7%94%B1%E4%B9%8B%E9%A3%8E/" title="自由之风">
自由之风</a>
<a href="https://www.kevinlu98.cn/tag/%E5%9B%BE%E5%BA%8A/" title="图床">
图床</a>
<a href="https://www.kevinlu98.cn/tag/%E5%86%B7%E6%96%87%E5%9B%BE%E5%BA%8A/" title="冷文图床">
冷文图床</a>
<a href="https://www.kevinlu98.cn/tag/markdown/" title="markdown">
markdown</a>
<a href="https://www.kevinlu98.cn/tag/gitee/" title="gitee">
gitee</a>
<a href="https://www.kevinlu98.cn/tag/springboot/" title="springboot">
springboot</a>
<a href="https://www.kevinlu98.cn/tag/linux/" title="linux">
linux</a>
<a href="https://www.kevinlu98.cn/tag/mac/" title="mac">
mac</a>
<a href="https://www.kevinlu98.cn/tag/%E5%AD%A6%E4%B9%A0/" title="学习">
学习</a>
<a href="https://www.kevinlu98.cn/tag/python/" title="python">
python</a>
<a href="https://www.kevinlu98.cn/tag/conda/" title="conda">
conda</a>
<a href="https://www.kevinlu98.cn/tag/%E7%9B%B8%E5%86%8C/" title="相册">
相册</a>
<a href="https://www.kevinlu98.cn/tag/jsDelivr/" title="jsDelivr">
jsDelivr</a>
<a href="https://www.kevinlu98.cn/tag/cdn/" title="cdn">
cdn</a>
<a href="https://www.kevinlu98.cn/tag/codemirror/" title="codemirror">
codemirror</a>
<a href="https://www.kevinlu98.cn/tag/freedom/" title="freedom">
freedom</a>
<a href="https://www.kevinlu98.cn/tag/%E8%85%BE%E8%AE%AFcos/" title="腾讯cos">
腾讯cos</a>
<a href="https://www.kevinlu98.cn/tag/cos/" title="cos">
cos</a>
<a href="https://www.kevinlu98.cn/tag/%E7%A7%81%E4%BA%BA%E5%9B%BE%E5%BA%8A/" title="私人图床">
私人图床</a>
<a href="https://www.kevinlu98.cn/tag/%E6%AC%A2%E8%BF%8E%E9%A1%B5/" title="欢迎页">
欢迎页</a>
<a href="https://www.kevinlu98.cn/tag/%E7%99%BB%E5%BD%95%E6%B3%A8%E5%86%8C/" title="登录注册">
登录注册</a>
<a href="https://www.kevinlu98.cn/tag/%E6%95%99%E7%A8%8B%E4%B8%8B%E8%BD%BD/" title="教程下载">
教程下载</a>
<a href="https://www.kevinlu98.cn/tag/itjc8/" title="itjc8">
itjc8</a>
<a href="https://www.kevinlu98.cn/tag/%E8%99%9A%E6%8B%9F%E6%9C%BA/" title="虚拟机">
虚拟机</a>
<!--/*@thymesVar id="tags" type="java.util.List<cc.bnblogs.pojo.Tag>"*/-->
<a th:each="tag:${tags}" href="#" th:title="${tag.name}" th:text="${tag.name}"></a>
</div>
</th:block>
<th:block th:fragment="footer">
<div class="lw-friend-link">
<div class="lw-container">
<h2>友情链接</h2>
<a href="https://hugo.bnblogs.cc">Barney's Blog</a>
<a href="https://zhihu.com">知乎</a>
<!--/*@thymesVar id="friends" type="java.util.List<cc.bnblogs.pojo.Friends>"*/-->
<a th:each="friend:${friends}" target="_blank" th:href="${friend.link}" th:text="${friend.title}"></a>
</div>
</div>
<footer th:utext="${@webSite.footer}"></footer>

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html" lang="en">
<head th:replace="common::header(~{::title},~{::link},~{::style})">
<title th:text="${'首页 - ' + @webSite.title}"></title>
@ -42,30 +42,15 @@
<div class="lw-left-list">
<div class="swiper mySwiper lw-swiper">
<div class="swiper-wrapper">
<div class="swiper-slide lw-posr">
<img src="/static/image/banner/1.jpg" alt="" srcset="">
<div class="swiper-slide lw-posr" th:each="banner:${banners}">
<img th:src="${banner.cover}" th:alt="${banner.title}" srcset="">
<div class="lw-banner-info lw-posa">
<a href="#"><h2 class="lw-text-hidden"><span class="label label-danger lw-mr5">站长推荐</span>Freewind
一一typecho主题
</h2></a>
<p>仅700多k的体积,拥有相册、说说、时间轴、友链、更换配色等功能,了解更多请移步至官网查看...</p>
</div>
</div>
<div class="swiper-slide lw-posr">
<img src="/static/image/banner/2.jpg" alt="" srcset="">
<div class="lw-banner-info lw-posa">
<a href="#"><h2 class="lw-text-hidden"><span class="label label-danger lw-mr5">站长推荐</span>Freewind主题编辑器功能
</h2></a>
<p>Freewind主题终于迎来了1.4的更新,同时也有了自己的编辑器,编辑器基于
codemirror这款开源产品进行开发,同时也将编辑器抽出了一个项目,大家有兴趣可以参考...</p>
</div>
</div>
<div class="swiper-slide lw-posr">
<img src="/static/image/banner/3.jpg" alt="" srcset="">
<div class="lw-banner-info lw-posa">
<a href="#"><h2 class="lw-text-hidden"><span class="label label-danger lw-mr5">站长推荐</span>冷文图床(腾讯COS)-个人版
</h2></a>
<p>一款基于腾讯COS的图床源码,采用java编写,有部署教程...</p>
<a th:href="${banner.link}">
<h2 class="lw-text-hidden"><span class="label label-danger lw-mr5">站长推荐</span>
<th:block th:text="${banner.title}"></th:block>
</h2>
</a>
<p th:text="${banner.summary}"></p>
</div>
</div>
</div>

@ -0,0 +1,27 @@
package cc.bnblogs.test;
import cc.bnblogs.Application;
import cc.bnblogs.common.DefaultImages;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author zfp@bnblogs.cc
* @createTime: 2022/10/20
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ImageTest {
@Autowired
private DefaultImages images;
@Test
public void getImage() {
System.out.println(images.cover("111"));
System.out.println(images.cover(""));
}
}
Loading…
Cancel
Save