1、拦截器中的拦截核心代码。代码中的事例是同一个接口,在同一秒内被允许访问2次。给方法支持多台服务器多实例,高并发场景。
package com.zh.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.zh.usd.service.UserAdminAccountServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.zh.util.Authentication;
import com.zh.util.MsgUtils;
import com.zh.util.USDConstants;
import lombok.extern.slf4j.Slf4j;
/**
* @ClassName: AuthorizationInterceptor
* @Description:
* @author: renkai721
* @date: 2019年6月14日 下午3:45:47
*/
@Slf4j
@Component
@Configuration
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
@Value("{bmusd.job.deleteTempUploadTask}")
private String deleteFile;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
BodyReaderHttpServletRequestWrapper requestWrapper = null;
if (request instanceof BodyReaderHttpServletRequestWrapper) {
requestWrapper = (BodyReaderHttpServletRequestWrapper) request;
String url = requestWrapper.getRequestURI();
if("/user/checkUsername".equals(url)){
JSONObject jsonObject = JSONObject.parseObject(requestWrapper.getBody());
Object keyObj = jsonObject.get("username");
if(keyObj != null){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Date d = new Date();
String time = sdf.format(d);
String key = keyObj.toString()+"_"+time;
try{
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-redis.xml");
// redisTemplate = applicationContext.getBean(RedisTemplate.class);
// incr是线程安全,支持多台服务器多节点部署
// incr先去查找这个key如果没有自动创建,赋值=0,然后加1,如果get到的值为1,说明是第一次。
// 在没有失效的时间里,会进行加1的操作。
// redisCommands = redisProvider.GetCommand();
// Long incrment = redisCommands.incr(key);
Long incrment = stringRedisTemplate.opsForValue().increment(key);
synchronized (incrment){
if(incrment.longValue() == 1){
// 设置key的有效期为1s,1s后这个key自动消失
// redisCommands.expire(key, 1);
stringRedisTemplate.expire(key,1, TimeUnit.SECONDS);
}
int maxRequestCount = 2;
if(incrment.longValue() > maxRequestCount){
PrintWriter out = response.getWriter();
String msg = MsgUtils.outJson("一个用户1秒内只能请求2次,系统繁忙!");
out.print(msg);
out.flush();
return false;
}
}
}catch (Exception e){
e.printStackTrace();
}
}else{
PrintWriter out = response.getWriter();
String msg = MsgUtils.outJson("用户名不能为空!");
out.print(msg);
out.flush();
return false;
}
}
}
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
BodyReaderHttpServletRequestWrapper requestWrapper;
if (request instanceof BodyReaderHttpServletRequestWrapper) {
// // 测试再次获取Body start....
requestWrapper = (BodyReaderHttpServletRequestWrapper) request;
// String url = requestWrapper.getRequestURL().toString();
// JSONObject params = JSON.parseObject(getBodyString(requestWrapper));
// log.info("客户端请求的URL=" + url+",JSON="+params);
// // 测试再次获取Body end....
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
/**
* 获取请求Body
* @param request
* @return
*/
public static String getBodyString(final ServletRequest request) {
StringBuilder sb = new StringBuilder();
InputStream inputStream = null;
BufferedReader reader = null;
try {
inputStream = cloneInputStream(request.getInputStream());
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
/**
* Description: 复制输入流</br>
* @param inputStream
* @return</br>
*/
public static InputStream cloneInputStream(ServletInputStream inputStream) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return byteArrayInputStream;
}
}