1. 程式人生 > >部落格開發總結之後臺程式碼

部落格開發總結之後臺程式碼

寫這個部落格專案也是我第一次使用Spring Boot框架,用過之後,發現真的回不去了。省去了一大堆配置檔案,簡直不能再爽。之前用Spring MVC,Spring,Hibernate,MyBatis等框架,繁瑣的配置檔案,每一個專案都是那一套,感覺不是在學框架內容,而是在學寫配置檔案。Spring Boot成功解決了這一難題,所以上手後寫起來也很順利。

專案搭建初期,就是構思資料庫的表結構。因為是第一次獨自開發專案,很多地方都沒有考慮到,建表時也一再回憶資料庫的一、二、三正規化,而表也是在開發過程中修改了好幾次。因為使用的是MyBatis,為了方便和避免重複造輪子,直接使用逆向工程生成實體類、介面和配置檔案,而每一次修改表結構,都要再重新生成。但是在Service層個別方法中,已經用到了Dao的屬性,如果想要大改資料表,很多程式碼就都要重寫,所以有一些表還是沒有達到滿意的程度。希望在下次寫專案之前,先把整體架構和需求明確。

資料庫的表生成用的是powerdesigner,表結構如下:

CREATE TABLE `blog_category` (
  `id` tinyint(4) NOT NULL,
  `name` varchar(255) NOT NULL,
  `status` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `blog_category_dictionary` (
  `id` tinyint(4) NOT NULL,
  `parent_id` tinyint(4) NOT NULL DEFAULT '0',
  `name` varchar(255) NOT NULL,
  `status` tinyint(4) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `blog_content` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category` varchar(128) NOT NULL,
  `author` varchar(32) NOT NULL,
  `title` varchar(32) NOT NULL,
  `content` text NOT NULL,
  `abstracts` varchar(255) DEFAULT NULL,
  `tags` varchar(8) NOT NULL,
  `createtime` datetime NOT NULL,
  `updatetime` datetime NOT NULL,
  `readtimes` int(32) unsigned NOT NULL DEFAULT '0',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '-1 下架 0 待審 1 釋出 ',
  PRIMARY KEY (`id`),
  KEY `category` (`category`),
  KEY `author` (`author`),
  KEY `tags` (`tags`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2030 DEFAULT CHARSET=utf8;

CREATE TABLE `blog_index_content` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL,
  `filename` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `blog_tag` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8;

CREATE TABLE `blog_timeline` (
  `id` int(16) NOT NULL AUTO_INCREMENT,
  `event_name` varchar(32) DEFAULT NULL,
  `event_content` varchar(64) DEFAULT NULL,
  `event_date` date DEFAULT NULL,
  `event_time` time DEFAULT NULL,
  `user` char(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

CREATE TABLE `blog_user` (
  `id` char(32) NOT NULL,
  `username` varchar(128) NOT NULL,
  `password` varchar(128) NOT NULL,
  `email` varchar(128) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `createtime` varchar(32) DEFAULT NULL,
  `profile` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

根據需求確定表結構之後就開始寫程式碼,首先是Controller層,起碼要可以顯示頁面。

@Controller
@RequestMapping("/admin")
public class ShowPageController {
    @GetMapping({"", "/index"})
    public String showIndex() {
        return "admin/index";
    }
}

@GetMapping @PostMapping ,分別用來接收兩種不同的 request請求 ,在類上加 @RequestMapping("/admin")

,類中所有請求都是以 /admin 開頭。

其他增刪改查的方法無非Controller呼叫Service,Service呼叫Dao,不再贅述。

有一個插入資料後需要獲取自增長id的需求。

在釋出新文章時,需要給文章新增標籤,因為標籤被拆分為單獨的一個表blog_tag,在blog_content表中儲存的是blog_tag的主鍵值,當發表文章輸入標籤時,如果標籤已經存在,就直接返回標籤id,如果id不存在,就插入一個標籤然後返回id。

public Integer getTagIdByName(String tagName) {
    BlogTagExample tagExample = new BlogTagExample();
    BlogTagExample.Criteria criteria = tagExample.createCriteria();
    criteria.andNameEqualTo(tagName);
    List<BlogTag> tags = tagMapper.selectByExample(tagExample);
    if (tags.size() == 0) {
        BlogTag newTag = new BlogTag();
        newTag.setName(tagName);
        tagMapper.insertAndGetId(newTag);
        return newTag.getId();
    }
    return tags.get(0).getId();
}

BlogTagMapper.xml : insertAndGetId()

<insert id="insertAndGetId" parameterType="com.myblog.website.entity.BlogTag">
    <selectKey keyColumn="id" resultType="int" order="AFTER" keyProperty="id">
        SELECT LAST_INSERT_ID()
    </selectKey>
    insert into blog_tag(name) values(#{name})
</insert>

Spring Boot定時器功能:

在使用者訪問文章時,當每次傳送請求,文章的閱讀數就會加1,如果不加以限制,頁面一直重新整理數量就一致增長。這不符合平常的使用場景,想到一個解決辦法就是用HashMap物件,key為當前使用者的 ip + 文章id ,value為最後一次訪問時間,當用戶再次訪問同一文章時,如果最後一次訪問的時間與當前時間的差值小於規定時間,則更新value為當前時間,文章閱讀數不會增加;反之,文章閱讀數加1,更新value為當前時間。

ContentUtils.setReadTimes(request.getRemoteAddr() + "-" + id, contentService, new ReadTimesEntity(content.getId(), content.getReadtimes()));
public static void setReadTimes(String ip, ContentService contentService,,IndexController.ReadTimesEntity entity) {
    if (!lookContent.containsKey(ip)) {
        contentService.updateReadtimes(entity.getId(), entity.getReadtimes());
    }
    lookContent.put(ip, new Date());
}
@Scheduled(cron = "0 0/10 * * * ? ")
private static void clearLookContent(){
    Set<Map.Entry<String, Date>> entries = lookContent.entrySet();
    Iterator<Map.Entry<String, Date>> iterator = entries.iterator();
    while (iterator.hasNext()) {
        Map.Entry<String, Date> ele = iterator.next();
        Date preDate = ele.getValue();
        if (System.currentTimeMillis() - preDate.getTime() >= 3600000) {
            iterator.remove();
        }
    }
}

上述程式碼中,當key不存在,新建key,並把當前時間作為value,如果key存在,則更新當前時間為value。

clearLookContent()方法,每十分鐘執行一次,遍歷HashMap,當value中的時間與當前時間相差一小時以上,就清除這個鍵值對,這樣當用戶下次訪問時,與如果間隔超過一個小時,文章的閱讀數就會加一。