本人实际开发中没用到过springboot框架,但因为最近springboot实在是太火了,然后就自己搭建了一套,当然,参考了许多优秀的coder写的博客,不过大多数都是零碎的,所以就想写一套完整的框架搭建流程。
开发工具:eclipse
搭建前准备工作:
1.java环境(不多说)
2.本地maven配置安装(网上很多教程)
3.redis配置安装(很简单,官网下个压缩包解压即可)
1。搭建springboot工框架
a.打开elipse,邮件NEW--》project--》Maven Project,然后一直下一步
b.输入Group Id以及Artifact Id,两个可以一样,我直接用的项目名,然后finish即可,到这里,你的maven项目创建成功
c:添加jar包(在pom.xml里添加):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.3.2.RELEASE</spring.version>
<slf4j.version>1.7.12</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<junit.version>4.12</junit.version>
<spring-data-redis.version>1.7.2.RELEASE</spring-data-redis.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql依赖jar -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 【redis】配置 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring-data-redis.version}</version>
<type>jar</type>
</dependency>
<!-- log -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- redis集成mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
编写代码,在编写代码之前我这里要强调一下的是,spring-boot项目有严格的层级要求,所以在编码前,最好是先把要建的文件夹给建好。我这里顺序是这样的,在src/main下面建三个文件夹,分别是java(主要是写代码的地方),resources(主要是配置文件的地方),webapp(主要是装页面的地方),我这里先写个Controller,同传统spring一样,然后再controller包同级的地方写个启动类Start。启动main方法,在浏览器输入:localhost:8080/home,到此,springboot框架就搭建好了。
注意:为什么要在controller包同级的地方写个启动类Start,这是为了然Start处于最外层,这样他能够读取到Controller里面所有的配置文件,当然啦,你也可以在com.cn.controller下面去屑启动方法,不过这样不利于后面测试,因为你每写一个controller都需要改start方法
代码结构如下:
UserController代码:
package com.cn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController{
@RequestMapping("/home")
@ResponseBody
public String getHome() {
return "hello,spring-boot!!!";
}
}
Start代码:
package com.cn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
}
2.集成mybatis(这一块同以前的spring框架集成类似)
a.因为我本地用的是mysql,所以在pom文件我加的是mysql的驱动jar,同时加入mybatis依赖的jar
<!-- mybaties依赖jar -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- mysql依赖jar -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
b.在resources文件夹下面创建applicaiton.properties,然后将数据源写入文件
###############数据库mybaties配置###############
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.cn.entity
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = kangbiao1234
c.编码,在编码之前,同样是先建好文件夹,大家可以仿照我这边的目录结构,然后写入相应的java文件以及xml文件。当然啦,大家得先建立好数据库
User:
package com.cn.entity;
import java.io.Serializable;
import java.util.List;
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public String id;
public int age;
public String name;
public List<User> userlist;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUserlist() {
return userlist;
}
public void setUserlist(List<User> userlist) {
this.userlist = userlist;
}
}
UserMapper.java:
package com.cn.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.cn.entity.User;
@Mapper
public interface UserMapper {
List<User> getAll();
User getOne(Integer id);
void insert(User user);
void update(User user);
void delete(Integer id);
}
userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.cn.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.cn.entity.User">
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List">
id, name, age
</sql>
<select id="getAll" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM user
</select>
<select id="getOne" parameterType="java.lang.Integer" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM user
WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.cn.entity.User">
INSERT INTO
user
(id,name,age)
VALUES
(#{id},#{name}, #{age})
</insert>
<update id="update" parameterType="com.cn.entity.User">
UPDATE
user
SET
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
WHERE
id = #{id}
</update>
<delete id="delete" parameterType="java.lang.Integer">
DELETE FROM
user
WHERE
id =#{id}
</delete>
</mapper>
mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="callSettersOnNulls" value="true" />
<!-- 这个配置使全局的映射器启用或禁用缓存。系统默认值是true,设置只是为了展示出来 -->
<setting name="cacheEnabled" value="true" />
<!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 系统默认值是true,设置只是为了展示出来 -->
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="true" />
<!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动)。 系统默认值是true,设置只是为了展示出来 -->
<setting name="multipleResultSetsEnabled" value="true" />
<!--使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方 法来决定所使用的驱动。 系统默认值是true,设置只是为了展示出来 -->
<setting name="useColumnLabel" value="true" />
<!--允许 JDBC 支持生成的键。需要适合的驱动。如果设置为 true,则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如 Derby)。 系统默认值是false,设置只是为了展示出来 -->
<setting name="useGeneratedKeys" value="false" />
<setting name="autoMappingBehavior" value="PARTIAL" />
<!--配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新 系统默认值是SIMPLE,设置只是为了展示出来 -->
<setting name="defaultExecutorType" value="SIMPLE" />
<!-- 开启驼峰匹配 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="NULL" />
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>
d.在HomeController.java这个文件里加上如下代码即可。到此,springboot+mybatis框架搭建完成
@Autowired
private UserMapper userMapper;
@RequestMapping("/getUsers")
public String getUsers(Model model) {
List<User> users = userMapper.getAll();
model.addAttribute("users", users);
return "user/userList";
}
3.集成redis
a.在pom文件里面引入redis相关jar
<!-- 【redis】配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<!-- redis集成mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
b.接下来在application.properties文件里面加入redis的配置
#redis
#redis数据库名称 从0到15,默认为db0
spring.redis.database=0
#redis服务器名称
spring.redis.host=127.0.0.1
#redis服务器密码
spring.redis.password=
#redis服务器连接端口号
spring.redis.port=6379
#redis连接池设置
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.maxTotal=8
spring.redis.pool.maxWaitMillis=1000
#spring.redis.sentinel.master=
#spring.redis.sentinel.nodes=
spring.redis.timeout=60000
c.创建缓存实现类以及中间类
MybatisRedisCache:
package com.cn.redis;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import com.cn.controler.HomeController;
import redis.clients.jedis.exceptions.JedisConnectionException;
public class MybatisRedisCache implements Cache {
private static JedisConnectionFactory jedisConnectionFactory;
private final static Logger logger = LoggerFactory.getLogger(HomeController.class);
private final String id;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public MybatisRedisCache(final String id) {
logger.info("====================MybatisRedisCache=====================");
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public void clear() {
logger.info("====================clear=====================");
RedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
connection.flushDb();
connection.flushAll();
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public String getId() {
logger.info("====================getId=====================");
return this.id;
}
@Override
public Object getObject(Object key) {
logger.info("====================getObject=====================");
Object result = null;
RedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = serializer.deserialize(connection.get(serializer.serialize(key)));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
@Override
public int getSize() {
logger.info("====================getSize=====================");
int result = 0;
RedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
result = Integer.valueOf(connection.dbSize().toString());
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
@Override
public void putObject(Object key, Object value) {
logger.info("====================putObject=====================");
RedisConnection connection = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
}
@Override
public Object removeObject(Object key) {
logger.info("====================removeObject=====================");
RedisConnection connection = null;
Object result = null;
try {
connection = jedisConnectionFactory.getConnection();
RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
result = connection.expire(serializer.serialize(key), 0);
} catch (JedisConnectionException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.close();
}
}
return result;
}
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
MybatisRedisCache.jedisConnectionFactory = jedisConnectionFactory;
}
}
RedisCacheTransfer:
package com.cn.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
@Component
public class RedisCacheTransfer {
@Autowired
public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
MybatisRedisCache.setJedisConnectionFactory(jedisConnectionFactory);
}
}
d:创建redis数据源applicationContext-cache.xml
applicationContext-cache.xml:
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${spring.redis.maxIdle}" />
<property name="maxTotal" value="${spring.redis.maxActive}" />
<property name="maxWaitMillis" value="${spring.redis.maxWait}" />
<property name="testOnBorrow" value="${spring.redis.testOnBorrow}" />
</bean>
<!-- Spring-redis连接池管理工厂 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${spring.redis.host}" p:port="${spring.redis.port}" p:password="${spring.redis.password}" p:pool-config-ref="poolConfig">
</bean>
<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
<bean id="redisCacheTransfer" class="com.cn.redis.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
</bean>
e.在userMpper.xml文件里面加入Mybatis二级缓存
<cache type="com.cn.redis.MybatisRedisCache" /> 这里的路径就是刚刚编写的缓存实现类
f.到此,springboot+mybatis+redis的框架搭建完成
拓展:引入日志
因为springboot的jar已经引入了loggin的jar,所以这里不需要加入其它日志的jar,在resources下创建logback-spring.xml,然后再application.properties里面引入路径
logback-spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="/log" />
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/log.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--myibatis log configure-->
<!-- <logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/> -->
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<!--日志异步到数据库 -->
<!--<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">-->
<!--<!–日志异步到数据库 –>-->
<!--<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">-->
<!--<!–连接池 –>-->
<!--<dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">-->
<!--<driverClass>com.mysql.jdbc.Driver</driverClass>-->
<!--<url>jdbc:mysql://127.0.0.1:3306/databaseName</url>-->
<!--<user>root</user>-->
<!--<password>root</password>-->
<!--</dataSource>-->
<!--</connectionSource>-->
<!--</appender>-->
</configuration>
application.properties加入如下配置
#日志配置路径
logging.config=classpath:logback-spring.xml
#打印sql语句
logging.level.com.cn.mapper=DEBUG
处理异常以及数据返回格式:
public class Msg<T> {
/*错误码*/
private Integer code;
/*提示信息 */
private String msg;
/*具体内容*/
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer 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;
}
}
返回数据格式:
public class ResultUtil {
/**
* 请求成功返回
* @param object
* @return
*/
public static Msg success(Object object){
Msg msg=new Msg();
msg.setCode(200);
msg.setMsg("请求成功");
msg.setData(object);
return msg;
}
public static Msg success(){
return success(null);
}
public static Msg error(Integer code,String resultmsg){
Msg msg=new Msg();
msg.setCode(code);
msg.setMsg(resultmsg);
return msg;
}
}