1. 跨域(多出现在前后端分离项目中)
(1) 跨域介绍可参考: 跨域(CORS)
(2) SpringBoot 中解决跨域方式有:
A. 使用 @CrossOrigin 注解;
B. 实现 Filter 类, 重写 doFilter 方法
- package com.ruhuanxingyun.config;
- import cn.hutool.core.util.StrUtil;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.http.HttpHeaders;
- import org.springframework.http.HttpMethod;
- import org.springframework.http.HttpStatus;
- import javax.servlet.*;
- import javax.servlet.annotation.webFilter;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- @WebFilter(filterName = "CorsFilter")
- public class CorsFilter implements Filter {
- @Override
- public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
- HttpServletRequest request = (HttpServletRequest) req;
- HttpServletResponse response = (HttpServletResponse) res;
- response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
- response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
- // 浏览器低版本不支持 *
- response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Authorization, Content-Type");
- // 跨域时会发送 option 请求
- if (StrUtil.equals(request.getMethod(), HttpMethod.OPTIONS.name())) {
- response.setStatus(HttpStatus.OK.value());
- } else {
- chain.doFilter(req, res);
- }
- }
- }
但是 SpringBoot 整合 Shiro 后, 注解跨域就失效了, 原因: shiro 的过滤器会在注解跨域处理之前执行, 这就导致未允许跨域的请求先到达 shiro 过滤器, 这样就会出现跨域错误
(3) 在 shiro 中实现跨域, 有以下两种方式
A. 继承 BasicHttpAuthenticationFilter 类, 重写 preHandle 方法
- /**
- * 提供跨域支持
- *
- * @param request 请求对象
- * @param response 响应对象
- * @return 允许跨域
- * @throws Exception 异常信息
- */
- @Override
- protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
- HttpServletRequest httpServletRequest = (HttpServletRequest) request;
- HttpServletResponse httpServletResponse = (HttpServletResponse) response;
- httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
- httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, OPTIONS, PUT, DELETE");
- // 浏览器低版本不支持 *
- httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Authorization, Content-Type");
- // 跨域时会发送 option 请求
- if (StrUtil.equals(httpServletRequest.getMethod(), HttpMethod.OPTIONS.name())) {
- httpServletResponse.setStatus(HttpStatus.OK.value());
- return false;
- }
- return super.preHandle(request, response);
- }
B. 实现 Filter 类, 重写 doFilter 方法(如上)
2. @Cacheable 缓存 /@Transactional 事务注解失效
(1) 问题体现: 缓存和事务注解失效的类, 都是在 shiro 框架中 (loginRealm,jwtRealm) 使用过 @Autowired 注入的类, 而其他 service 事务都可以正常使用
(2) 产生原因: 在 shiro 中为了引入权限注解, 配置了 defaultAdvisorAutoProxyCreator 和 authorizationAttributeSourceAdvisor 类, 他们是通过 AOP 方式对 @RequiredPermission 类进行增强, 生成对应的代理类对象, 由于 shiroFilterFactoryBean 实现了 factoryBean 接口, 所以会被提前初始化, 所以引发所有相关的 bean 提前初始化, 导致他们没有被事务 AOP 包裹着, 从而引发事务无效的问题
(3) 解决方式
A. @Autowired + @Lazy 注解 延时加载注入
B. 在 Realm 中直接使用 mapper, 而不是 service
C. ApplicationContextRegister.getBean()方法, 手动注入 bean
SpringBoot 整合 Shiro 涉及跨域和 @Cacheable 缓存 /@Transactional 事务注解失效问题(五)
来源: http://www.bubuko.com/infodetail-3364686.html