对于程序中一些字典信息、配置信息应该在程序启动时加载到缓存中,用时先到缓存中取,如果没有命中,再到数据库中获取同时放到缓存中,这样做可以减轻数据库层的压力。目前暂时先整合ehcache缓存,同时预留了集成redis和memcached的接口。

先开发两个最基本的功能,就是注册和登录,对于页面几乎就是直接用bootstrap的风格,目前没有过多的设计。

1、整合ehcache

在spring boot中整合ehcache还是很方便的,首先添加依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency> <dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.2</version>
</dependency>

新增ehcache的配置文件,ehcache.xml,即:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd"
updateCheck="false"
monitoring="autodetect"
dynamicConfig="true"> <diskStore path="java.io.tmpdir" /> <!-- 系统临时缓存(十分钟) -->
<cache
name="SystemTempCache"
maxEntriesLocalHeap="0"
maxEntriesLocalDisk="10000000"
eternal="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
diskSpoolBufferSizeMB="30"
memoryStoreEvictionPolicy="LRU">
</cache> <!-- 系统永久缓存 -->
<cache
name="SystemEternalCache"
maxEntriesLocalHeap="0"
maxEntriesLocalDisk="10000000"
eternal="true"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
diskSpoolBufferSizeMB="30"
memoryStoreEvictionPolicy="LRU">
</cache> </ehcache>

其中设置了两种缓存类型,一个是临时缓存,另一个是永久缓存。

此处使用缓存方式不是基于注解的,虽然基于注解的方式也很方便,但是个人觉得还是自己程序控制缓存好一些。

程序中会将站点的配置信息加载到缓存中,那么使用方式如下:

(1)、首先定义一个缓存接口,本程序中需要用到缓存的,必须实现该接口,即:

package com.swnote.common.cache;

/**
* 缓存接口
*
* @author lzj
* @since 1.0
* @date [2019-04-27]
*/
public interface ICache<T> {
/**
* 根据key获取缓存数据
*
* @param key
* @return
*/
public T get(Object key); /**
* 存放缓存数据
*
* @param key
* @param value
*/
public void put(Object key, T value); /**
* 根据key移除内容
*
* @param key
*/
public void remove(Object key);
}

(2)、站点配置信息缓存ConfigCache,实现该接口,即:

package com.swnote.common.cache;

import com.swnote.common.domain.Config;
import com.swnote.common.service.IConfigService;
import com.swnote.common.util.Const;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;
import java.util.List; /**
* 缓存配置信息
* 配置信息放到系统永久缓存中,存放形式为:"_CONFIG" + configId为key,value为配置信息对象
*
* @author lzj
* @since 1.0
* @date [2019-04-27]
*/
@Slf4j
@DependsOn("configService")
@Component("configCache")
public class ConfigCache implements ICache<Config> { /**
* 注入基于Spring提供的Cache接口实例,默认由Ehcache实现
* TODO 以后也可以是Redis、Memcached提供实现
*/
@Autowired
private CacheManager cacheManager; @Autowired
private IConfigService configService; /**
* 系统临时缓存实例
*/
private Cache cache; /**
* key的前缀
*/
private String keyPrefix = "_CONFIG"; @PostConstruct
public void init() {
// 获取系统永久缓存实例
cache = cacheManager.getCache(Const.CACHE_SYSTEM_ETERNAL);
log.info("获取系统永久缓存实例"); log.info("开始加载所有配置信息");
List<Config> configs = configService.list();
if (configs != null && !configs.isEmpty()) {
configs.stream().forEach(config -> cache.put(keyPrefix + config.getConfigId(), config));
}
log.info("加载完毕所有配置信息");
} @Override
public Config get(Object key) {
Cache.ValueWrapper valueWrapper = cache.get(keyPrefix + key);
if (valueWrapper == null) {
// 此时从数据库重新加载一次
Config config = configService.getById((String) key);
if (config == null) {
return null;
} // 再次放到缓存中
cache.put(keyPrefix + config.getConfigId(), config); return config;
}
return (Config) valueWrapper.get();
} @Override
public void put(Object key, Config value) {
cache.put(keyPrefix + key, value);
} @Override
public void remove(Object key) {
cache.evict(keyPrefix + key);
}
}

2、注册功能

注册页面效果如下:

页面风格很素,这个暂时先这样。

主要看一下UserController中处理注册信息的关键代码,即:

/**
* 保存注册信息
*
* @param model
* @param request
* @return
*/
@RequestMapping(value = "/auth/signup", method = RequestMethod.POST)
@ResponseBody
public Result signup(Model model, HttpServletRequest request) {
Result result = new Result();
try {
// 接收参数
String name = request.getParameter("name");
String email = request.getParameter("email");
String password = request.getParameter("password"); // 简单校验
if (StringUtils.isEmpty(name) || StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {
throw new TipException("缺少必要请求参数");
} if (!StringUtil.isEmail(email)) {
throw new TipException("邮箱不符全规范");
} // 校验用户名
User tempUser = userService.getByName(name);
if (tempUser != null && !StringUtils.isEmpty(tempUser.getUserId())) {
throw new TipException("该用户已经注册了");
} // 校验邮箱
tempUser = userService.getByEmail(email);
if (tempUser != null && !StringUtils.isEmpty(tempUser.getUserId())) {
throw new TipException("该邮箱已经注册了");
} // 获取用户ip
String ip = HttpUtil.getIpAddr(request); // 构建用户信息
User user = new User();
user.setLoginName(name);
user.setEmail(email);
user.setPassword(StringUtil.md5(password));
user.setCreateIp(ip); // 保存用户信息
boolean flag = userService.create(user);
if (!flag) {
throw new TipException("用户创建失败");
} result.setCode(Result.CODE_SUCCESS);
result.setMsg("用户创建成功");
} catch (Exception e) {
log.error("用户创建失败", e);
result.setCode(Result.CODE_EXCEPTION);
result.setMsg("用户创建失败");
}
return result;
}

在UserService中有一个create方法,即:

@Override
public boolean create(User user) {
// 获取当前时间
Date now = new Date(); // 设置主键
user.setUserId(IdGenarator.guid());
// 设置未实名认证
user.setRealStatus(User.REAL_STATUS_NO); // 用户是否需要激活
Config config = configCache.get(Const.CONFIG_USER_ACTIVE);
if (config != null && "1".equals(config.getConfigValue())) {
// TODO 发送激活邮件信息
// 说明需要激活
user.setIsActive(User.ACTIVE_NO);
} else {
// 说明不需要激活,默认激活
user.setIsActive(User.ACTIVE_YES);
} // 设置启用账号状态
user.setStatus(User.STATUS_YES);
// 设置创建时间
user.setCreateTime(now);
// 设置关注数为0
user.setFollows(0);
// 设置粉丝数为0
user.setFans(0);
return save(user);
}

此处有一个还没有实现的功能,就是发送激活邮件信息,这个功能后面会补上,这里先处于TODO状态。

3、登录功能

登录页面效果如下:

UserController中关键的代码如下:

/**
* 处理登录信息
*
* @param request
* @return
*/
@RequestMapping(value = "/auth/login", method = RequestMethod.POST)
@ResponseBody
public Result login(HttpServletRequest request, HttpSession session) {
Result result = new Result();
try {
// 接收参数
String name = request.getParameter("name");
String password = request.getParameter("password"); if (StringUtils.isEmpty(name) || StringUtils.isEmpty(password)) {
throw new TipException("缺少必要请求参数");
} // 获取用户ip
String ip = HttpUtil.getIpAddr(request); User user = userService.verifyUser(name, password, ip);
if (user == null) {
throw new TipException("用户名或密码错误");
} // 放置session信息
session.setAttribute(Const.SESSION_USER, user); // TODO 还有一些相关统计信息,后面再加上 result.setCode(Result.CODE_SUCCESS);
result.setMsg("登录成功");
} catch (TipException e) {
result.setCode(Result.CODE_EXCEPTION);
result.setMsg(e.getMessage());
} catch (Exception e) {
log.error("登录失败", e);
result.setCode(Result.CODE_EXCEPTION);
result.setMsg("登录失败");
}
return result;
}

当用户登录时,还有一些相关统计信息,这里由于其它功能还没有开发完,所以获取统计信息的代码后面再加上。

关注我

以你最方便的方式关注我:

微信公众号:

基于SpringBoot从零构建博客网站 - 整合ehcache和开发注册登录功能的更多相关文章

  1. 基于SpringBoot从零构建博客网站 - 集成editor.md开发发布文章功能

    发布文章功能里面最重要的就是需要集成富文本编辑器,目前富文本编辑器有很多,例如ueditor,CKEditor.editor.md等.这里守望博客里面是集成的editor.md,因为editor.md ...

  2. 基于SpringBoot从零构建博客网站 - 整合lombok和mybatis-plus提高开发效率

    在上一章节中<技术选型和整合开发环境>,确定了开发的技术,但是如果直接这样用的话,可能开发效率会不高,为了提高开发的效率,这里再整合lombok和mybatis-plus两个组件. 1.l ...

  3. 基于SpringBoot从零构建博客网站 - 技术选型和整合开发环境

    技术选型和整合开发环境 1.技术选型 博客网站是基于SpringBoot整合其它模块而开发的,那么每个模块选择的技术如下: SpringBoot版本选择目前较新的2.1.1.RELEASE版本 持久化 ...

  4. 基于SpringBoot从零构建博客网站 - 确定需求和表结构

    要确定一个系统的需求,首先需要明确该系统的用户有哪些,然后针对每一类用户,确定其需求.对于博客网站来说,用户有3大类,分别是: 作者,也即是注册用户 游客,也即非注册用户 管理员,网站维护人员 那么从 ...

  5. 基于SpringBoot从零构建博客网站 - 新增创建、修改、删除专栏功能

    守望博客是支持创建专栏的功能,即可以将一系列相关的文章归档到专栏中,方便用户管理和查阅文章.这里主要讲解专栏的创建.修改和删除功能,至于专栏还涉及其它的功能,例如关注专栏等后续会穿插着介绍. 1.创建 ...

  6. 基于SpringBoot从零构建博客网站 - 设计可扩展上传模块和开发修改头像密码功能

    上传模块在web开发中是很常见的功能也是很重要的功能,在web应用中需要上传的可以是图片.pdf.压缩包等其它类型的文件,同时对于图片可能需要回显,对于其它文件要能够支持下载等.在守望博客系统中对于上 ...

  7. 基于SpringBoot从零构建博客网站 - 开发设置主页标识和修改个人信息功能

    由于守望博客系统中支持由用户自己设置个人主页的URL的后半段,所以必须要用户设置该标识的功能,而且是用户注册登录之后自动弹出的页面,如果用户没有设置该标识,其它的操作是不能够操作的,同时要求主页标识只 ...

  8. 基于SpringBoot从零构建博客网站 - 开发文章详情页面

    文章详情页面是博客系统中最为重要的页面,登录用户与游客都可以浏览文章详情页面,只不过只有登录用户才能进行其它的一些操作,比如评论.点赞和收藏等等. 本次的开发任务只是将文章详情页面展示出来,至于一些收 ...

  9. 基于SpringBoot从零构建博客网站 - 分页显示文章列表功能

    显示文章列表一般都是采用分页显示,比如每页10篇文章显示.这样就不用每次就将所有的文章查询出来,而且当文章数量特别多的时候,如果一次性查询出来很容易出现OOM异常. 后台的分页插件采用的是mybati ...

随机推荐

  1. 015_linuxC++之_覆写

    34.类成员函数的重载.覆盖和隐藏区别?答案:a.成员函数被重载的特征:(1)相同的范围(在同一个类中):(2)函数名字相同:(3)参数不同:(4)virtual 关键字可有可无.b.覆盖是指派生类函 ...

  2. 无法识别的配置节点 applicationSettings/* Properties.Settings 解决方法

    http://blog.csdn.net/yaoxtao/article/details/7766888 在项目中引用web service时,偶然出现 无法识别的配置节点 applicationSe ...

  3. 洛谷 P2184 贪婪大陆

    题面 又是一类比较套路的题呢? 假如我们的地雷都表示成 [l[i],r[i]] ,要求[L,R],那么就相当于要求满足 (l[i]<=R && r[i]>=L)的i的个数. ...

  4. CaoHaha's staff (HDU 6154)(2017中国大学生程序设计竞赛 - 网络选拔赛)

    Problem Description "You shall not pass!" After shouted out that,the Force Staff appered i ...

  5. Django基础之初识视图

    编写视图 一个视图函数,或者简短来说叫做视图,是一个简单的Python函数,它接受web请求,并且返回web响应. 响应可以是一个网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一 ...

  6. node.js获取ip及mac

    ; (function (win) { var os = require('os'); var ifaces = os.networkInterfaces(); function NetworkUti ...

  7. 1分钟快速制作漂亮的Html5本地记事本

    大家好,以前给大家分享过一个五步骤制作精美的HTML5时钟的文章,点击回顾<五步教你制作漂亮精致的HTML时钟>,还有<一分钟教你如何实现唯美的文字描边>:今天给大家分享一个用 ...

  8. 预处理、const、static与sizeof-static有什么作用(至少说出2个)

    1:在C语言中,关键字static有3个明显的作用: (1)在函数体,一个被声明为静态的变量在这一函数被调用的过程中维持其值不变. (2)在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所 ...

  9. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  10. Handler注意事项

    一. Handler与Thread的区别. Handler与调用者处于同一线程,如果Handler里面做耗时的动作,调用者线程会阻塞.Android UI操作不是线程安全的,并且这些操作必须在UI线程 ...