前言
这是一个基于Spring Boot的基础架构,整合了Mybatis,Shiro,Redis,Slf4j和Druid,Mybatis做持久层框架,Shiro做安全框架,Redis用来存储用户登录数据,Slf4j做日志框架,Druid用来做数据库连接池。框架已经搭好,可以直接拿来写业务逻辑。
附上项目GitHub地址:GitHub地址,会经常更新,欢迎Star和Fork。
正文
如何创建一个Spring Boot项目就不多说了,网上有太多大神写的详细教程,这篇博客就是结合本项目讲解下一个企业级Spring Boot项目的架构。首先展示下项目的结构图:
主要分为java和resources,java中存放java代码,resources中存放各种配置文件和Mybatis的相关文件。
这个项目是按照功能分的包,也可以按照controller,service,dao,entity分包,common包中存放项目中用到的非业务相关的代码,包括shiro配置文件,mybatis配置文件,druid配置文件,项目统一异常处理相关类,工具类等等。
一、Spring Boot启动类
@SpringBootApplication
@MapperScan("com.ssmshiro.**.dao")
public class SSMShiroApplication {
public static void main(String[] args) {
SpringApplication.run(SSMShiroApplication.class,args);
}
}
@SpingBootApplication是一个Spring Boot项目必要的注解,用它来标注一个Spring Boot项目的启动类。
@MapperScan是Mybatis的注解,主要用来告诉项目dao层的位置。
二、实体层
public class Goods extends BaseEntity<Goods> {
private Long goodsId;
private String name;
private String description;
private Double price;
public Long getGoodsId() {
return goodsId;
}
public void setGoodsId(Long goodsId) {
this.goodsId = goodsId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
实体层实际上就是数据库表的对应类。
这边我是继承了自己封装的一个Base,里面主要是分页的一些处理,具体可以看git上的代码。
三、Dao层
public interface GoodsDao extends BaseDao<Goods> {
}
Dao层是数据访问层,主要做数据库的交互工作,实际上就是定义好了数据库的操作方法,然后给Service业务逻辑层调用,真正的数据库语句是在下面要说的mapper里面写的。
这边一样也是继承了一个Base,里面是一些常用的数据库CRUD,具体可以看git上的代码。
四、mapper
<?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.ssmshiro.goods.dao.GoodsDao">
<resultMap id="BaseResultMap" type="com.ssmshiro.goods.entity.Goods">
<id column="GOODS_ID" jdbcType="BIGINT" property="goodsId" />
<result column="NAME" jdbcType="VARCHAR" property="name" />
<result column="DESCRIPTION" jdbcType="VARCHAR" property="description" />
<result column="PRICE" jdbcType="DOUBLE" property="price" />
</resultMap>
<sql id="Base_Column_List">
GOODS_ID, NAME, DESCRIPTION, PRICE
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from goods
where GOODS_ID = #{goodsId,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from goods
where GOODS_ID = #{goodsId,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.ssmshiro.goods.entity.Goods">
insert into goods (GOODS_ID, NAME, DESCRIPTION,
PRICE)
values (#{goodsId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
#{price,jdbcType=DOUBLE})
</insert>
<insert id="insertSelective" parameterType="com.ssmshiro.goods.entity.Goods">
insert into goods
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="goodsId != null">
GOODS_ID,
</if>
<if test="name != null">
NAME,
</if>
<if test="description != null">
DESCRIPTION,
</if>
<if test="price != null">
PRICE,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="goodsId != null">
#{goodsId,jdbcType=BIGINT},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="price != null">
#{price,jdbcType=DOUBLE},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.ssmshiro.goods.entity.Goods">
update goods
<set>
<if test="name != null">
NAME = #{name,jdbcType=VARCHAR},
</if>
<if test="description != null">
DESCRIPTION = #{description,jdbcType=VARCHAR},
</if>
<if test="price != null">
PRICE = #{price,jdbcType=DOUBLE},
</if>
</set>
where GOODS_ID = #{goodsId,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="com.ssmshiro.goods.entity.Goods">
update goods
set NAME = #{name,jdbcType=VARCHAR},
DESCRIPTION = #{description,jdbcType=VARCHAR},
PRICE = #{price,jdbcType=DOUBLE}
where GOODS_ID = #{goodsId,jdbcType=BIGINT}
</update>
</mapper>
mapper是Mybatis的映射文件,里面实现了数据库的操作语句,每个CRUD操作的ID都必须和Dao层中的方法名相对应,这样才能通过调用Dao层的接口实现数据库操作。
五、Service层
@Service
public class GoodsService extends BaseService<GoodsDao,Goods> {
@Autowired
private GoodsDao goodsDao;
@Transactional(readOnly = false)
public void save(Goods goods){
try{
goodsDao.insert(goods);
}catch (Exception e){
throw new ServiceException(InfoCode.EMSG0001);
}
}
public Goods get(Long id){
try{
return goodsDao.selectByPrimaryKey(id);
}catch (Exception e){
throw new ServiceException(InfoCode.EMSG0004);
}
}
}
Service层是业务逻辑层,一般业务逻辑都是写在这层中,也是在这层中进行调用Dao层接口。
@Service用于标注业务层组件。
这边也是继承了一个Base,里面封装了一些基本的Service层方法。
六、Controller层
@RestController
@RequestMapping("/goods")
public class GoodsController extends BaseController<GoodsService,GoodsDao,Goods> {
@Autowired
private GoodsService goodsService;
@RequestMapping(value = "/save",method = RequestMethod.POST)
public ResultEntity<String> save(@RequestBody Goods goods){
goodsService.save(goods);
return new ResultEntity<String>().OK(InfoCode.IMSG0001);
}
@RequestMapping(value = "/get/{id}",method = RequestMethod.GET)
public ResultEntity<Goods> getById(@PathVariable Long id){
return new ResultEntity<Goods>().OK(goodsService.get(id),InfoCode.IMSG0004);
}
}
Controller层是控制器层,主要用来做地址拦截,进入方法后调用Service层进行业务逻辑处理,相当于以前写Servlet时的web.xml。
@RestController是@Controller和@ResponseBody的结合,@Controller用于标注控制层组件,@ResponseBody作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据,这之中需要注意的是假如用了@RestController标注控制层,那么这个控制层中所有方法的返回都不会去执行视图处理器,也就是只能返回数据,不能返回视图。所以假如有需求需要返回视图的话,就用@Controller去标注,在需要格式化返回数据的时候再在需要的方法上加上@ResponseBody。
@RequestMapping是用来处理地址映射的注解,标注在类上则表示该类的所有处理地址映射的方法都以此路径作为父路径,这个注解有六个常用属性value,method,consumes,produces,params,headers,其中最常用的就是value和method。
value指定了请求的实际地址,也可以是URI Template模式的地址,也就是如
@RequestMapping(value = "/get/{id}",method = RequestMethod.GET)
这样的value,这个id在控制层中用
public ResultEntity<Goods> getById(@PathVariable Long id)
@Pathvariable注解去获取,然后将值赋给注解后定义的变量。
method指定了请求的类型,值可以是GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE,一般用到POST和GET就行,其他的介绍可以看这篇文章,这个已经介绍的很详细了。
如何使用
首先修改application.yml配置文件,主要就是数据库改为自己的。
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8
然后修改mybatis_generator.properties属性配置文件
#数据库配置
#jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8
jdbc_url=jdbc:mysql://localhost:3306/test
jdbc_driver=com.mysql.jdbc.Driver
jdbc_username=root
jdbc_password=123456
#输出目录
targetProject=src/main/java
modelPackage=com.ssmshiro.goods.entity
daoMapperPackage=com.ssmshiro.goods.dao
#输出名称
tableName=goods
modelName=Goods
mapperName=GoodsDao
这个主要是Mybatis generator自动生成插件的属性,具体的插件配置文件是generatorConfig.xml。
修改完之后run mybatis-generator:generate,如图
成功的话会在定义的包下生成entity和dao以及mapper文件,然后让entity和dao继承Base,写好Service层和Controller层代码,一个模块的基础就写好了。
结尾
第一次写博客,其中还是有很多混乱和不足的地方,以后会多加改进,有啥问题可以提出来,每天我都会看下这个博客的,以后也会经常写些学到的东西啥的,最后,谢谢各位能够花时间看我写的小博客,欢迎Star哈。