基于自定义注解解决cross跨域

基于自定义注解解决cross跨域

1、起因

最近开发的项目前台使用axios发送HTTP请求,在打开控制台的时候出现缺少相关响应头的警告。
后台使用jfinal,#spring 有CrossOrign 注解可以处理cross请求,也可以配置类实现。

2、过程

1.注解

 `@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrign {
	/**
	 * @info 例外路径,即不添加corss的响应头信息的方法
	 * @return
	 */
	String[] exceptionPath() default {};
}
  1. 这里使用反射获取注解的相关信息;
public class AnnotationUtil {
	// 指定包下的所有类名
	private static  List<String> list = new ArrayList<>();
	// 可以访问的地址
	private static List<String> allowPath = new ArrayList<>();


	static {
		List<String> list = PackageUtil.getClassName("com.sinosoft.controller");
		if (list != null) {
			AnnotationUtil.list = list;
			getAccessPath();
		}
	}
	
	/**
	 * @info 获取可以访问的路径
	 */
	private static void getAccessPath() {
		final String slash = "/";
		for (String str : AnnotationUtil.list) {
			try {
				Class<?> clazz = Class.forName(str);
				ControllerBind bind = clazz.getAnnotation(ControllerBind.class);
				if (bind != null) {
					String ck = bind.controllerKey();
					CrossOrign co = clazz.getAnnotation(CrossOrign.class);
					if (co != null) {
						String[] method = co.exceptionPath();
						Method[] methods = clazz.getDeclaredMethods();
						// 所有方法名
						List<String> list = new ArrayList<>();
						for (Method method2 : methods) {
							list.add(slash + method2.getName());
						}
						list.removeAll(Arrays.asList(method));
						// 允许访问的路径
						allowPath.add(ck);
						for (String string : list) {
							allowPath.add(ck + string);
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * @info 校验地址
	 * @param uri
	 * @return
	 */
	public static boolean validation(String uri) {
		return allowPath.contains(uri);
	}

3.后台配置一个过滤器,只过滤添加了@CrossOrign和不在 exceptionPath的方法(jfinal 自定义的controller 继承了Controller抽象类,除了index方法,剩下的方法方法名即为action)

public class CorsFilter implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		String uri = request.getRequestURI();
		String options = "OPTIONS";
		String method = request.getMethod();
		String contextPath = request.getContextPath();
		// 如果URL地址最后有/ 需要替换成""
		uri = uri.replace(contextPath, "");
		uri = uri.endsWith("/") ? uri.substring(0, uri.length() - 1) : uri;
		boolean flag = AnnotationUtil.validation(uri);
		if (flag) {
			System.out.println(uri + "可以添加跨域响应头");
			// 指定允许其他域名访问
			response.addHeader("Access-Control-allow-Origin", "*");
			// 响应类型
			response.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With,Content-Type, Accept");
			// 响应头设置
			response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT,DELETE");
			// axios的post请求第一次会进行预请求,get方法试用qs.stringify()方法可以不进行预请求
			if (options.equals(method) || options.toLowerCase().equals(method)) {
				return;
			}
		}
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {

	}
// 注意:这里的filter需要配置在com.jfinal.core.JFinalFilter jfinal过滤器的前面

4.将我们的自定义注解添加到需要的controller中,启动,完成
5.nginx也可以解决cross跨域的问题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值