转自:https://blog.csdn.net/qq_41305266/article/details/80956498
1. SpringBoot环境搭建
以前使用springMVC的时候,要引入一大堆xml等配置文件。引入SpringBoot的目的,就是为了简化web配置。
pom依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
目录结构
Controller控制器
package com.wings.seckill.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class DemoController {
@RequestMapping("/")
@ResponseBody
public String index(){
return "index";
}
}
启动类
package com.wings.seckill;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
使用SpringBoot后,就无需tomcat等web服务器,直接使用main函数启动即可。
2. 结果集封装
Controller在开发过程,通常主要有两个作用:1.返回json结果;2.返回页面路径。
json结果一般我们会定义以下数据结构Result:
package com.wings.seckill.result;
public class Result<T> {
private int code;
private String msg;
private T data;
public Result(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = 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;
}
}
在Controller添加一下方法:
@RequestMapping("/hello")
@ResponseBody
public Result hello(){
return new Result(0, "hello", "data");
}
@RequestMapping("/hello")
@ResponseBody
public Result hello(){
return new Result(0, "hello", "data");
}
这样做的问题是不同方法需要重复写繁琐的new,而且结果集中的code就会硬编码。
优化结果集代码如下:
package com.wings.seckill.result;
public class CodeMsg {
private int code;
private String msg;
// 通用异常
public static CodeMsg SERVER_ERROR = new CodeMsg(500100, "服务器异常");
// 业务异常
public static CodeMsg STOCK_ERROR = new CodeMsg(500200, "库存不足");
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
private CodeMsg(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
package com.wings.seckill.result;
public class Result<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) {
return new Result<T>(cm);
}
private Result(T data) {
this.code = 0;
this.msg = "success";
this.data = data;
}
private Result(CodeMsg cm) {
if (cm != null) {
this.code = cm.getCode();
this.msg = cm.getMsg();
this.data = null;
}
}
/*
* public Result(int code, String msg, T data) { this.code = code; this.msg
* = msg; this.data = data; }
*/
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
}
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) {
return new Result<T>(cm);
}
private Result(T data) {
this.code = 0;
this.msg = "success";
this.data = data;
}
private Result(CodeMsg cm) {
if (cm != null) {
this.code = cm.getCode();
this.msg = cm.getMsg();
this.data = null;
}
}
/*
* public Result(int code, String msg, T data) { this.code = code; this.msg
* = msg; this.data = data; }
*/
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
}
Controller 改为:
@RequestMapping("/hello")
@ResponseBody
public Result<String> hello(){
//return new Result(0, "hello", "data");
return Result.success("result data");
}
@RequestMapping("/helloError")
@ResponseBody
public Result<String> error(){
return Result.error(CodeMsg.SERVER_ERROR);
}
@RequestMapping("/hello")
@ResponseBody
public Result<String> hello(){
//return new Result(0, "hello", "data");
return Result.success("result data");
}
@RequestMapping("/helloError")
@ResponseBody
public Result<String> error(){
return Result.error(CodeMsg.SERVER_ERROR);
}
请求结果:
3. 视图层引入thymeleaf
pom文件添加一下依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
新增配置文件application.properties 与 视图层模板文件夹template、页面hello.html
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
<!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>
Controller 新增方法:
@RequestMapping("/thymeleaf")
public String thymeleaf(Model model){
model.addAttribute("name", "Wings");
return "hello";
}
4. 集成mybatis
pom引入mybatis和druid依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.5</version>
</dependency>
application.properties 添加相应配置
# mybatis
mybatis.type-aliases-package=com.imooc.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/imooc/miaosha/dao/*.xml
# druid
spring.datasource.url=jdbc:mysql://192.168.220.128:3306/miaosha?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
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
添加对应的实体类、dao、service
package com.wings.seckill.domain;
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = 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;
}
}
package com.wings.seckill.dao;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import com.wings.seckill.domain.User;
@Mapper
public interface UserDao {
@Select("select * from t_user where id = #{id}")
public User getById(int id);
}
package com.wings.seckill.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.wings.seckill.dao.UserDao;
import com.wings.seckill.domain.User;
@Service
public class UserService {
@Autowired
UserDao userDao;
public User getById(int id){
return userDao.getById(id);
}
}
Controller增加以下方法:
@RequestMapping("/getById")
@ResponseBody
public Result<User> getById(){
User user = userService.getById(112);
return Result.success(user);
}
配置事务处理:
@RequestMapping("/tx")
@ResponseBody
@Transactional
public Result<Integer> tx(){
int result = userService.createUser(new User(8581, "Fiorina"));
int result2 = userService.createUser(new User(8581, "Fiorina"));
return Result.success(result2);
}
5.集成Redis
到 https://redis.io/ 下载最新源码包
解压并移动目录
tar -zxvf redis-4.0.10.tar.gz mv redis-4.0.10 /usr/local/redis cd /usr/local/redis/
编译并把编译后的可执行文件添加到启动目录
make -j 4 make install
修改配置文件redis.conf
绑定允许访问的ip:bind 0.0.0.0
允许后台执行:daemonize yes
需要密码登陆:requirepass 123465
把redis做成服务
pom 添加依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
application.properties添加配置:
#redis
redis.host=120.78.235.152
redis.port=6379
redis.timeout=3
redis.password=123456
redis.poolMaxTotal=10
redis.poolMaxIdle=10
redis.poolMaxWait=3
添加redis相关操作类
package com.wings.seckill.redis;
public interface KeyPrefix {
public int expireSeconds();
public String getPrefix();
}
package com.wings.seckill.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;
}
}
package com.wings.seckill.redis;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix="redis") // 可以读取application.properties文件中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;//秒
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getPoolMaxTotal() {
return poolMaxTotal;
}
public void setPoolMaxTotal(int poolMaxTotal) {
this.poolMaxTotal = poolMaxTotal;
}
public int getPoolMaxIdle() {
return poolMaxIdle;
}
public void setPoolMaxIdle(int poolMaxIdle) {
this.poolMaxIdle = poolMaxIdle;
}
public int getPoolMaxWait() {
return poolMaxWait;
}
public void setPoolMaxWait(int poolMaxWait) {
this.poolMaxWait = poolMaxWait;
}
}
package com.wings.seckill.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@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;
}
}
package com.wings.seckill.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@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);
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);
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);
}
}
/**
* 增加值
* */
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);
}
}
/**
* 减少值
* */
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<?> clazz = value.getClass();
if(clazz == int.class || clazz == Integer.class) {
return ""+value;
}else if(clazz == String.class) {
return (String)value;
}else if(clazz == long.class || clazz == Long.class) {
return ""+value;
}else {
return JSON.toJSONString(value);
}
}
@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) {
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();
}
}
}
package com.wings.seckill.redis;
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");
}
Controller添加一以下方法:
@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(11, "wings");
redisService.set(UserKey.getById, "" + 1, user);// UserKey:id1
return Result.success(true);
}