1.前后端分离的web项目-后台管理系统
2.外置tomcat,保留web.xml
3.打包方式:war
4.yml配置
1.支持多数据源
2.文件上传
3.定时
4.异步
5.shiro 权限整合
6.log4j
#切换不同运行环境的配置
spring:
profiles:
active: local
---
#开发配置
spring:
profiles: local
# double mysql datasource
datasource:
# 数据源1
db1:
jdbc-url:
username:
password:
driver-class-name: com.mysql.cj.jdbc.Driver
# type: com.alibaba.druid.pool.DruidDataSource
type: org.apache.commons.dbcp2.BasicDataSource
dbcp2:
initialSize: 2
maxTotal: 4
minIdle: 2
maxWaitMillis: 5000
validationQuery: select 1
maxConnLifetimeMillis: 43200000
timeBetweenEvictionRunsMillis: 14400000
numTestsPerEvictionRun: 500
# 数据源2
#db2:
# session
session:
store-type: none
#停用jmx监控,tomcat多个项目使用相同数据源名时会部署失败;
jmx:
enabled: false
# mybatis backpage
mybatis:
typeAliasesPackage: demo.model
#mapperLocations: classpath:mapper/*.xml
---
#test environment
spring:
profiles: test
datasource:
# db1
db1:
jdbc-url:
username:
password:
driver-class-name: com.mysql.cj.jdbc.Driver
# type: com.alibaba.druid.pool.DruidDataSource
type: org.apache.commons.dbcp2.BasicDataSource
dbcp2:
initialSize: 2
maxTotal: 4
minIdle: 2
maxWaitMillis: 5000
validationQuery: select 1
maxConnLifetimeMillis: 43200000
timeBetweenEvictionRunsMillis: 14400000
numTestsPerEvictionRun: 500
# db2
#db2:
# session
session:
store-type: none
jmx:
enabled: false
# mybatis backpage
mybatis:
typeAliasesPackage: demo.model
#config-location:
依旧在webapp->WEB-INF下
version="3.0">
** * 启动类 */ // controller,service等扫描路径 : 默认扫描和启动类同个包下文件 @EnableScheduling // 启用spring定时 @EnableTransactionManagement//数据库事务 @EnableAsync //异步 @SpringBootApplication public class SpringBootBackApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringBootBackApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(SpringBootBackApplication.class); } /** * 去除multipartResolver 冲突,上传文件配置 * * @return */ @Bean(name = "multipartResolver") public CommonsMultipartResolver multipartResolver() { CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); multipartResolver.setDefaultEncoding("UTF-8"); // resolveLazily属性启用是为了推迟文件解析,以在在UploadAction中捕获文件大小异常 // multipartResolver.setResolveLazily(true); multipartResolver.setMaxInMemorySize(5120); // 上传文件大小 30M 30*1024*1024 multipartResolver.setMaxUploadSize(30 * 1024 * 1024); return multipartResolver; } /** * 文件上传配置 * * @return */ // @Bean // public MultipartConfigElement multipartConfigElement() { // MultipartConfigFactory factory = new MultipartConfigFactory(); // // 单个文件最大 // factory.setMaxFileSize("30MB"); // KB,MB // /// 设置总上传数据总大小 // factory.setMaxRequestSize("30MB"); // return factory.createMultipartConfig(); // } /** * redis * * @return */ // @Bean // public static ConfigureRedisAction configureRedisAction() { // return ConfigureRedisAction.NO_OP; // } }
5.1数据源注册
/* * db1的数据源,事务,工厂等配置 */ @Configuration @MapperScan(basePackages = "hotkidclub.mapper", sqlSessionTemplateRef = "db1SqlSessionTemplate") public class MasterDataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.db1") @Primary public DataSource db1DataSource() { return DataSourceBuilder.create().build(); } @Bean @Primary public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:hotkidclub/mapper/*.xml")); return bean.getObject(); } @Bean @Primary public DataSourceTransactionManager db1TransactionManager(@Qualifier("db1DataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean @Primary public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
5.2 Mvc 可根据具体应用场景配置
/** * Mvc相关配置 * * Interceptors:拦截器 * * ArgumentResolvers: 参数绑定解析器 * * ViewControllers:页面跳转 * * ResourceHandlers:静态资源 * * configureDefaultServletHandling:默认静态资源处理器 * * configureViewResolvers:视图解析器 * * configureContentNegotiation:配置内容裁决的一些参数 * * addCorsMappings:跨域 * * configureMessageConverters:信息转换器 */ @Configuration public class WebConfigurer implements WebMvcConfigurer { @Autowired private LoggedInInterceptor loggedInInterceptor; @Autowired private LoginUserInfoResolver loginUserInfoResolver; /** * 配置静态资源:html,js,css,等等 * * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { } /** * 注册拦截器:自定义的拦截器需要通过这里添加注册才能生效 * * * @param registry */ // @Override // public void addInterceptors(InterceptorRegistry registry) { // registry.addInterceptor(loggedInInterceptor).addPathPatterns("/**").excludePathPatterns("/login.ctrl");// 添加请求路径拦截,以及不包含的路径(不拦截) // registry.addInterceptor(loggedInInterceptor);// 在注册时不指定拦截路径,通过拦截器中判断是否函数带有isLogin(自定义)的注解来拦截 // } /** * 注册:参数绑定解析器 * * @param argumentResolvers */ @Override public void addArgumentResolvers(ListargumentResolvers) { //argumentResolvers.add(loginUserInfoResolver); } }
6.1 自定义realm
/** * shiro 核心组件-realm : 处理用户资源权限,实现认证和授权 */ public class ShiroRealm extends AuthorizingRealm { @Autowired RoleService roleService; /** * 认证器 : ** 本平台用户登入接口调用-subject.login() : 回调该函数 *
* * @param authcToken 凭证信息:可存放用户账号密码 * @return 认证信息:包含当前请求登入的用户信息 * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { Subject subject = SecurityUtils.getSubject(); // 1.获取认证的主体信息:账户密码 UsernamePasswordToken token = (UsernamePasswordToken) authcToken; // 2.可校验数据库存储的账号密码(本系统在登入接口的service层已处理) // 3.创建简单认证信息对象可存放相关信息 : (object, object, 字符串);可传递自定义对象,字符内容; // Session session = subject.getSession(); // session.setAttribute("user", token.getPrincipal()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName()); return info; } /** * 授权器 : 校验用户的角色和权限 ** 本平台接口配置角色/权限的授权注解时 : 回调该函数 *
* * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String principal = (String) principalCollection.getPrimaryPrincipal(); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 1.通过用户名去数据库查询该用户的角色和权限 MapverifyInfo = roleService.getAuthorizationInfo(principal); Set rs = (Set) verifyInfo.get("roleNames"); Set ps = (Set) verifyInfo.get("permissionCodes"); // 2.设置角色信息 if (rs != null && rs.size() > 0) { info.addRoles(rs); } // 3.设置权限信息 if (ps != null && ps.size() > 0) { info.addStringPermissions(ps); } return info; } }
6.2自定义异常
public class AuthenticationFilter extends FormAuthenticationFilter { //未登入 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { response.setContentType("application/json; charset=utf-8"); response.setCharacterEncoding("UTF-8"); response.getWriter().print("{\"errorCode\":444,\"errorMsg\":\"未登入\"}"); response.flushBuffer(); return false; } }
/** * 全局未授权异常-捕获&处理 * * 本项目使用场景: shiro鉴权时抛出的未授权异常未处理直接响应客户端,使用全局异常注解@ControllerAdvice 捕获处理 * */ @RestControllerAdvice public class UnauthorizedExceptionHandler { /** * 处理UnauthorizedException * * @param req * @param e * @return */ @ExceptionHandler(value = UnauthorizedException.class) public Map, ?> defaultExceptionHandler(HttpServletRequest req, Exception e) { Mapexception_response = new HashMap<>(); exception_response.put("errorCode", 445); exception_response.put("errorMsg", "拒绝访问-权限不足"); return exception_response; } }
后期持续更新springBoot的各种应用场景...