栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

秒杀项目01-项目开发环境与框架搭建

Java 更新时间:发布时间: 百科书网 趣学号

秒杀项目01
  • 技术点介绍
  • 秒杀系统实现
  • 学习目标
  • 一、项目框架搭建
    • 1.1 SpringBoot环境搭建
    • 1.2 集成Thymeleaf,Result结果封装
    • 1.3 集成Mybatis+Druid
      • 导入依赖
      • mybatis相关配置
      • Druid相关配置
    • 1.4 集成Jedis+Redis安装+通用缓存Key封装
      • Redis安装
      • 集成Redis
      • 通用缓存Key封装
      • 测试
      • 完善并优化redis相关类

技术点介绍

前端: Thymeleaf,Bootstrap,JQuery
后端: SpringBoot,JSR303,MyBatis
中间件: RabbitMQ,Redis,Druid

秒杀系统实现

学习目标

**应对大并发: **

  1. 如何利用缓存
  2. 如何使用异步
  3. 如何编写优雅的代码
一、项目框架搭建 1.1 SpringBoot环境搭建

父工程pom.xml



    4.0.0

    com.hmx
    miaosha
    1.0-SNAPSHOT
    
        miaosha01
    

    pom

    
        org.springframework.boot
        2.5.0
        spring-boot-starter-parent
    

    
        8
        8
    




子工程pom.xml


    
    
    
        org.apache.commons
        commons-lang3
    
    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.projectlombok
        lombok
    

创建启动类,三层

1.2 集成Thymeleaf,Result结果封装

    org.springframework.boot
    spring-boot-starter-thymeleaf

application.properties

# 允许thymeleaf使用缓存
spring.thymeleaf.cache=true
# 是否为web框架启动thymeleaf视图解析
spring.thymeleaf.enabled=true
# 写入 HTTP 响应的 Content-Type 值。
spring.thymeleaf.servlet.content-type=text/html
# 模板文件编码
spring.thymeleaf.encoding=UTF-8
# 要应用于模板的模板模式
spring.thymeleaf.mode=HTML5
# 在构建 URL 时预先添加到查看名称的前缀。
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时预先添加到查看名称的后缀。
spring.thymeleaf.suffix=.html

Result.java

@Data
public class Result {
    private int code;
    private String msg;
    private T data;

    private Result(T data) {
        this.code = CodeMsg.SUCCESS.getCode();
        this.msg = CodeMsg.SUCCESS.getMsg();
        this.data = data;
    }

    private Result(CodeMsg cm) {
        if (cm == null) {
            return;
        }
        this.code = CodeMsg.SERVER_ERROR.getCode();
        this.msg = CodeMsg.SERVER_ERROR.getMsg();
    }

    
    public static  Result success(T data) {
        return new Result(data);
    }

    
    public static  Result fail(CodeMsg cm) {
        return new Result(cm);
    }
}

CodeMsg.java

public enum CodeMsg {

    //通用异常
    SUCCESS(0,"success"),
    SERVER_ERROR(500100, "服务端异常");
    //登录模块 5002XX

    //商品模块 5003XX

    //订单模块 5004XX

    //秒杀模块 5005XX


    private int code;

    private String msg;

    private CodeMsg(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

1.3 集成Mybatis+Druid 导入依赖

    com.alibaba
    druid
    1.2.6


    mysql
    mysql-connector-java
    8.0.25


    com.baomidou
    mybatis-plus-boot-starter
    3.4.3


mybatis相关配置
# mybatis
# 搜索类别名的包
mybatis-plus.type-aliases-package=com.hmx.miaosha.domain
# 下划线转成驼峰
mybatis-plus.configuration.map-underscore-to-camel-case=true
# 为驱动程序设置一个提示,以控制返回结果的获取大小。此参数值可以被查询设置覆盖。
mybatis-plus.configuration.default-fetch-size=100
# 设置驱动程序等待数据库响应的秒数。
mybatis-plus.configuration.default-statement-timeout=3000
# Mapper xml配置文件的位置
mybatis-plus.mapper-locations=classpath:com/hmx/miaosha/mapper}" = systemd ]
#then
#       echo "This systems seems to use systemd."
#       echo "Please take a look at the provided example service unit files in this directory, and adapt and install them. Sorry!"
#       exit 1
#fi


10. 查看系统服务列表

chkconfig --list | grep redis
  1. 启动redis系统服务
systemctl start redis_6379
集成Redis
  1. 添加Jedis依赖

    redis.clients
    jedis

  1. 添加Fastjson依赖

    com.alibaba
    fastjson
    1.2.75

  1. redis相关配置
# redis
spring.redis.host=192.168.174.128
spring.redis.port=6379
spring.redis.database=0
spring.redis.timeout=3
spring.redis.password=123456
spring.redis.jedis.pool.max-active=10
# 最大空闲 10个
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.max-wait=3
通用缓存Key封装

RedisConfig.java

@Component
@ConfigurationProperties(prefix = "spring.redis")
@Data
public class RedisConfig {

    private String host;
    private int port = 6379;
    //秒
    private int timeout;
    // 使用几号库
    private int database = 0;
    private String password;
    private int maxActive = 10;
    private int maxIdle = 10;
    //秒
    private int maxWait = 3;

}

RedisService.java

@Service
public class RedisService {

    @Autowired
    private JedisPool jedisPool;

    public Boolean set(String key, T value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String str = beanToString(value);
            jedis.set(key, str);
            return true;
        } finally {
            returnToPool(jedis);
        }
    }

    public  T get(String key, Class clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String str = jedis.get(key);
            T t = stringToBean(str,clazz);
            return t;
        } finally {
            returnToPool(jedis);
        }
    }

    private  String beanToString(T value) {
        if (value == null) {
            return null;
        }

        Class clazz = value.getClass();
        if (clazz == Integer.class) {
            return "" + value;
        } else if (clazz == String.class) {
            return (String) value;
        } else if (clazz == Long.class) {
            return "" + value;
        } else {
            return JSON.toJSONString(value);
        }
    }

    private  T stringToBean(String str, Class clazz) {
        if (StringUtils.isBlank(str) || clazz == null) {
            return null;
        }
        if (clazz == Integer.class) {
            return (T)Integer.valueOf(str);
        } else if (clazz == String.class) {
            return (T)str;
        } else if (clazz == Long.class) {
            return (T) Long.valueOf(str);
        } else {
            return JSON.parseObject(str,clazz);
        }

    }

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

JedisPoolFactory.java

@Service
public class RedisPoolFactory {

    @Autowired
    private RedisConfig redisConfig;

    @Bean
    public JedisPool jedisPoolFactory() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(redisConfig.getMaxIdle());
        poolConfig.setMaxTotal(redisConfig.getMaxActive());
        poolConfig.setMaxWaitMillis(redisConfig.getMaxWait() * 1000L);
        JedisPool jp = new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getTimeout() * 1000, redisConfig.getPassword(), redisConfig.getDatabase());
        return jp;
    }

}

注意: 本来把RedisPoolFactory中的内容放在RedisService中的,启动会报循环依赖,因为RedisService依赖JedisPool,JedisPool依赖RedisService中的RedisConfig

测试
@Controller
@RequestMapping("/demo")
public class DemoController {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisService redisService;

    @RequestMapping("/redis/get")
    @ResponseBody
    public Result redisGet() {
        return Result.success(redisService.get("key1", Long.class));
    }

    @RequestMapping("/redis/set")
    @ResponseBody
    public Result redisSet() {
        return Result.success(redisService.set("key2", "hello hmx"));
    }

    @RequestMapping("/db/tx")
    @ResponseBody
    public Result tx() {
        return userService.tx();
    }

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

    @ResponseBody
    @RequestMapping("/hello")
    public Result hello() {
        return Result.success("hello springboot");
    }

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

}

完善并优化redis相关类

在redis中set key时可能会出现key被覆盖的操作,所以我们使用前缀来避免这个情况,不同的模块使用不同的前缀
KeyPrefix.java

public interface KeyPrefix {
    int expireSeconds();

    String getPrefix();
}

basePrefix.java

public abstract class basePrefix implements KeyPrefix{

    private int expireSeconds;

    private String prefix;

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

    public basePrefix() {
    }

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

    
    @Override
    public int expireSeconds() {
        return expireSeconds;
    }

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

UserKey.java

public class UserKey extends basePrefix{

    private UserKey(String prefix) {
        super(prefix);
    }

    public static UserKey getById = new UserKey("id");
    public static UserKey getByName = new UserKey("name");

}

RedisService.java

@Service
public class RedisService {

    @Autowired
    private JedisPool jedisPool;

    
    public Boolean set(KeyPrefix prefix, String key, T value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            //生成真正的key
            String realKey = prefix.getPrefix() + key;
            String str = beanToString(value);
            int seconds = prefix.expireSeconds();
            if (seconds <= 0) {
                jedis.set(realKey, str);
            } else {
                jedis.setex(realKey, (long)seconds, str);
            }
            return true;
        } finally {
            returnToPool(jedis);
        }
    }

    
    public  T get(KeyPrefix prefix, String key, Class 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);
        }
    }

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

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

    
    public 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  String beanToString(T value) {
        if (value == null) {
            return null;
        }

        Class clazz = value.getClass();
        if (clazz == Integer.class) {
            return "" + value;
        } else if (clazz == String.class) {
            return (String) value;
        } else if (clazz == Long.class) {
            return "" + value;
        } else {
            return JSON.toJSONString(value);
        }
    }

    
    private  T stringToBean(String str, Class clazz) {
        if (StringUtils.isBlank(str) || clazz == null) {
            return null;
        }
        if (clazz == Integer.class) {
            return (T)Integer.valueOf(str);
        } else if (clazz == String.class) {
            return (T)str;
        } else if (clazz == Long.class) {
            return (T) Long.valueOf(str);
        } else {
            return JSON.parseObject(str,clazz);
        }

    }

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



}

DemoController.java

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

    @Autowired
    private UserService userService;

    @Autowired
    private RedisService redisService;

    @RequestMapping("/redis/get")
    @ResponseBody
    public Result redisGet() {
        return Result.success(redisService.get(UserKey.getById, "2", User.class));
    }

    @RequestMapping("/redis/set")
    @ResponseBody
    public Result redisSet() {
        User user = new User();
        user.setId(2);
        user.setName("hmx2");
        return Result.success(redisService.set(UserKey.getById, "2", user));
    }

    @RequestMapping("/db/tx")
    @ResponseBody
    public Result tx() {
        return userService.tx();
    }

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

    @ResponseBody
    @RequestMapping("/hello")
    public Result hello() {
        return Result.success("hello springboot");
    }

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

}

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/295574.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号