▶【SecKill】U1 项目框架搭建
▶【SecKill】U1 项目框架搭建
一、SpringBoot环境搭建
1、新建Maven Project


2、在pom.xml中添加依赖

3、搭建 简易 的SpringBoot框架
(1)删除src/test/java测试类

(2)改包名

【注】SpringBoot是在SpringMVC的基础上,做了封装。
SpringBoot开发程序 = SpringMVC(controller调用service,service调用DAO 的分层结构开发)
(3)分层结构controller、service、dao
① controller

② service

③ dao

(4)测试Demo1:新建DemoController类,添加代码(官网Spring Quickstart Guide简易项目代码)

package com.kirin.miaosha.controller;
@Controller
@EnableAutoConfiguration
public class DemoController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(DemoController.class, args);
}
}
(5)运行测试
成功!
4、测试Demo2
(1)在com.kirin.miaosha中新建class类:MainApplication.class

(2)将DemoController.java中的这2段放入MainApplication.class中
DemoController.java:

MainApplication.class:
package com.kirin.miaosha;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(MainApplication.class, args);
}
}
(3)运行MainApplication.class
【注】运行新的Tomcat前,先按停止键,暂停之前正在运行的Tomcat
5、Controller中的方法:
(1)rest api json输出
【例】
新建com.kirin.miaosha.result包
在com.kirin.miaosha.result包下,新建Result类

在Result类中,定义变量code、msg、data,生成get()、set()
package com.kirin.miaosha.result;
public class Result<T> { //<T>:泛型(广泛的类型)
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
DemoController.java:
package com.kirin.miaosha.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.kirin.miaosha.result.Result;
@Controller
public class DemoController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
//Controller中的方法:
//1.rest api json输出
//【例】com.kirin.miaosha.result包下Result类
@RequestMapping("/hello")
@ResponseBody
String hello() {
Result.success(data);
return new Result(0,"success","helo,kirin");
}
@RequestMapping("/helloError")
@ResponseBody
String helloError() {
Result.error(CodeMsg);
return new Result(500102,"XXX");
return new Result(500101,"XXX");
return new Result(500100,"session失效");
}
}
CodeMsg.java:
package com.kirin.miaosha.result;
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, "服务端异常");
private CodeMsg(int code, String msg) {
this.code = code;
this.msg = msg;
}
//生成get、set方法(后来发现用不到set方法,删除)
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
Result.java:
package com.kirin.miaosha.result;
public class Result<T> { //<T>:泛型(广泛的类型)
private int code;
private String msg;
private T data;
public static <T> Result<T> success(T data){
return new Result<T>(data);
}
public static <T> Result<T> error(CodeMsg cm){ //报错:自动生成CodeMsg.java类
return new Result<T>(cm); //写完后报错:生成一个构造函数private Result(CodeMsg cm)
}
private Result(T data) {
this.code = 0; //成功
this.msg = "success";
this.data = data;
}
private Result(CodeMsg cm) {
if(cm == null) {
return;
}
this.code = cm.getCode();
this.msg = cm.getMsg();
}
public int getCode() {
return code;
}public String getMsg() {
return msg;
}public T getData() {
return data;
}
}
DemoController.java:

package com.kirin.miaosha.controller;
@Controller
public class DemoController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
//Controller中的方法:
//1.rest api json输出
//【例】com.kirin.miaosha.result包下Result类
@RequestMapping("/hello")
@ResponseBody
public Result <String> hello() {
return Result.success("helo,kirin");
}
@RequestMapping("/helloError")
@ResponseBody
public Result <String> helloError() {
return Result.error(CodeMsg.SERVER_ERROR);
}
}
运行MainApplication.java

成功!
(2)前端页面
二、集成Thymeleaf(页面模板=JSP),Result结果封装
1、添加Thymeleaf依赖(前端=JSP)

<!-- thymeleaf依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
2、配置文件
spring.thymeleaf.cache=false spring.thymeleaf.content-type=text/html spring.thymeleaf.enabled=true spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.mode=HTML5 spring.thymeleaf.prefix=classpath:/templates/ spring.thymeleaf.suffix=.html
3、Result结果封装
(1)DemoController.java:

//U1-2 集成Thymeleaf(页面模板=JSP),Result结果封装
@RequestMapping("/thymeleaf")
public String Thymeleaf() { //返回页面模板
return "hello";
//在配置文件中配置hello的页面模板
}
(2)在配置文件中配置hello的页面模板
① 新建templates文件夹
② 在配置文件中配置hello的页面模板:src/main/resources/templates/hello.html
<!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>
③ 定义一个对象

//U1-2 集成Thymeleaf(页面模板=JSP),Result结果封装
@RequestMapping("/thymeleaf")
public String Thymeleaf(Model model) { //返回页面模板
model.addAttribute("name","kirin"); //定义一个对象
return "hello";
//在配置文件中配置hello的页面模板:src/main/resources/templates/hello.html
}
运行MainApplication.java
成功!

原因:项目的配置没有及时更新with这个pom.xml文件,所以更新一下配置文件即可。
三、集成Mybatis(数据库)+Druid
1、添加pom.xml依赖
<!-- 4.添加Mybatis依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
2、添加配置mybatis
① 新建包domain:访问根数据库的表
② 在application.properties中添加配置mybatis
# mybatis mybatis.type-aliases-package=com.kirin.miaosha.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/kirin/miaosha/dao/*.xml
③ 在application.properties中添加配置druid(连接池)
# druid spring.datasource.url=jdbc:mysql://localhost:3306/miaosha spring.datasource.username=root spring.datasource.password=12345 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
④ 在application.properties中添加配置Mysql

<!-- 5.添加Mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
⑤ 连接数据库
A.新建数据库miaosha
CREATE DATABASE `miaosha`; USE `miaosha`;
B.新建数据库表user
C.新建user表对应的domain对象

package com.kirin.miaosha.domain;
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;
}
}
D.新建调用user表的接口UserDao

package com.kirin.miaosha.dao;
@Mapper
public interface UserDao {
@Select("select * from user where id = #{id}")
public User getById(@Param("id") int id);
}
E.新建UserService

package com.kirin.miaosha.service;
@Service
public class UserService {
@Autowired
UserDao userDao;
public User getById(int id) {
return userDao.getById(id);
}
}
F.DemoController.java
在数据库插入1条记录


//U1-4 数据库测试:获取id
@Autowired
UserService userService;
@RequestMapping("/db/get")
@ResponseBody
public Result<User> dbGet() {
User user = userService.getById(1);
return Result.success(user);
}
G.运行
成功!
H.数据库测试2:事务
DemoController.java:

在UserDao.java写插入语句

UserService.java:

I. 运行

数据库中 id=2,name=2222 的记录没有插入,因为这是一条事务
若去掉事务标签,

则数据库中 id=2,name=2222 的记录插入

四、集成Jedis+Redis安装+通用缓存Key封装
1、Linux服务器准备工作
(1)Navicat连接Linux服务器的MYSQL
(2)新建miaosha数据库
① 连接数据库
启动服务
systemctl start mysqld.service
登录
mysql -uroot -p
密码为空

② 新建数据库:create database 数据库名;
create database miaosha;
选择数据库:use 数据库名;
use miaosha;

在Navicat出现miaosha数据库

③ 新建数据库表user
在数据库插入1条记录

④ 修改application.properties中服务器地址
⑤ 运行

2、安装Redis
(1)安装包redis-4.0.2.tar.gz
(2)将安装包拉进root文件夹下
(3)解压
tar -zxvf redis-4.0.2.tar.gz

解压后,出现目录redis-4.0.2
移动该文件夹到
mv redis-4.0.2 /usr/local/redis

(4)make
① 进入移动后的目录

② 用4个CPU make一下,可加快编译速度
make -j 4
make完成后,查看目录

③ 把编译完成的可执行文件添加到目录中
make install
完成!
④ 修改 redis.conf 配置文件

查看 redis.conf 配置文件
vi redis.conf
⑤ 修改 redis.conf 配置文件
A. 使其可以让所有服务器访问

B. 允许后台执行

⑥ 查看Redis服务器是否可以访问
运行Redis服务器
redis-server ./redis.conf
(5)执行 install_server.sh,生成系统服务
进入 utils 下


执行 install_server.sh,生成系统服务
./install_server.sh

3、集成Redis
(1)在pom.xml添加Jedis和Fastjson依赖
<!-- 6.添加Jedis依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- 7.添加Fastjson依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
(2)在application.properties配置Redis
#redis redis.host=192.168.xx.xx redis.port=6379 redis.timeout=3 redis.password=xxxxx redis.poolMaxTotal=10 redis.poolMaxIdle=10 redis.poolMaxWait=3
(3)代码
① 新建redis包
② 新建RedisConfig.java,加入配置文件的参数和方法

③ 新建其余7个class类

BasePrefix.java:
package com.kirin.miaosha.redis;
public abstract class BasePrefix implements KeyPrefix{
private int expireSeconds;
private String prefix;
public BasePrefix(String prefix) { //0代表永不过期
this(0, prefix);
}
public BasePrefix( int expireSeconds, String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
public int expireSeconds() { //默认0代表永不过期
return expireSeconds;
}
public String getPrefix() {
String className = getClass().getSimpleName();
return className+":" + prefix;
}
}
KeyPrefix.java:
package com.kirin.miaosha.redis;
public interface KeyPrefix {
public int expireSeconds(); //有效期
public String getPrefix(); //前缀
}
MiaoshaUserKey.java:
package com.kirin.miaosha.redis;
public class MiaoshaUserKey extends BasePrefix{
public static final int TOKEN_EXPIRE = 3600*24 * 2;
private MiaoshaUserKey(int expireSeconds, String prefix) {
super(expireSeconds, prefix);
}
public static MiaoshaUserKey token = new MiaoshaUserKey(TOKEN_EXPIRE, "tk");
}
OrderKey.java:
package com.kirin.miaosha.redis;
public class OrderKey extends BasePrefix {
public OrderKey(int expireSeconds, String prefix) {
super(expireSeconds, prefix);
}
}
RedisPoolFactory.java:
package com.kirin.miaosha.redis;
@Service
public class RedisPoolFactory {
@Autowired
RedisConfig redisConfig;
@Bean
public JedisPool JedisPoolFactory() {
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;
}
}
RedisService.java:
package com.kirin.miaosha.redis;
@Service
public class RedisService {
@Autowired
JedisPool jedisPool;
//获取当前对象
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); //将获取的值,从String类型转换成bean类型
return t;
}finally {
returnToPool(jedis);
}
}
//设置对象
public <T> boolean set(KeyPrefix prefix, String key, T value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String str = beanToString(value); //将设置的值,从bean类型转换成String类型
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);
}
return true;
}finally {
returnToPool(jedis);
}
}
//判断key是否存在
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);
}
}
//将设置的值,从bean类型转换成String类型
private <T> String beanToString(T value) {
if(value == null) { //若空,直接返回
return null;
}
Class<?> clazz = value.getClass();
if(clazz == int.class || clazz == Integer.class) { //若是int类型,直接写入
return ""+value;
}else if(clazz == String.class) { //若是String类型,直接写入
return (String)value;
}else if(clazz == long.class || clazz == Long.class) { //若是long类型,直接写入
return ""+value;
}else {
return JSON.toJSONString(value);
}
}
//将获取的值,从String类型转换成bean类型
@SuppressWarnings("unchecked")
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) { //若是int类型,强转为int类型
return (T)Integer.valueOf(str);
}else if(clazz == String.class) { //若是String类型,直接输出
return (T)str;
}else if(clazz == long.class || clazz == Long.class) { //若是long类型,强转为long类型
return (T)Long.valueOf(str);
}else {
return JSON.toJavaObject(JSON.parseObject(str), clazz);
}
}
private void returnToPool(Jedis jedis) {
if(jedis != null) {
jedis.close();
}
}
}
UserKey.java:
package com.kirin.miaosha.redis;
public class UserKey extends BasePrefix{
private UserKey(String prefix) {
super(prefix);
}
}
DemoController.java:

测试:




浙公网安备 33010602011771号