参考他人的(老版本)
https://blog.csdn.net/xjj1040249553/article/details/82658889
注意1:配置文件新版本更改:
https://blog.csdn.net/qq_33326449/article/details/80457571
json导入使用
https://blog.csdn.net/sinat_35821285/article/details/79762464
spring.redis.jedis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
redis的使用(中文官网)
http://www.redis.cn/commands.html#list
学习参考视频()
https://www.bilibili.com/video/av38657363?p=82
1.安装与开启
已经安装好了
F:\Redis-x64-3.0.504
1.1
开启服务:redis-server.exe redis.windows.conf
F:\Redis-x64-3.0.504>redis-server.exe redis.windows.conf
1.2 建立连接(可选,测试一下)
redis-cli.exe -h 127.0.0.1 -p 6379
2.引入starter
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.配置redis
#springboot配置文件 建立连接
spring.redis.host=localhost
4.springboot test使用
4.1配置类
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Manager> managerRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Manager> template = new RedisTemplate<Object, Manager>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Manager> ser=new Jackson2JsonRedisSerializer<Manager>(Manager.class);
template.setDefaultSerializer(ser);
return template;
}
}
4.2测试中使用
@Autowired
StringRedisTemplate stringRedisTemplate;//专门抽出来操作k-v都是字符串的
/**
* redis常用五大数据类型
* String() list(列表) Set(集合) Hash(散列) ZSet(有序集合)
* stringRedisTemplate.opsForValue(); String
* stringRedisTemplate.opsForList(); list
* stringRedisTemplate.opsForSet(); Set
* stringRedisTemplate.opsForHash(); Hash
* stringRedisTemplate.opsForZSet(); ZSet
*/
@Test
public void test01() {
stringRedisTemplate.opsForValue().append("msg", "hello");
String s=stringRedisTemplate.opsForValue().get("msg");
System.out.println(s);
stringRedisTemplate.opsForList().leftPush("mylist", "1");
stringRedisTemplate.opsForList().leftPush("mylist", "2");
}
@Autowired
LoginMapper loginMapper;
@Autowired
RedisTemplate<Object,Manager> managerRedisTemplate;//k-v都是对象的
//测试保存对象,需要配置,配置代码为:类MyRedisConfig
@Test
public void test02() {
//有要求Manager是可序列化的
Manager manager=loginMapper.getManagerByPasswordAndPhone("15990011043","034676");
//1.将数据以json的方式保存
//(方式1)自己将对象转化为json
//(方式2)redisTemplate默认的序列化规则
//选择方式二
managerRedisTemplate.opsForValue().set("man-01", manager);
manager =managerRedisTemplate.opsForValue().get("man-01");
System.out.println( manager.getPhone());
}
5.配置拦截器
5.1编写登录状态拦截器RedisSessionInterceptor
所有请求经过这个拦截器,除了登录请求
public class RedisSessionInterceptor implements HandlerInterceptor {
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//Object user=request.getSession().getAttribute("loginUser");
//无论访问的地址是不是正确的,都进行登录验证,登录成功后的访问再进行分发,404的访问自然会进入到错误控制器中
HttpSession session = request.getSession();
if(session.getAttribute("phone")!=null){
try
{
//验证当前请求的session是否是已登录的session
String loginSessionId = redisTemplate.opsForValue().get("loginUser:" + (String) session.getAttribute(
"phone"));//收到的是电话号码的字符串,例如"15990011043"
if (loginSessionId != null && loginSessionId.equals(session.getId()))
{
//已登录,放行请求
return true;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
//未登录
response401(response);
// request.setAttribute("msg", "没有权限请先登录");
// request.getRequestDispatcher("/index.html").forward(request,response );
return false;
}
private void response401(HttpServletResponse response)
{
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try
{
response.getWriter().print(JSON.toJSONString(new ReturnData(StatusCode.NEED_LOGIN, "", "用户未登录!")));
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
5.2编写拦截器WebSecurityConfig
@Configuration
public class WebSecurityConfig extends WebMvcConfigurationSupport {
@Bean
public RedisSessionInterceptor getSessionInterceptor(){
return new RedisSessionInterceptor();
}
@Override
protected void addInterceptors(InterceptorRegistry registry) {
//所有已api开头的访问都要进入RedisSessionInterceptor拦截器进行登录验证,并排除login接口(全路径)。必须写成链式,分别设置的话会创建多个拦截器。
//必须写成getSessionInterceptor(),否则SessionInterceptor中的@Autowired会无效
registry.addInterceptor(getSessionInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/manager" +
"/login");
super.addInterceptors(registry);
}
}
6.接收请求
@RestController
@RequestMapping(value = "/api/manager")
public class ManagerLoginController {
@Autowired
LoginMapper loginMapper;
@Autowired
private StringRedisTemplate redisTemplate;
Logger logger= LoggerFactory.getLogger(getClass());
@PostMapping("/login" )
public ReturnData loginManager(
HttpServletRequest request,
@RequestParam(value = "phone") String phone,
@RequestParam(value = "password") String password
){
logger.trace("后台接收到登录请求");
logger.trace("phone:"+phone);
logger.trace("password:"+password);
Manager manager=loginMapper.getManagerByPasswordAndPhone(phone,password);
if(manager!=null){
HttpSession session=request.getSession();
//session中存放电话号码
session.setAttribute("loginUserPhone",manager.getPhone());
//redis中存值,key:"loginUser:15990011043" value:"56D2E8E078473B331A2BBF0A83A5DD68" 即session的id
redisTemplate.opsForValue().set("loginUser:" + manager.getPhone(), session.getId());
return new ReturnData(StatusCode.REQUEST_SUCCESS, manager,"登录成功!");
}else{
return new ReturnData(StatusCode.ACCOUNT_OR_PASSWORD_ERROR,"" ,"账户名或密码错误!");
}
}
@PostMapping("/logout" )
public ReturnData loginManager(HttpServletRequest request){
logger.trace("后台接收到退出登录请求");
HttpSession session=request.getSession();
//获取session中的电话号码
String phone=(String)session.getAttribute("loginUserPhone");
logger.trace("获取session中的电话号码:"+phone);
//删除session
session.invalidate();
logger.trace("删除session");
//删除redis的session Id
redisTemplate.delete("loginUser:" +phone);
logger.trace("删除redisTemplate:"+"loginUser:" +phone);
logger.trace("删除成功");
return new ReturnData(StatusCode.REQUEST_SUCCESS,"","退出成功!");
}
}
7.遇到的问题
7.1跨域问题:
具体配置参考文章开头的链接
@Configuration
public class CORSConfiguration extends WebMvcConfigurationSupport {
@Override
protected void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//配置可以被跨域的路径
.allowedMethods("*")//allowedMethods:允许所有的请求方法访问该跨域资源服务器,如:POST、GET、PUT、DELETE等。
.allowedOrigins("http://localhost:8080")//允许所有的请求域名访问我们的跨域资源,可以固定单条或者多条内容,如:"http://www.baidu
// .com",只有百度可以访问我们的跨域资源。
.allowCredentials(true)
.allowedHeaders("*");//允许所有的请求header访问,可以自定义设置任意请求头信息,如:"X-YAUTH-TOKEN"
}
}
7.2session丢失
是因为前端使用了axios,axio
1.Vue的main.js添加:
Axios.defaults.withCredentials = true
2.springboot配置添加:
.allowedOrigins("http://localhost:8080")
.allowCredentials(true)
必须指明来源是http://localhost:8080
8.总结
总体流程就是前端发送axios请求,springboot的WebSecurityConfig(规范)进行拦截,拦截的要求在RedisSessionInterceptor里,含有session且排除必要的请求后放行。