秒杀系统Web实践——01框架搭建Spring Boot+Mybatis +Redis(Jedis)

第一章项目框架搭建

项目github:https://github.com/LCYang-1/-

主要任务

1.Spring Boot环境搭建

2.集成Thymeleaf , Result结果封装

3.集成Mybatis + Druid

4.集成Jedis+ Redis安装+通用缓存Key封装

5.测试


 


 

1.Spring Boot环境搭建

目前选取这些依赖,后期遇到什么,再添加就行了(记性不好!!一步一步来吧)

2.集成Thymeleaf , Result结果封装

编辑application.properties配置文件

Result结果封装

    private int code;        //响应码
    private String msg;      //提示
    private T data;          //内容

详细封装请看gitbut

3.集成Mybatis + Druid

添加依赖

 <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>

         <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>

添加配置

#mybatis
mybatis.type-aliases-package=com.lcy.miaosha.pojo
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=3000
mybatis.mapper-locations=classpath:com/lcy/miaosha/dao/*.xml

#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/miaosha?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
        
# druid
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

4.集成Jedis+ Redis安装+通用缓存Key封装

Redis安装

请参考https://www.runoob.com/redis/redis-install.html

添加依赖

依赖原生Jedis;添加Fastjson,序列化后为json,方便查看。

        <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.1.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

在application.properties设置配置参数

这里我使用的是自定义的配置参数

#redis
redis.host=***.***.***.***
redis.port=6379
#连接超时时间
redis.timeout=3
redis.password=123456
#连接池配置
#最大连接数
redis.poolMaxTotal=10
#最大空闲连接数
redis.poolMaxIdle=10
#最大等待连接数
redis.poolMaxWait=3

所以我们要写一个类来获取配置参数信息

@Component
@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;//秒

    //set/get方法
    /**
    *别忘添加
    */
}

编写JedisPoolFactory类来配置JedisPool资源连接池

@Service
public class JedisPoolFactory {

    @Autowired
    RedisConfig redisConfig;

    @Bean
    public JedisPool JedisPoolFactory(){

        System.out.println(redisConfig.toString());
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
        poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
        poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait()*1000);
        JedisPool jp=new JedisPool(poolConfig,redisConfig.getHost(),redisConfig.getPort()
                ,redisConfig.getTimeout()*1000,redisConfig.getPassword(),0);
        return jp;
    }
}

通用缓存Key封装

为防止我们使用Redis时Key值重复给予不同类型含义的Value,我们在此对通用缓存Key封装

一个接口

public interface KeyPrefix {

    public int expireSeconds();

    public String getPrefix();

}

一个抽象类

public abstract class BasePrefix implements KeyPrefix {

    private int expireSeconds;

    private String prefix;

    public BasePrefix( String prefix) {
        this(0,prefix);
    }

    public BasePrefix(int expireSeconds, String prefix) {
        this.expireSeconds = expireSeconds;
        this.prefix = prefix;
    }

    @Override
    public int expireSeconds() {//0代表永不过期
        return expireSeconds;
    }

    @Override
    public String getPrefix() {
        String classname = getClass().getSimpleName();
        return classname+":"+prefix;
    }
}

RedisService类的编写

分别有get、set、exists、incr、decr。

@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();
            //生成真正的key
            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;
            //生成真正的key
            String realKey =prefix.getPrefix()+key;
            int seconds=prefix.expireSeconds();
            if (seconds<=0){
                jedis.set(realKey,str);
            } else {
                jedis.setex(realKey,seconds,str);
            }
            jedis.set(realKey, str);
            return true;

        }finally {
            returnToPool(jedis);
        }

    }

    /**
     * 判断是否存在
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> boolean exists(KeyPrefix prefix,String key){
        Jedis jedis =null;
        try {
            jedis = jedisPool.getResource();
            //生成真正的key
            String realKey =prefix.getPrefix()+key;
            return jedis.exists(realKey);

        }finally {
            returnToPool(jedis);
        }

    }

    /**
     * 增加值
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> Long incr(KeyPrefix prefix,String key){
        Jedis jedis =null;
        try {
            jedis = jedisPool.getResource();
            //生成真正的key
            String realKey =prefix.getPrefix()+key;
            return jedis.incr(realKey);

        }finally {
            returnToPool(jedis);
        }

    }

    /**
     * 减少值
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> Long decr(KeyPrefix prefix,String key){
        Jedis jedis =null;
        try {
            jedis = jedisPool.getResource();
            //生成真正的key
            String realKey =prefix.getPrefix()+key;
            return jedis.decr(realKey);

        }finally {
            returnToPool(jedis);
        }

    }


    private <T> String beanToString(T value) {
        if (value==null)
            return null;
        Class<?> aClass = value.getClass();
        if (aClass==int.class||aClass==Integer.class){
            return ""+value;
        }else if (aClass==String.class){
            return (String) value;
        }else if (aClass==long.class||aClass==Long.class){
            return ""+value;
        }else {
            return JSON.toJSONString(value);
        }
    }

    private <T> T stringToBean(String str,Class<T> aClass) {
        if (str==null||str.length()<=0||aClass==null)
            return null;


        if (aClass==int.class||aClass==Integer.class){
            return (T)Integer.valueOf(str);
        }else if (aClass==String.class){
            return (T)str;
        }else if (aClass==long.class||aClass==Long.class){
            return (T)Long.valueOf(str);
        }else {
            return JSON.toJavaObject(JSON.parseObject(str),aClass);
        }
    }

    private void returnToPool(Jedis jedis) {
        if (jedis!=null){
            jedis.close();
        }
    }


}

 


5.测试

前提条件,数据库中有一个可用的表

对应的User类

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

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

对应的一个UserDao

@Mapper
public interface UserDao {

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


}

当然还有UserService

@Service
public class UserService {

    @Autowired
    UserDao userDao;

    public User getById(int id){
        return userDao.getById(id);
    }
}

我们还要实现一个UserKey来继承BasePrefix

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");
}

现在我们就可以进行测试了,我们通过Controll类来进行测试

@Controller
@RequestMapping("/demo")
public class SampleController {

    @Autowired
    RedisService redisService;

    @Autowired
    UserService userService;

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

    @RequestMapping("/db/get")
    @ResponseBody
    public String dbGet(){
        User user=userService.getById(1);
        return user.toString();
    }

    @RequestMapping("/redis/get")
    @ResponseBody
    public String redisGet(){
        User v1=redisService.get(UserKey.getById,""+1,User.class);
        return v1.toString();
    }

    @RequestMapping("/redis/set")
    @ResponseBody
    public boolean redisSet(){
        User user = new User(1, "1111");
        boolean b = redisService.set(UserKey.getById, "" + 1, user);

        return b;
    }
}

看到第一个方法返回一个“hello”字符串,并且没有 @ResponseBody注解,我们就要编辑相应的hello.html页面

他的位置对应在classpath:/templates/

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>hello</title>
    <meta http-equiv="Content-Type " content="text/html;charset=UTF-8"/>
</head>
<body>
<p th:text="'hello:'+${name}"></p>
</body>
</html>

启动项目

图片说明Thymeleaf一切正常

图片说明Mybatis+Druid+Result结果封装正常图片说明redis服务正常


到此为止第一章的内容就算结束了!!!!!!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值