Spring boot之拦截器与定时任务的实现

  • 场景:由于用Spring boot编写了关于Ranger策略以及Hive脱敏相关的接口,并以http方式向外部提供。
  • 为了防止请求被非法模仿,因而编写了一个访问Ip 鉴权类,也就是设置了访问ip白名单,只有在白名单上的ip才可以访问接口。
  • Spring boot自带HandlerInterceptor,可通过继承它来实现拦截功能,其的功能跟过滤器类似,但是提供更精细的的控制能力:
    在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。

代码如下所示:

1、创建拦截器,并实现业务逻辑

package com.bms.utils;

import java.io.OutputStream;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jboss.logging.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * @author YeChunBo
 * @time 2017年9月8日
 *
 *       类说明: ip 拦截器,只有在配置文件中定义了的ip 才可以访问接口
 */

public class URLInterceptor implements HandlerInterceptor {

	private static final Logger logger = Logger.getLogger(URLInterceptor.class);

	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
		// TODO Auto-generated method stub

	}

	/**
	 * 在请求处理之前进行调用(Controller方法调用之前)调用,
	 *  返回true 则放行, false 则将直接跳出方法
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
		String ip = getIpAddr(request);
		String ipStr = PropertyUtil.getProperty("ipWhiteList"); // 获取可以访问系统的白名单
		String[] ipArr = ipStr.split("\\|");
		List<String> ipList = java.util.Arrays.asList(ipArr);

		if (ipList.contains(ip)) {
			logger.info("the request ip is : " + ip);
			return true;
		} else {
			logger.error(ip + " is not contains ipWhiteList .......");
			response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8
		    String data = "您好,ip为" + ip + ",暂时没有访问权限,请联系管理员开通访问权限。";
		    OutputStream stream = response.getOutputStream();
		    stream.write(data.getBytes("UTF-8"));
			return false;
		}
	}

	/**
	 * 获取访问的ip地址
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}

}

2、注册拦截器

package com.bms.utils;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
* @author YeChunBo
* @time 2017年9月8日 
*
* 类说明: ip 鉴权类,只有在配置文件中定义了的ip 才可以访问接口
*/

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {

    @Bean   //把我们的拦截器注入为bean
    public HandlerInterceptor getMyInterceptor(){
        return new URLInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns 用于添加拦截规则, 这里假设拦截 /url 后面的全部链接
        // excludePathPatterns 用户排除拦截
        registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}

访问结果如下所示:
这里写图片描述


二、定时任务

package com.bms.qurat;

/**
* @author YeChunBo
* @time 2017年10月10日 
*
* 类说明 :定时任务的设定类
*/

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.bms.service.HdfsService;
import com.bms.service.HiveTableInfoService;
import com.bms.service.SyncGzdcTableInfo2DbService;
import com.bms.service.SyncUserVisitInfo2Db;

@Component
public class QuartzJob {

	private static final Logger logger = LoggerFactory.getLogger(Scheduled.class);

	// 每十五分钟执行一次,监控用户对于磁盘使用情况
	@Scheduled(cron = "0 0/15 * * * ?")
	public void executeMonitorTask() {
		logger.info("Scheduled.compareAllUserDiskTask is begin ....");
		// 超过磁盘设定的值后,定时任务获取对应策略,若存在create权限则修改,不存在则不改
		boolean compareAllUserDisk = HdfsService.compareAllUserDisk();
		logger.info("Scheduled.compareAllUserDiskTask and the result:" + compareAllUserDisk);
	}
	
}

其实就是在方法之上引入如下注解:

 @Scheduled(cron = "0 0/15 * * * ?")

定时任务参数说明:

* 第一位,表示秒,取值0-59
* 第二位,表示分,取值0-59
* 第三位,表示小时,取值0-23
* 第四位,日期天/日,取值1-31
* 第五位,日期月份,取值1-12
* 第六位,星期,取值1-7,星期一,星期二...,注:不是第1周,第二周的意思
          另外:1表示星期天,2表示星期一。
* 第7为,年份,可以留空,取值1970-2099

cron中,还有一些特殊的符号,含义如下:

(*)星号:可以理解为每的意思,每秒,每分,每天,每月,每年...
(?)问号:问号只能出现在日期和星期这两个位置,表示这个位置的值不确定,每天3点执行,所以第六位星期的位置,我们是不需要关注的,就是不确定的值。同时:日期和星期是两个相互排斥的元素,通过问号来表明不指定值。比如,1月10日,比如是星期1,如果在星期的位置是另指定星期二,就前后冲突矛盾了。
(-)减号:表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
(,)逗号:表达一个列表值,如在星期字段中使用“1,2,4”,则表示星期一,星期二,星期四
(/)斜杠:如:x/y,x是开始值,y是步长,比如在第一位(秒) 0/15就是,从0秒开始,每15秒,最后就是0,15,30,45,60    另:*/y,等同于0/y

下面列举几个例子供大家来验证:

0 0 3 * * ?     每天3点执行
0 5 3 * * ?     每天3点5分执行
0 5 3 ? * *     每天3点5分执行,与上面作用相同
0 5/10 3 * * ?  每天3点的 5分,15分,25分,35分,45分,55分这几个时间点执行
0 10 3 ? * 1    每周星期天,3点10分 执行,注:1表示星期天    
0 10 3 ? * 1#3  每个月的第三个星期,星期天 执行,#号只能出现在星期的位置

参考:Spring Boot 拦截器
参考:spring boot项目中处理Schedule定时任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值