在web开发的过程中,为了实现登录权限验证,我们往往需要添加一个拦截器在用户的的请求到达controller层的时候实现登录验证,那么SpringBoot如何添加拦截器呢?
步骤如下:
1.继承WebMvcConfigureAdapter类,覆盖其addInterceptors接口,注册我们自定义的拦截器:
/**
*
* 注册拦截器
* Created by SYSTEM on 2017/8/16.
*/
public class WebAppConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器,添加拦截路径和排除拦截路径
registry.addInterceptor(new InterceptorConfig()).addPathPatterns("api/path/**").excludePathPatterns("api/path/login");
}
}
2.实现HandlerInterceptor接口,重写接口中的三个方法:
public class InterceptorConfig implements HandlerInterceptor{
private static final Logger log = LoggerFactory.getLogger(InterceptorConfig.class);
/**
* 进入controller层之前拦截请求
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
log.info("---------------------开始进入请求地址拦截--- 从session获取数据如果存在就放行不存在就抛出异常拦截-------------------------");
HttpSession session = httpServletRequest.getSession();
if(!StringUtils.isEmpty(session.getAttribute("userName"))){
return true;
}
else{
PrintWriter printWriter = httpServletResponse.getWriter();
printWriter.write("{code:0,message:\"session is invalid,please login again!\"}");
return false;
}
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
log.info("--------------处理请求完成后视图渲染之前的处理操作---------------");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
log.info("---------------视图渲染之后的操作-------------------------0");
}
}
注册拦截器
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter{
/**
* 注册 拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogHandlerInterceptor());
}
}
测试:这样我们就可以在用户请求到达controller层实现登录拦截了,所有用户请求都会被拦截,在prehandle方法进行登录判断,返回true则验证通过,否则失败
UserController
@RestController
public class UserController {
@GetMapping("/user/home")
public String home(){
System.out.println("--- user home ---");
return "user home";
}
}
redis==========================
1、引入 spring-boot-starter-redis(1.4版本前),spring-boot-starter-data-redis(1.4版本后)
org.springframework.boot
spring-boot-starter-cache
org.springframework.boot
spring-boot-starter-data-redis
2,application.properties 配置文件
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0
2.SpringBoot配置文件中配置Redis连接(YAML方式配置)
spring:
application:
name: spring-boot-redis
redis:
host: 192.168.145.132
port: 6379
timeout: 20000
cluster:
nodes: 192.168.211.134:7000,192.168.211.134:7001,192.168.211.134:7002
maxRedirects: 6
pool:
max-active: 8
min-idle: 0
max-idle: 8
max-wait: -1
解释:本配置采用Redis一主三从的的配置方式来提高缓存的吞吐量
3.Redis缓存配置类提供redisTemplate(获得配置文件中连接参数后的)
@Configuration
@EnableCaching
public class RedisCacheConfig {
@Bean
public CacheManager cacheManager(RedisTemplate, ?> redisTemplate){
CacheManager cacheManager = new RedisCacheManager(redisTemplate);
return cacheManager;
}
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory){
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(factory);
// key序列化方式;(不然会出现乱码;),但是如果方法上有Long等非String类型的话,会报类型转换错误;
// 所以在没有自己定义key生成策略的时候,以下这个代码建议不要这么写,可以不配置或者自己实现ObjectRedisSerializer
// 或者JdkSerializationRedisSerializer序列化方式;
RedisSerializer redisSerializer = new StringRedisSerializer();// Long类型不可以会出现异常信息;
redisTemplate.setKeySerializer(redisSerializer);
redisTemplate.setHashKeySerializer(redisSerializer);
return redisTemplate;
}
}
Redis工具类
/**
* redicache 工具类
*
*/
@SuppressWarnings("unchecked")
@Component
public class RedisUtil {
@SuppressWarnings("rawtypes")
@Autowired
private RedisTemplate redisTemplate;
/**
* 写入缓存
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存设置时效时间
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations operations = redisTemplate.opsForValue();
operations.set(key, value);
redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 批量删除对应的value
* @param keys
*/
public void remove(final String... keys) {
for (String key : keys) {
remove(key);
}
}
/**
* 批量删除key
* @param pattern
*/
public void removePattern(final String pattern) {
Set keys = redisTemplate.keys(pattern);
if (keys.size() > 0)
redisTemplate.delete(keys);
}
/**
* 删除对应的value
* @param key
*/
public void remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
}
}
/**
* 判断缓存中是否有对应的value
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
ValueOperations operations = redisTemplate.opsForValue();
result = operations.get(key);
return result;
}
/**
* 哈希 添加
* @param key
* @param hashKey
* @param value
*/
public void hmSet(String key, Object hashKey, Object value){
HashOperations hash = redisTemplate.opsForHash();
hash.put(key,hashKey,value);
}
/**
* 哈希获取数据
* @param key
* @param hashKey
* @return
*/
public Object hmGet(String key, Object hashKey){
HashOperations hash = redisTemplate.opsForHash();
return hash.get(key,hashKey);
}
/**
* 列表添加
* @param k
* @param v
*/
public void lPush(String k,Object v){
ListOperations list = redisTemplate.opsForList();
list.rightPush(k,v);
}
/**
* 列表获取
* @param k
* @param l
* @param l1
* @return
*/
public List
import com.example.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@RequestMapping(value = "/test",method = RequestMethod.POST)
public void demoTest(){
RedisUtil.set("1","value22222");
}}
将用户信息保存到redis中
1.继承WebMvcConfigureAdapter类,覆盖其addInterceptors接口,注册我们自定义的拦截器:
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {
@Bean
public HandlerInterceptor getMyInterceptor(){
return new MyHandlerInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// addPathPatterns 用于添加拦截规则, 这里假设拦截 /url 后面的全部链接
// excludePathPatterns 用户排除拦截
registry.addInterceptor(getMyInterceptor()).addPathPatterns("/api/*");
super.addInterceptors(registry);
}
}
2.实现HandlerInterceptor接口,重写接口中的三个方法:
public class MyHandlerInterceptor implements HandlerInterceptor {
private final Logger logger = LoggerFactory.getLogger(MyHandlerInterceptor.class);
@Autowired
private RedConf conf;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
HttpServletResponse httpResponse = (HttpServletResponse) httpServletResponse;
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
boolean retMsg = false;
String token = httpServletRequest.getHeader("token");
if (null == token || token.isEmpty()) {
//json 形式返回前端
JSONObject res = new JSONObject();
res.put("success", "false");
res.put("msg", "token没有认证通过!原因为:客户端请求参数中无token信息");
out = httpResponse.getWriter();
out.append(res.toString());
logger.info("token没有认证通过!原因为:客户端请求参数中无token信息");
return retMsg;
} else {
Jedis jedis = RedisUtil.getJedis(conf.getRedisIp(),Integer.parseInt(conf.getRedisPort()),1000,conf.getRedisAuth());
boolean exits = jedis.exists(token);
if (exits) {
jedis.expire(token, 900);
retMsg = true;
logger.info("认证成功");
RedisUtil.returnResource(jedis);
return retMsg;
} else {
JSONObject res = new JSONObject();
res.put("success", "false");
res.put("msg", "当前的token已过期,请重新登陆");
out = httpResponse.getWriter();
out.append(res.toString());
logger.info("当前的token已过期,请重新登陆");
return retMsg;
}
}
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}