java篇-(java使用内嵌Tomcat开发javaWeb项目-高级篇1)

java使用内嵌Tomcat开发javaWeb项目

写在前面

这一篇博客,是在java篇-(java使用内嵌Tomcat开发javaWeb项目-中级篇)这篇博客之上进行扩展,整合spring data jpa,junit,thymeleaf,redis实现使用此方式开发项目
项目初始结构请查看java篇-(java使用内嵌Tomcat开发javaWeb项目-中级篇这篇博客,博客地址: java篇-(java使用内嵌Tomcat开发javaWeb项目-中级篇)

整合spring data jpa

pom.xml添加spring data jpa相关依赖

在这里插入图片描述
这里只复制了jpa相关部分pom文件内容

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <kotlin.code.style>official</kotlin.code.style>
        <kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget>
        <tomcat.embed.version>9.0.31</tomcat.embed.version>
        <thymeleaf.version>3.0.12.RELEASE</thymeleaf.version>
        <spring.version>5.3.5</spring.version>
        <fastjson.version>1.2.73</fastjson.version>
        <validation-api.version>2.0.1.Final</validation-api.version>
        <hibernate-validator.version>6.2.0.Final</hibernate-validator.version>
        <javax.el-api.version>3.0.0</javax.el-api.version>
        <slf4j.version>1.7.30</slf4j.version>
        <log4j2.version>2.14.1</log4j2.version>
        <spring.data.version>2.4.7</spring.data.version>
        <hikaricp.version>4.0.3</hikaricp.version>
        <hibernate.version>5.4.15.Final</hibernate.version>
        <hibernate.jpa.version>1.0.2.Final</hibernate.jpa.version>
        <javax.persistence-api.version>2.2</javax.persistence-api.version>
        <mysql.version>8.0.23</mysql.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>${javax.persistence-api.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>${hibernate.jpa.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>${hikaricp.version}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>${spring.data.version}</version>
        </dependency>
        ...

添加spring data jpa相关配置

在resources目录下面创建spring-config.xml,用来加载配置文件

在这里插入图片描述

在spring-config.xml里面配置加载配置文件

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="classpath:db.properties" />
</beans>

创建数据库配置文件

在这里插入图片描述

db.properties

db.username=root
db.password=123456
db.driverClassName=com.mysql.cj.jdbc.Driver
db.url=jdbc:mysql://192.168.101.150:3306/embed-tomcat?allowPublicKeyRetrieval=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&useUnicode=true
db.maxSize=5
db.maxLifetime=300000
db.minIdle=1

在resources目录下面创建spring-jpa.xml,用来存放jpa相关配置

在这里插入图片描述

在spring-jpa.xml添加jpa相关配置

spring-jpa.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <!--  扫描jpa repository 接口  -->
    <jpa:repositories base-package="com.lhstack.embed.repository" entity-manager-factory-ref="entityManagerFactoryBean"
                      transaction-manager-ref="transactionManager"/>
	<!--  开启事物注解驱动  -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
        <property name="jdbcUrl" value="${db.url}"/>
        <property name="driverClassName" value="${db.driverClassName}"/>
        <property name="minimumIdle" value="${db.minIdle}"/>
        <property name="maximumPoolSize" value="${db.maxSize}"/>
        <!--    单个链接的最大生命周期    -->
        <property name="maxLifetime" value="${db.maxLifetime}"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="dataSource" ref="dataSource"/>
        <property name="entityManagerFactory" ref="entityManagerFactoryBean"/>
    </bean>

    <bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaProperties">
            <props>
                <!--        格式化jpa打印的sql语句        -->
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
        <!--    扫描jpa entity所在包里面的类,与数据库表进行绑定    -->
        <property name="packagesToScan" value="com.lhstack.embed.entity.domain"/>

        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
    </bean>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <!--    根据entity自动生成数据库表,同步    -->
        <property name="generateDdl" value="true"/>
        <property name="database" value="MYSQL"/>
        <!--    显示sql    -->
        <property name="showSql" value="true"/>
    </bean>
</beans>

创建entity

这里包就是上面jpa配置里面的entityManagerFactoryBean.packagesToScan所在的包
在这里插入图片描述
User.java

package com.lhstack.embed.entity.domain;

import javax.persistence.*;
import java.util.Date;

/**
 * @author lhstack
 * Entity 标识此对象是数据库里面的表
 * Table标识对应数据库那张表,这里对应的就是t_user这张表
 */
@Entity
@Table(name = "t_user")
public class User {

    /**
     * Id标识此字段为主键
     * GenerationType.IDENTITY是设置id自增
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name",length = 20,nullable = false,unique = true)
    private String name;

    @Column(name = "username",length = 20,nullable = false,unique = true)
    private String username;

    @Column(name = "password",length = 200,nullable = false)
    private String password;

    @Column(name = "create_time",nullable = false)
    private Date createTime;

    @Column(name = "update_time",nullable = false)
    private Date updateTime;

    public User() {
    }

    public User(Integer id, String name, String username, String password, Date createTime, Date updateTime) {
        this.id = id;
        this.name = name;
        this.username = username;
        this.password = password;
        this.createTime = createTime;
        this.updateTime = updateTime;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                '}';
    }
}

创建对应的repository

同理,这里对应jpa:repositories标签里面的base-package属性值
在这里插入图片描述
UserRepository.java

package com.lhstack.embed.repository;

import com.lhstack.embed.entity.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User,Integer> {
}

在resources目录下面创建spring-service.xml配置文件,配置扫描service相关接口

在这里插入图片描述
spring-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.lhstack.embed.service" />
</beans>

在配置的包下面创建对应的service接口和实现类

在这里插入图片描述
IUserService.java

package com.lhstack.embed.service;

import com.lhstack.embed.entity.domain.User;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * 用户相关接口
 * @author lhstack
 */
public interface IUserService {

    User save(User user);

    User update(Integer id,User user);

    List<User> queryList();

    Page<User> queryPageList(Integer page,Integer size);

    User findById(Integer id);

    void deleteById(Integer id);
}

UserServiceImpl.java

package com.lhstack.embed.service.impl;

import com.lhstack.embed.entity.domain.User;
import com.lhstack.embed.repository.UserRepository;
import com.lhstack.embed.service.IUserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author lhstack
 * 用户操作相关实现类
 */
@Service
public class UserServiceImpl implements IUserService {

    private final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    public User save(User user) {
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        return userRepository.save(user);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    public User update(Integer id, User user) {
        Optional<User> optionalUser = userRepository.findById(id);
        if (optionalUser.isPresent()) {
            User result = optionalUser.get();
            if (StringUtils.hasText(user.getName())) {
                result.setName(user.getName());
            }
            if (StringUtils.hasText(user.getUsername())) {
                result.setUsername(user.getUsername());
            }
            if (StringUtils.hasText(user.getPassword())) {
                result.setPassword(user.getPassword());
            }
            result.setUpdateTime(new Date());
            return userRepository.save(result);
        }
        return null;
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public List<User> queryList() {
        return userRepository.findAll();
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public Page<User> queryPageList(Integer page, Integer size) {
        return userRepository.findAll(PageRequest.of(page - 1, size));
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public User findById(Integer id) {
        return userRepository.findById(id).orElseGet(null);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    public void deleteById(Integer id) {
        userRepository.deleteById(id);
    }
}

创建UserController,暴露curd接口

在这里插入图片描述
UserController.java

package com.lhstack.embed.controller;

import com.lhstack.embed.entity.domain.User;
import com.lhstack.embed.service.IUserService;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("user")
public class UserController {

    private final IUserService userService;

    public UserController(IUserService userService) {
        this.userService = userService;
    }


    @PostMapping
    public User save(@RequestBody User user) {
        return userService.save(user);
    }

    @PutMapping("{id}")
    public User updateById(@PathVariable("id") Integer id, @RequestBody User user) {
        return userService.update(id, user);
    }

    @GetMapping("list")
    public List<User> queryList(){
        return userService.queryList();
    }

    @GetMapping("page")
    public Page<User> queryPageList(@RequestParam(name = "page",defaultValue = "1")Integer page,
                                    @RequestParam(name = "size",defaultValue = "10") Integer size){
        return userService.queryPageList(page,size);
    }

    @DeleteMapping("{id}")
    public ResponseEntity<Boolean> deleteById(@PathVariable("id") Integer id){
        userService.deleteById(id);
        return ResponseEntity.ok(true);
    }
}

启动项目

控制台打印了对应的sql,数据库自动创建了对应的表结构
在这里插入图片描述
在这里插入图片描述
使用postman测试接口
添加数据
在这里插入图片描述
更新数据
在这里插入图片描述
查询数据
在这里插入图片描述
分页查询
在这里插入图片描述
在这里插入图片描述

整合junit,实现单元测试

pom.xml添加junit相关依赖

在这里插入图片描述
这里只复制junit相关的内容
pom.xml

	...
    	<junit.version>4.12</junit.version>
    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    ...

创建test类,配置spring使用junit进行单元测试

在这里插入图片描述

执行单元测试

在这里插入图片描述

整合thymeleaf,实现mvc架构

在pom.xml添加thymeleaf相关依赖

由于之前在pom.xml里面预留了thymeleaf的依赖,所以这里添加thymeleaf集成spring的依赖即可
在这里插入图片描述

		<dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>${thymeleaf.version}</version>
        </dependency>

在resources目录创建spring-thymeleaf.xml文件

用于存放spring继承thymeleaf的配置信息
在这里插入图片描述
spring-thymeleaf.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <bean id="springResourceTemplateResolver"
          class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
        <!--    开启缓存,并配置缓存时间    -->
        <property name="cacheTTLMs" value="60000"/>
        <property name="cacheable" value="true"/>
        <!--   配置前缀,这里会根据tomcat的docBase作为相对路径向下匹配     -->
        <property name="prefix" value="/templates/"/>
        <!--   后缀,这里根据controller返回的字符串,拼接为context.getRealPath() + prefix + controller return value + suffix     -->
        <property name="suffix" value=".html"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateMode" value="HTML5"/>
    </bean>

    <bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
        <property name="templateResolver" ref="springResourceTemplateResolver"/>
        <!--   配置支持spring el表达式     -->
        <property name="enableSpringELCompiler" value="true"/>
    </bean>

    <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver" id="viewResolver">
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine" ref="templateEngine"/>
        <!--   设置响应给浏览器的内容格式     -->
        <property name="contentType" value="text/html;charset=utf-8"/>
    </bean>

    <!--  配置视图解析器  -->
    <mvc:view-resolvers>
        <ref bean="viewResolver"/>
    </mvc:view-resolvers>

</beans>

编写controller进行测试

在这里插入图片描述
IndexController.kt

package com.lhstack.embed.controller

import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping

@Controller
@RequestMapping("index")
class IndexController {

    @GetMapping
    fun index():String{
        return "index"
    }
}

在resources目录下面创建对应的html页面
在这里插入图片描述

启动项目,访问index

在这里插入图片描述

结合spring data jpa,实现简单的crud

修改IndexController,添加crud相关逻辑

在这里插入图片描述

IndexController.kt

package com.lhstack.embed.controller

import com.lhstack.embed.entity.domain.User
import com.lhstack.embed.service.IUserService
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.*
import java.util.*

@Controller
@RequestMapping("thymeleaf")
class IndexController(private val userService: IUserService) {

    @GetMapping("index")
    fun index(model: Model,
              @RequestParam(name = "page",defaultValue = "1") page: Int,
              @RequestParam(name = "size",defaultValue = "10")size: Int
    ):String{
        model.addAttribute("list",this.userService.queryPageList(page,size))
        return "index"
    }


    /**
     * 跳转更新页面
     */
    @GetMapping("toUpdatePage/{id}")
    fun toUpdatePage(model:Model,@PathVariable("id") id:Int):String{
        val user = this.userService.findById(id)
        if(Objects.isNull(user)){
            return "redirect:/thymeleaf/index"
        }
        model.addAttribute("user",user)
        return "update"
    }

    @PostMapping("update/{id}")
    fun update(user:User,@PathVariable("id") id:Int):String{
        this.userService.update(id,user)
        return "redirect:/thymeleaf/index"
    }

    /**
     * 跳转保存页面
     */
    @GetMapping("toSave")
    fun toSavePage():String{
        return "save"
    }

    @PostMapping("save")
    fun save(user:User):String{
        this.userService.save(user)
        return "redirect:/thymeleaf/index"
    }

    @GetMapping("del/{id}")
    fun delete(@PathVariable("id") id:Int):String{
        this.userService.deleteById(id)
        return "redirect:/thymeleaf/index"
    }
}

修改index.html,实现渲染用户列表

在这里插入图片描述
index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<a th:href="${#request.contextPath} + '/thymeleaf/toSave'">新增</a>
<table>
    <thead>
        <tr>
            <th>id</th>
            <th>名称</th>
            <th>用户名</th>
            <th>密码</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
        <tr th:each="item,stat : ${list}">
            <td th:text="${item.id}"></td>
            <td th:text="${item.name}"></td>
            <td th:text="${item.username}"></td>
            <td th:text="${item.password}"></td>
            <td>
                <a th:href="${#request.getContextPath()} + '/thymeleaf/toUpdatePage/' + ${item.id}">更新</a>
                <a th:href="${#request.getContextPath()} + '/thymeleaf/del/' + ${item.id}">删除</a>
            </td>
        </tr>
    </tbody>
</table>
<a th:href="${#request.getContextPath()} + '/thymeleaf/index?page=1&size=' + ${list.pageable.pageSize}">首页</a>
<a th:href="${#request.getContextPath()} + '/thymeleaf/index?page=' + ${list.pageable.pageNumber <= 0 ? 1 : list.pageable.pageNumber} + '&size=' + ${list.pageable.pageSize}">上一页</a>
<a th:href="${#request.getContextPath()} + '/thymeleaf/index?page=' + ${list.pageable.pageNumber + 2} + '&size=' + ${list.pageable.pageSize}">下一页</a>
</body>
</html>

添加新增页面,实现数据的新增

在这里插入图片描述

save.html

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>update</title>
</head>
<body>
<form th:action="${#request.contextPath} + '/thymeleaf/save/'" method="post">
    <div>
        <label for="name">名称</label>
        <input name="name" id="name"/>
    </div>
    <div>
        <label for="username">用户名</label>
        <input name="username" id="username" />
    </div>
    <div>
        <label for="password">密码</label>
        <input name="password" id="password" />
    </div>
    <div>
        <input type="submit" value="提交" /><input type="reset" value="重置" />
    </div>
</form>
</body>
</html>

添加更新页面,实现数据更新

在这里插入图片描述

update.html

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>update</title>
</head>
<body>
<form th:action="${#request.contextPath} + '/thymeleaf/update/' + ${user.id}" method="post">
    <div>
        <label for="name">名称</label>
        <input name="name" id="name" th:value="${user.name}" />
    </div>
    <div>
        <label for="username">用户名</label>
        <input name="username" id="username" th:value="${user.username}" />
    </div>
    <div>
        <label for="password">密码</label>
        <input name="password" id="password" th:value="${user.password}" />
    </div>
    <div>
        <input type="submit" value="提交" /><input type="reset" value="重置" />
    </div>
</form>
</body>
</html>

启动项目

访问首页
在这里插入图片描述
新增数据
在这里插入图片描述
在这里插入图片描述
修改数据
在这里插入图片描述
在这里插入图片描述
删除数据
在这里插入图片描述
在这里插入图片描述

添加redis,实现数据的缓存

pom.xml添加spring-data-redis和redis客户端相关依赖

在这里插入图片描述

	...
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <kotlin.code.style>official</kotlin.code.style>
        <kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget>
        <tomcat.embed.version>9.0.31</tomcat.embed.version>
        <thymeleaf.version>3.0.12.RELEASE</thymeleaf.version>
        <spring.version>5.3.5</spring.version>
        <fastjson.version>1.2.73</fastjson.version>
        <validation-api.version>2.0.1.Final</validation-api.version>
        <hibernate-validator.version>6.2.0.Final</hibernate-validator.version>
        <javax.el-api.version>3.0.0</javax.el-api.version>
        <slf4j.version>1.7.30</slf4j.version>
        <log4j2.version>2.14.1</log4j2.version>
        <spring.data.version>2.4.7</spring.data.version>
        <hikaricp.version>4.0.3</hikaricp.version>
        <hibernate.version>5.4.15.Final</hibernate.version>
        <hibernate.jpa.version>1.0.2.Final</hibernate.jpa.version>
        <javax.persistence-api.version>2.2</javax.persistence-api.version>
        <mysql.version>8.0.23</mysql.version>
        <junit.version>4.12</junit.version>
        <lettuct.version>6.1.0.RELEASE</lettuct.version>
    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/io.lettuce/lettuce-core -->
        <dependency>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
            <version>${lettuct.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>${spring.data.version}</version>
        </dependency>
    ...

修改spring-config.xml,加载redis配置文件

在这里插入图片描述
redis.propertis
在这里插入图片描述redis.properties

redis.database=0
redis.host=192.168.101.150
redis.port=6379

resources目录下创建spring-redis.xml配置文件

在这里插入图片描述
spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

    <bean id="redisConnectionFactory"
          class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
        <constructor-arg index="0" ref="standaloneConfiguration"/>
    </bean>
    <bean id="standaloneConfiguration" class="org.springframework.data.redis.connection.RedisStandaloneConfiguration">
        <property name="database" value="${redis.database}"/>
        <property name="port" value="${redis.port}"/>
        <property name="hostName" value="${redis.host}"/>
    </bean>

    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" factory-method="create">
        <constructor-arg ref="redisConnectionFactory"/>
    </bean>

    <!--  后续可能会用到调redis api的地方 ,这里先创建出redisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redisConnectionFactory"/>
    </bean>

    <!--  开启缓存,并使用redis作为cache组件  -->
    <cache:annotation-driven cache-manager="cacheManager"/>
</beans>

修改UserServiceImpl里面的方法,加入缓存功能

在这里插入图片描述

UserServiceImpl.java

package com.lhstack.embed.service.impl;

import com.lhstack.embed.entity.domain.User;
import com.lhstack.embed.repository.UserRepository;
import com.lhstack.embed.service.IUserService;
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.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author lhstack
 * 用户操作相关实现类
 */
@Service
public class UserServiceImpl implements IUserService {

    private final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    /**
     * @CacheEvict(cacheNames = "user",allEntries = true)清除cacheName为user的所有缓存
     * @param user
     * @return
     */
    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    @CacheEvict(cacheNames = "user",allEntries = true)
    public User save(User user) {
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        return userRepository.save(user);
    }

    @CacheEvict(cacheNames = "user",allEntries = true)
    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    public User update(Integer id, User user) {
        Optional<User> optionalUser = userRepository.findById(id);
        if (optionalUser.isPresent()) {
            User result = optionalUser.get();
            if (StringUtils.hasText(user.getName())) {
                result.setName(user.getName());
            }
            if (StringUtils.hasText(user.getUsername())) {
                result.setUsername(user.getUsername());
            }
            if (StringUtils.hasText(user.getPassword())) {
                result.setPassword(user.getPassword());
            }
            result.setUpdateTime(new Date());
            return userRepository.save(result);
        }
        return null;
    }

    @Cacheable(cacheNames = "user",key = "'queryList'")
    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public List<User> queryList() {
        return userRepository.findAll();
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    @Cacheable(cacheNames = "user",key = "'queryPageList page:::' + #p0 + '  size:::' + #p1")
    public Page<User> queryPageList(Integer page, Integer size) {
        return userRepository.findAll(PageRequest.of(page - 1, size));
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    @Cacheable(cacheNames = "user",key = "'findById id:::' + #p0")
    public User findById(Integer id) {
        return userRepository.findById(id).orElseGet(null);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class})
    @CacheEvict(cacheNames = "user",allEntries = true)
    public void deleteById(Integer id) {
        userRepository.deleteById(id);
    }
}

修改User.java类,让其实现Serializable接口,保证此对象可以被序列化

在这里插入图片描述

启动项目

第一次请求,控制台打印出了sql
在这里插入图片描述

在这里插入图片描述
第二次请求,还是第一次请求的sql,说明这一次没有走数据库
在这里插入图片描述
查看redis,缓存已经进来了
在这里插入图片描述
添加数据,控制台走了两次sql,第一次是插入数据,第二次是重定向到index时,查询数据,说明缓存是成功更新了的
在这里插入图片描述

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值