当前位置:   article > 正文

Spring Boot 电商系统之秒杀实战 -- 1.基础环境搭建_springboot themaleaf 引js

springboot themaleaf 引js

记录学习总结

目标:

1.掌握Spring Boot环境搭建

2.掌握Lombok的集成使用

2.掌握Thymeleaf集成,Result结果封装

3.掌握Mybatis+Druid集成

4.掌握Jedis集成+通用缓存Key封装

文章总体目录

Spring Boot项目搭建

Spring Boot环境搭建

这里使用 IDEA 来进行项目开发,提供了很方便了模板。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

集成Lombok

1.菜单栏File > Settings > Plugins > Browse repositories

2.搜索 Lombok Plugin 安装后,重启IDEA即可生效
在这里插入图片描述

3.添加lombok依赖

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
            <optional>true</optional>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

4.编写一个实体类 User,使用@Data注解(包含了set和get方法)

@Data
public class User {
    private int id;
    private String name;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其他的Lombok用法这里不多说,大家可以自行查阅

集成Mybatis+Druid

1.在 pom.xml 添加依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.在 application.properties 中添加相关配置

# mybatis
mybatis.type-aliases-package=com.chandler.seckill.domain
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=3000
mybatis.mapperLocations = classpath:com/chandler/seckill/dao/*.xml
# druid
spring.datasource.url=jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.filters=stat
spring.datasource.maxActive=2
spring.datasource.initialSize=1
spring.datasource.maxWait=60000
spring.datasource.minIdle=1
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=select 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
spring.datasource.maxOpenPreparedStatements=20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

3.在DAO中添加相关注解

@Mapper
public interface UserDao {
    @Select("select * from user where id = #{id}")
    public User getById(@Param("id")int id);

    @Insert("insert into user(id,name) values(#{id},#{name})")
    public int insert(User user);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

集成Thymeleaf

1.在 pom.xml 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

2.在 application.properties 中添加相关配置

# thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

集成Jedis

1.在 pom.xml 添加依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

2.在 application.properties 中添加相关配置

#redis
redis.host=192.168.25.128
redis.port=6379
redis.timeout=3
redis.password=123456
redis.poolMaxTotal=10
redis.poolMaxIdle=10
redis.poolMaxWait=3

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Result结果封装

很多时候都是需要返回JSON对象,根据需求事先先封装好一个结果对象,方便复用。

因为希望的返回结果形式为:

{
    code:0,
    msg:success,
    name:chandler
}
  • 1
  • 2
  • 3
  • 4
  • 5

所有最终设计的Result结果类为:

@Data
public class Result<T> {

    private int code;
    private String msg;
    private T data;

    /**
     * 成功时的调用
     * @param data
     * @param <T>
     * @return
     */
    public static <T> Result<T> success(T data){
        return new Result<T>(data);
    }

    /**
     * 失败时候的调用
     * @param cm
     * @param <T>
     * @return
     */
    public static <T> Result<T> error(CodeMsg cm){
        return new Result<T>(cm);
    }

    public Result(T data) {
        this.code = 0;
        this.msg = "success";
        this.data = data;
    }

    public Result(CodeMsg cm) {
        if (cm == null) {
            return;
        }
        this.code = cm.getCode();
        this.msg = cm.getMsg();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
@Data
@AllArgsConstructor
public class CodeMsg {

    private int code;
    private String msg;

    //通用异常

    public static CodeMsg SUCCESS = new CodeMsg(0,"success");
    public static CodeMsg SERVER_ERROR = new CodeMsg(500100,"服务端异常");

    //TODO其他异常

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

通用缓存Key封装

我们还需要创建一个 Redis 服务方便进行缓存操作

先定义一个读取application.properties文件中 redis 配置的类

    @Component
    @Data
    @ConfigurationProperties(prefix = "redis")
    public class RedisConfig {
        private String host;
        private int port;
        private int timeout;//秒
        private String password;
        private int poolMaxTotal;
        private int poolMaxIdle;
        private int poolMaxWait;//秒
    
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

有了配置文件中的信息我们在来创建一个工厂类,方便初始化 redis 连接池

    @Service
    public class RedisPoolFactory {
    
        @Autowired
        RedisConfig redisConfig;
        //注册bean对象
        @Bean
        public JedisPool jedisPoolFactory(){
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
            jedisPoolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
            jedisPoolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait());
            JedisPool jp = new JedisPool(jedisPoolConfig,redisConfig.getHost(),redisConfig.getPort(),redisConfig.getTimeout() * 1000,redisConfig.getPassword(),0);
            return jp;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

为了方便我们在读取 key 值的时候能够显示的读取相关值且存入的key值 在不同模块间不同名重复和后期拓展,我们这里稍微对读取和存储 key 值进行一点加工设计,实现了 KeyPrefix 接口和 BasePrefix 基础抽象类,这样其他模块的添加只需要继承基础抽象类即可。

  • 接口扩展类
    public interface KeyPrefix {
        public int expireSeconds();
        public String getPrefix();
    }
  • 1
  • 2
  • 3
  • 4
  • 基础抽象类
    @AllArgsConstructor
    public abstract class BasePrefix implements KeyPrefix{
        private int expireSeconds;
        private String prefix;
    
        public BasePrefix(String prefix) {
            //0代表永不过期
            this(0,prefix);
        }
    
        @Override
        public int expireSeconds(){
            return expireSeconds;
        }
    
        @Override
        public String getPrefix() {
            String className = getClass().getSimpleName();
            return className+":"+prefix;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 业务相关类
    public class OrderKey extends BasePrefix {
        public OrderKey(int expireSeconds, String prefix) {
            super(expireSeconds, prefix);
        }
    }



    public class UserKey extends BasePrefix {
        public UserKey(String prefix) {
            super(prefix);
        }
        public static UserKey getById = new UserKey("id");
        public static UserKey getByName = new UserKey("name");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 最后是比较关键的RedisService 服务类,缓存相关操作都封装在这个类中
@Service
    public class RedisService {
    
        @Autowired
        JedisPool jedisPool;
    
        /**
         * 获取单个对象
         *
         * @param prefix
         * @param key
         * @param clazz
         * @param <T>
         * @return
         */
        public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                String realKey = prefix.getPrefix() + key;
                String str = jedis.get(realKey);
                T t = stringToBean(str, clazz);
                return t;
            } finally {
                returnToPool(jedis);
            }
        }
    
        /**
         * 设置对象
         * @param prefix
         * @param key
         * @param value
         * @param <T>
         * @return
         */
        public <T> boolean set(KeyPrefix prefix,String key,T value){
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                String str = beanToString(value);
                if (str == null || str.length() <= 0) {
                    return false;
                }
                String realKey = prefix.getPrefix() + key;
                int seconds = prefix.expireSeconds();
                if (seconds <= 0){
                    jedis.set(realKey,str);
                } else {
                    jedis.setex(realKey,seconds,str);
                }
                return true;
            } finally {
                returnToPool(jedis);
            }
        }
    
        /**
         * 判断 key 是否存在
         * @param prefix
         * @param key
         * @param <T>
         * @return
         */
        public <T> boolean exists(KeyPrefix prefix,String key){
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                String realKey = prefix.getPrefix() + key;
                return jedis.exists(realKey);
            } finally {
                returnToPool(jedis);
            }
        }
    
        /**
         * 执行原子增加 key 值
         * @param prefix
         * @param key
         * @param <T>
         * @return
         */
        public <T> Long incr(KeyPrefix prefix,String key){
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                String realKey = prefix.getPrefix() + key;
                return jedis.incr(realKey);
            } finally {
                returnToPool(jedis);
            }
        }
    
        /**
         * 减少 key 值
         * @param prefix
         * @param key
         * @param <T>
         * @return
         */
        public <T> Long decr(KeyPrefix prefix,String key){
            Jedis jedis = null;
            try {
                jedis = jedisPool.getResource();
                String realKey = prefix.getPrefix() + key;
                return jedis.decr(realKey);
            } finally {
                returnToPool(jedis);
            }
        }
    
        private <T> String beanToString(T value) {
            if (value == null) {
                return null;
            }
            Class<?> clazz = value.getClass();
            if (clazz == int.class || clazz == Integer.class){
                return ""+value;
            } else if (clazz == Long.class || clazz == long.class){
                return "" + value;
            } else if (clazz == String.class){
                return (String) value;
            } else {
                return JSON.toJSONString(value);
            }
        }
    
        private <T> T stringToBean(String str, Class<T> clazz) {
            if (str == null || str.length() <= 0 || clazz == null) {
                return null;
            }
            if (clazz == int.class || clazz == Integer.class) {
                return (T) Integer.valueOf(str);
            } else if (clazz == String.class) {
                return (T) str;
            } else if (clazz == Long.class || clazz == long.class) {
                return (T) Long.valueOf(str);
            } else {
                return JSON.toJavaObject(JSON.parseObject(str), clazz);
            }
        }
    
        private void returnToPool(Jedis jedis) {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

测试验证

环境都搭建配置之后测试是必不可少的环节,开始动手搞起来。

1.创建测试 TestController 类

@Controller
@RequestMapping("/test")
public class TestController {

    @Autowired
    UserService userService;

    @Autowired
    RedisService redisService;

    @RequestMapping("/hello")
    @ResponseBody
    public Result<String> home(){
        return Result.success("Hello world");
    }

    @RequestMapping("/error")
    @ResponseBody
    public Result<String> error(){
        return Result.error(CodeMsg.SERVER_ERROR);
    }

    @RequestMapping("/hello/themaleaf")
    public String themaleaf(Model model){
        model.addAttribute("name","Chandler");
        return "hello";
    }

    @RequestMapping("/db/get")
    @ResponseBody
    public Result<User> dbGet(){
        User user = userService.getById(1);
        return Result.success(user);
    }

    @RequestMapping("/redis/get")
    @ResponseBody
    public Result<User> redisGet(){
        User user = redisService.get(UserKey.getById,""+1,User.class);
        return Result.success(user);
    }
    @RequestMapping("/redis/set")
    @ResponseBody
    public Result<Boolean> redisSet(){
        User user =new User();
        user.setId(1);
        user.setName("Chandler");
        redisService.set(UserKey.getById,""+1,user);
        return Result.success(true);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

2.测试Result类是否能够返回我们需要的json格式
在这里插入图片描述
在这里插入图片描述

3.测试Themaleaf是否配置成功
在这里插入图片描述

4.测试User类是否正常
在这里插入图片描述

5.测试Redis配置是否成功
在这里插入图片描述
在这里插入图片描述

进入 Redis 中查看
在这里插入图片描述

这样大概的环境流程验证OK,接下来就可以开始实现功能开发了~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/143806
推荐阅读
相关标签
  

闽ICP备14008679号