0、写在前面的话
一直想能仿公司框架的形式,着手作一个简单的脚手架,一来是带着目标性能更好地学习,接触新的技术,另外本身若是有什么想要实现的简单需求,就能够进行快速开发,主要仍是但愿能在权限上有所控制,因此最花时间的仍是在Shiro上。
其实目标在github已经有很多大佬的参考物了:
- zheng 基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构,提供整套公共微服务服务模块
- ES JavaEE企业级项目的快速开发的脚手架,提供了底层抽象和通用功能,拿来即用
- renren-security 轻量级权限管理系统
- lenos 快速开发模块化脚手架
我本身也试着搭建了最简单的包含权限的后端,主要是为了走通整个流程,以后也会慢慢试着参考大佬们作一款本身的架子。在整个集成过程当中,固然难免遇到了各类奇奇怪怪的问题,这里作一些简单的经验记录,避免旧坑重踩。
一、技术框架整合
1.1 Maven多模块项目的搭建
参考连接:
1.2 SpringBoot-MyBatis集成
参考连接:
1.3 SpringBoot-Shiro集成
参考连接:
二、踩坑警告
- SpringBoot 版本:2.0.3.RELEASE
- JUnit 版本:4.12
- SpringBoot-MyBatis 版本:1.3.2
- SpringBoot-Shiro 版本:1.4.0-RC2
2.1 多模块带来的注意事项
SpringBoot 多模块的单元测试须要指定注解 @SpringBootTest(classes = {Application.class}),这里的 Application.class 即你的SpringBoot启动类,这也就意味着你其余模块的测试也只能在 Application.class 所在的模块中进行,不然编译没法经过由于其余模块找不到 Application.class,固然这是由于其余模块中的依赖问题致使的。
另外须要注意的是,SpringBoot中 的 Bean 扫描默认为 Application.java 所在包及子包,因此哪怕是多模块,也请注意包名的问题,并调整 Application.java 的位置,不然很容易出现找不到 Bean 注入的状况。
若是你还使用了 MyBatis-generator,一样其对于数据源的配置文件,由于多模块的缘故,你可能也没法直接使用 SpringBoot 中 application.properties 的配置,须要单独写一个配置文件在 MyBatis-generator 使用的那个模块下。
2.2 SpringBoot+MyBatis与单元测试
若是在单元测试时发现 xxxMapper 或 xxxDao 的 Bean 没法注入,那么请注意你使用的注解了。在持久层接口上注解使用 @Mapper,而不是仅仅使用 @Repository。实际上哪怕不使用 @Repository 也能够注入持久层的 Bean,可是IDE会在Service类中报红提醒 xxxDao 没有注册 Bean,因此最好仍是加上 @Repository,尽管去掉也没有什么影响。
@Repository
@Mapper
public interface RoleDao {
int deleteByPrimaryKey(Long id);
int insert(Role record);
int insertSelective(Role record);
Role selectByPrimaryKey(Long id);
int updateByPrimaryKeySelective(Role record);
int updateByPrimaryKey(Role record);
Set<Role> findAll();
Set<Role> findByUserId(Long userId);
}
2.3 Shiro中自定义Realm的Bean注册
在 SpringBoot 和 Shiro 的集成中,Shiro的配置一般是使用一个自定义配置类,经过在方法上使用 @Bean 注解来将配置注册成 Bean,以下:
@Configuration
public class ShiroConfig {
@Bean
public Realm realm() {
return new MyRealm();
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition();
//todo "/anon" not useful
chain.addPathDefinition("/anon/*", "anon");
chain.addPathDefinition("/authc/*", "authc");
return chain;
}
}
那么在自定义的Realm中还须要单独的注解(如 @Component)标记吗?答案是不须要。以下,哪怕它之中还须要用到其余的 Bean 组件,也不须要再单独作组件注解了(加上反而由于和 @Bean 的方式冲突报错):
//无需 @Component
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//...
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//...
return null;
}
}
另外须要注意的是,在配置url访问权限时,以下两种写法请注意:
- chain.addPathDefinition("/anon", "anon"); //无效
- chain.addPathDefinition("/anon/*", "anon"); //有效
三、Demo源码