org.springframework.boot
spring-boot-starter-data-redis
即redis相关配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password: abc[mYedmy7Bank+r28xgfer+wxEgIsCY+lnHTmZlzzwdQ1R0jFXBRVPUc6UUKAQm3mN]
redis:
host: localhost
port: 6379
password:
database: 15
jedis:
pool:
max-active: 8
max-wait: -1
max-idle: 500
min-idle: 0
lettuce:
shutdown-timeout: 0
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 定义一个注解标明需要使用限流的接口
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
int seconds();
int maxCount();
}
import com.alibaba.fastjson.JSONObject;
import com.one.smile.test.service.RedisService;
import com.one.smile.test.utils.AccessLimit;
import com.one.smile.test.utils.SystemUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
@Configuration
public class WebSecurityConfig implements HandlerInterceptor {
@Autowired
private RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果请求输入方法
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
//获取方法中的注解,看是否有该注解
AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
if (accessLimit != null) {
long seconds = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
//关于key的生成规则可以自己定义。本项目需求是对每个方法都加上限流功能,如果你只是针对ip地址做限流,那么key只需要用ip即可
String key = SystemUtil.getIpAddr(request) + hm.getMethod().getName();
//从redis中获取用户访问的次数
//此操作代表取该key对应的值自增1后的结果
long q = redisService.incr(key, seconds);
if (q > maxCount) {
//加1
JSONObject jsonObject = new JSONObject();
jsonObject.put("status", 0);
jsonObject.put("msg", "请求过于频繁,请稍后再试");
jsonObject.put("data", null);
render(response, jsonObject);
return false;
}
return true;
}
}
return true;
}
private void render(HttpServletResponse response, JSONObject cm) throws Exception {
response.setContentType("application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
String str = cm.toString();
out.write(str.getBytes("UTF-8"));
out.flush();
out.close();
}
}
public interface RedisService {
/**
* set存数据
*
* @param key
* @param value
* @return
*/
boolean set(String key, String value);
/**
* get获取数据
*
* @param key
* @return
*/
String get(String key);
/**
* 设置有效天数
*
* @param key
* @param expire
* @return
*/
boolean expire(String key, long expire);
/**
* 移除数据
*
* @param key
* @return
*/
boolean remove(String key);
/**
* 获取自增1后的 值
*
* @param key
* @param time
* @return
*/
Long incr(String key, long time);
}
import com.one.smile.test.service.RedisService;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Service
public class RedisServiceImpl implements RedisService {
@Resource
private RedisTemplate redisTemplate;
@Override
public boolean set(final String key, final String value) {
boolean result = redisTemplate.execute(new RedisCallback() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer = redisTemplate.getStringSerializer();
connection.set(serializer.serialize(key), serializer.serialize(value));
return true;
}
});
return result;
}
@Override
public String get(final String key) {
String result = redisTemplate.execute(new RedisCallback() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer = redisTemplate.getStringSerializer();
byte[] value = connection.get(serializer.serialize(key));
return serializer.deserialize(value);
}
});
return result;
}
@Override
public boolean expire(final String key, long expire) {
return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
}
@Override
public boolean remove(final String key) {
boolean result = redisTemplate.execute(new RedisCallback() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
RedisSerializer serializer = redisTemplate.getStringSerializer();
connection.del(key.getBytes());
return true;
}
});
return result;
}
@Override
public Long incr(String key, long time) {
long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
//设置有效期一分钟
set(key, "1");
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return count;
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
/**
* 获取系统的信息
*/
public final class SystemUtil {
/**
* 命令获取mac地址
*
* @param cmd
* @return
*/
private static String callCmd(String[] cmd) {
String result = "";
String line = "";
try {
Process proc = Runtime.getRuntime().exec(cmd);
InputStreamReader is = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader(is);
while ((line = br.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @param cmd 第一个命令
* @param another 第二个命令
* @return 第二个命令的执行结果
*/
private static String callCmd(String[] cmd, String[] another) {
String result = "";
String line = "";
try {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(cmd);
proc.waitFor(); // 已经执行完第一个命令,准备执行第二个命令
proc = rt.exec(another);
InputStreamReader is = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader(is);
while ((line = br.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @param ip 目标ip,一般在局域网内
* @param sourceString 命令处理的结果字符串
* @param macSeparator mac分隔符号
* @return mac地址,用上面的分隔符号表示
*/
private static String filterMacAddress(final String ip, final String sourceString, final String macSeparator) {
String result = "";
String regExp = "((([0-9,A-F,a-f]{1,2}" + macSeparator + "){1,5})[0-9,A-F,a-f]{1,2})";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(sourceString);
while (matcher.find()) {
result = matcher.group(1);
if (sourceString.indexOf(ip) <= sourceString.lastIndexOf(matcher.group(1))) {
break; // 如果有多个IP,只匹配本IP对应的Mac.
}
}
return result;
}
/**
* 获取访问地址的IP
*/
public static String getHostAddress(HttpServletRequest request) {
String ipAddr = "";
InetAddress address = null;
try {
String serverName = request.getServerName();
if (isboolIp(serverName)) {
ipAddr = serverName;
} else {
address = InetAddress.getByName(serverName);
ipAddr = address.getHostAddress();
}
} catch (Exception e) {
e.printStackTrace();
}
return ipAddr;
}
/**
* 获取来访者的主机名称
*
* @param ip
* @return
*/
public static String getHostName(String ip) {
InetAddress inet;
try {
inet = InetAddress.getByName(ip);
return inet.getHostName();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "";
}
/**
* 获取访问者IP 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。
*
* 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割), 如果还不存在则调用Request
* .getRemoteAddr()。
*
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Real-IP");
if (ip != null && !"".equals(ip) && !"unknown".equalsIgnoreCase(ip)) {
return ip;
}
ip = request.getHeader("X-Forwarded-For");
if (ip != null && !"".equals(ip) && !"unknown".equalsIgnoreCase(ip)) {
// 多次反向代理后会有多个IP值,第一个为真实IP。
int index = ip.indexOf(',');
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
} else {
return request.getRemoteAddr();
}
}
/**
* 获取MAC地址
*
* @return 返回MAC地址
*/
public static String getMacAddress(String ip) {
String macAddress = "";
macAddress = getMacInWindows(ip).trim();
if (macAddress == null || "".equals(macAddress)) {
macAddress = getMacInLinux(ip).trim();
}
return macAddress;
}
/**
* @param ip 目标ip
* @return Mac Address
*/
private static String getMacInLinux(final String ip) {
String result = "";
String[] cmd = {"/bin/sh", "-c", "ping " + ip + " -c 2 && arp -a"};
String cmdResult = callCmd(cmd);
result = filterMacAddress(ip, cmdResult, ":");
return result;
}
/**
* @param ip 目标ip
* @return Mac Address
*/
private static String getMacInWindows(final String ip) {
String result = "";
String[] cmd = {"cmd", "/c", "ping " + ip};
String[] another = {"cmd", "/c", "arp -a"};
String cmdResult = callCmd(cmd, another);
result = filterMacAddress(ip, cmdResult, "-");
return result;
}
/**
* 获取来访者的浏览器版本
*
* @param request
* @return
*/
public static String getRequestBrowserInfo(HttpServletRequest request) {
String browserVersion = null;
String header = request.getHeader("user-agent");
if (header == null || header.equals("")) {
return "";
}
if (header.indexOf("MSIE 6.0") > 0) {
browserVersion = "IE 6";
} else if (header.indexOf("MSIE 7.0") > 0) {
browserVersion = "IE 7";
} else if (header.indexOf("MSIE 8.0") > 0) {
browserVersion = "IE 8";
} else if (header.indexOf("MSIE 9.0") > 0) {
browserVersion = "IE 9";
} else if (header.indexOf("MSIE 10.0") > 0) {
browserVersion = "IE 10";
} else if (header.indexOf("rv:11.0") > 0) {
browserVersion = "IE 11";
} else if (header.indexOf("Firefox") > 0) {
browserVersion = "Firefox";
} else if (header.indexOf("Chrome") > 0) {
browserVersion = "Chrome";
} else if (header.indexOf("Safari") > 0) {
browserVersion = "Safari";
} else if (header.indexOf("Camino") > 0) {
browserVersion = "Camino";
} else if (header.indexOf("Konqueror") > 0) {
browserVersion = "Konqueror";
}
return browserVersion;
}
/**
* 获取系统版本信息
*
* @param request
* @return
*/
public static String getRequestSystemInfo(HttpServletRequest request) {
String systenInfo = null;
String header = request.getHeader("user-agent");
if (header == null || header.equals("")) {
return "";
}
// 得到用户的操作系统
if (header.indexOf("NT 6.0") > 0) {
systenInfo = "Windows Vista/Server 2008";
} else if (header.indexOf("NT 5.2") > 0) {
systenInfo = "Windows Server 2003";
} else if (header.indexOf("NT 5.1") > 0) {
systenInfo = "Windows XP";
} else if (header.indexOf("NT 6.0") > 0) {
systenInfo = "Windows Vista";
} else if (header.indexOf("NT 6.1") > 0) {
systenInfo = "Windows 7";
} else if (header.indexOf("NT 6.2") > 0) {
systenInfo = "Windows Slate";
} else if (header.indexOf("NT 6.3") > 0) {
systenInfo = "Windows 9";
} else if (header.indexOf("NT 10.0") > 0) {
systenInfo = "Windows 10";
} else if (header.indexOf("NT 5") > 0) {
systenInfo = "Windows 2000";
} else if (header.indexOf("NT 4") > 0) {
systenInfo = "Windows NT4";
} else if (header.indexOf("Me") > 0) {
systenInfo = "Windows Me";
} else if (header.indexOf("98") > 0) {
systenInfo = "Windows 98";
} else if (header.indexOf("95") > 0) {
systenInfo = "Windows 95";
} else if (header.indexOf("Mac") > 0) {
systenInfo = "Mac";
} else if (header.indexOf("Unix") > 0) {
systenInfo = "UNIX";
} else if (header.indexOf("Linux") > 0) {
systenInfo = "Linux";
} else if (header.indexOf("SunOS") > 0) {
systenInfo = "SunOS";
}
return systenInfo;
}
/**
* 判断是否为合法IP * @return the ip
*/
public static boolean isboolIp(String ipAddress) {
String ip = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
Pattern pattern = Pattern.compile(ip);
Matcher matcher = pattern.matcher(ipAddress);
return matcher.matches();
}
public static void main(String[] args) {
InetAddress address = null;
try {
address = InetAddress.getByName("f0rb.iteye.com");
} catch (UnknownHostException e) {
e.printStackTrace();
System.out.println("获取失败");
}
System.out.println(address.getHostAddress());
}
}