当前位置: 首页 > news >正文

怎样在手机上面建设网站以下工具属于网站设计工具的是

怎样在手机上面建设网站,以下工具属于网站设计工具的是,网络营销公司经营范围,建设银行理财网站Redis代替session session共享问题 每个Tomcat中都有一份属于自己的session,所以多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时可能会导致数据丢失 用户第一次访问1号tomcat并把自己的信息存放session域中, 如果第二次访问到了2号tomcat就无法获取到在1号…Redis代替session session共享问题 每个Tomcat中都有一份属于自己的session,所以多台Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时可能会导致数据丢失 用户第一次访问1号tomcat并把自己的信息存放session域中, 如果第二次访问到了2号tomcat就无法获取到在1号服务器存放的信息,导致登录拦截功能会出问题 session拷贝: 每当任意一台服务器的session修改时,都会同步给其他的Tomcat服务器的session实现session的共享 每台服务器中都有完整的一份session数据导致服务器压力过大session拷贝数据时可能会出现延迟 使用Redis替换session可以实现服务器共享数据的问题 redis的三大特点: 数据共享(所有的服务器都可以在里面查询数据),内存存储(高性能),键值对的存储结构 存储用户信息key的结构 如果存入的数据(登陆用户的信息)比较简单,可以考虑使用Redis的String或hash结构存储数据 String结构: 使用JSON字符串来保存登录的用户信息,信息比较直观但不易修改数据, 并且会额外的存储一些字符占用内存 Hash结构: 将对象中的每个属性独立存储,既可以针对单个字段做CRUD, 内存占用少只会存储数据本身不用保存序列化对象信息或者JSON的一些额外字符串 基于Redis实现短信登录 Redis的key是共享的,key要具有唯一性避免其他服务器在存储数据的时候出现key重复value覆盖的问题,用户发起请求时key还要方便携带 第一步: 修改sendCode方法,验证码不再保存到session中而是保存到Redis中(手机号作为key),验证码需要设置一个有效期节省Redsi内存 public static final String LOGIN_CODE_KEY login:code:;public static final Long LOGIN_CODE_TTL 2L;// 自动注入StringRedisTemplate客户端操作Redis Autowired private StringRedisTemplate stringRedisTemplate; Override public Result sendCode(String phone, HttpSession session) throws MessagingException {// 验证邮箱的格式if (RegexUtils.isEmailInvalid(phone)) {return Result.fail(邮箱格式不正确);}// 生成验证码并保存到Redis,执行set key value ex 120String code MailUtils.achieveCode();stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY phone, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);log.info(发送登录验证码{}, code);// 发送验证码,注意子类继承的方法不能比父类抛出更多的异常MailUtils.sendTestMail(phone, code);return Result.ok(); }第二步: 修改login方法,将验证码和用户信息都存储到Redis中 存储验证码时不再存储到session中,而是将手机号作为key存储到Redis的String结构中,校验验证码时从Redis中获取验证码存储用户信息时不再是存储到session中,而是随机生成一个token(登录令牌)作为key,将用户信息转换为HashMap对象存储到Redis的Hash结构中使用StringRedisTemplate向Redis中存数据时要求key和value都是String类型,所以将对象的每个属性转换成Map集合的元素时要求key和value都是String类型 public static final String LOGIN_USER_KEY login:token:; public static final Long LOGIN_USER_TTL 30L;Override public Result login(LoginFormDTO loginForm, HttpSession session) { // 1.校验手机号String phone loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合返回错误信息return Result.fail(手机号格式错误);}// 3.从redis获取验证码并和用户提交的验证码校验比对String cacheCode stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY phone);String code loginForm.getCode();if (cacheCode null || !cacheCode.equals(code)) {// 不一致则报错return Result.fail(验证码错误);}// 4.验证码一致则根据手机号查询用户select * from tb_user where phone ?User user query().eq(phone, phone).one();// 5.判断用户是否存在if (user null) {// 6.不存在创建新用户并保存user createUserWithPhone(phone);}// 7.保存用户信息到redis中// 7.1.随机生成token作为登录令牌String token UUID.randomUUID().toString(true);// 7.2.将UserDTO对象的属性转为HashMap集合中的元素,这样一次可以存储多个键值对UserDTO userDTO BeanUtil.copyProperties(user, UserDTO.class);// 手动将UserDTO的每个属性及其值都转化为String类型并存储到HashMap集合HashMapString, String userMap new HashMap();userMap.put(icon, userDTO.getIcon());userMap.put(id, String.valueOf(userDTO.getId()));userMap.put(nickName, userDTO.getNickName());// 使用万能工具类将userDTO对象的属性转化为HashMap集合中的元素,创建CopyOptions用来自定义key和value的类型 MapString, Object userMap BeanUtil.beanToMap(userDTO, new HashMap(),CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, fieldValue) - fieldValue.toString()));// 7.3.调用putAll方法将HashMap集合存储到Redis当中String tokenKey LOGIN_USER_KEY token;stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);// 7.4.设置tokenKey有效期为30分钟stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);// 7.5 登陆成功则删除验证码信息stringRedisTemplate.delete(LOGIN_CODE_KEY phone);// 8.返回tokenreturn Result.ok(token); }第三步:前端将后端返回的token保存到浏览器当中 login(){if(!this.radio){this.$message.error(请先确认阅读用户协议);return}if(!this.form.phone || !this.form.code){this.$message.error(手机号和验证码不能为空);return}axios.post(/user/login, this.form).then(({data}) { // data是后端随机生成的tokenif(data){// 保存taken到浏览器当中sessionStorage.setItem(token, data);}// 跳转到首页,info.html是用户详情页location.href /index.html}) }// request拦截器,每次发请求都会将用户token放入请求头中 let token sessionStorage.getItem(token); axios.interceptors.request.use(config {if(token) config.headers[authorization] tokenreturn config}, )登录状态刷新问题 我们保存到Redis中的tokenKey的有效期为30分钟,在这段时间内根据用户有无操作决定是否刷新tokenKey的有效期 如果用户有操作就需要刷新tokenKey的有效期,如果用户没有任何操作30分钟后tokenKey会消失,此时登录校验时就无法获取登录用户的信息,用户需要重新登录 第一步: 修改登陆拦截器,通过拦截器拦截到的请求来证明用户是否在操作 public class LoginInterceptor implements HandlerInterceptor {//Autowired,这里不能自动装配因为LoginInterceptor是我们手动在WebConfig里new出来的并不受容器的管理private StringRedisTemplate stringRedisTemplate;public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1. 获取请求头中的tokenString token request.getHeader(authorization);//2. 如果token是空表示未登录需要拦截if (StrUtil.isBlank(token)) {response.setStatus(401);return false;}//3. 基于token作为key获取Redis的Hash结构中保存的用户数据,返回的是一个Map集合String key RedisConstants.LOGIN_USER_KEY token;MapObject, Object userMap stringRedisTemplate.opsForHash().entries(key);//4. 判断Map集合中有没有元素没有则拦截if (userMap.isEmpty()) {response.setStatus(401);return false;}//5. 将查询到的Hash结构的数据转化为UserDto对象,fasle表示不忽略转化时的错误 UserDTO userDTO BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);//6. 将用户信息保存到UserHolder类的ThreadLocal中UserHolder.saveUser(userDTO);//7. 刷新token有效期为30分钟stringRedisTemplate.expire(key, RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);//8. 放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();} }第二步: 在配置类MvcConfig注册拦截器使其生效 Configuration public class MvcConfig implements WebMvcConfigurer {Autowiredprivate StringRedisTemplate stringRedisTemplate;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册登录拦截器registry.addInterceptor(new LoginInterceptor(stringRedisTemplate)).excludePathPatterns(// 排除不需要拦截的路径/user/code,/user/login,/blog/hot,/shop/**,/shop-type/**,/upload/**,/voucher/**);} }登陆状态刷新优化 LoginInterceptor拦截器只能拦截需要登陆校验的路径,若当前用户访问了一些不会被拦截的路径,此时登录拦截器就不会生效,那么令牌刷新动作也就不会执行 第一步: 编写RefreshTokenInterceptor拦截器拦截所有路径: 负责基于token获取用户信息,然后保存用户的信息到ThreadLocal当中,同时刷新令牌的有效期 public class RefreshTokenInterceptor implements HandlerInterceptor {// 这里并不是自动装配因为RefreshTokenInterceptor是我们手动在WebConfig里new出来的private StringRedisTemplate stringRedisTemplate;// 构造方法public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate stringRedisTemplate;}Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的tokenString token request.getHeader(authorization);if (StrUtil.isBlank(token)) {return true;}// 2.基于token获取redis中的用户信息String key LOGIN_USER_KEY token;MapObject, Object userMap stringRedisTemplate.opsForHash().entries(key);// 3.判断用户是否存在if (userMap.isEmpty()) {// 用户不存在也放行交给LoginInterceptor处理return true;}// 5.将从Redis中查询到的Hash结构的数据转为UserDTO对象,fasle表示不忽略转化时的错误UserDTO userDTO BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);// 6.将用户信息保存到UserHolder类的ThreadLocal中UserHolder.saveUser(userDTO);// 7.刷新token有效期为30分钟stringRedisTemplate.expire(key, LOGIN_USER_TTL, TimeUnit.MINUTES);// 8.放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserHolder.removeUser();} }第二步: 修改LoginInterceptor登陆拦截器只负责登录校验,即只需要判断UserHolder类的ThreadLocal中是否存在用户信息,存在放行不存在则拦截 public class LoginInterceptor implements HandlerInterceptor {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 判断UserHolder类的ThreadLocal中是否有用户if (UserHolder.getUser() null) {// 用户信息不存在则拦截并设置状态码response.setStatus(401);return false;}// 用户信息存在则放行return true;} }第二步: 在配置类MvcConfig注册两个拦截器,并设置它们的执行顺序和拦截路径 拦截器的执行顺序默认按照添加的顺序执行,但也可以由order来指定顺序(数字越小优先级越高),另外如果拦截器未设置拦截路径则默认是拦截所有路径 Configuration public class MvcConfig implements WebMvcConfigurer {//自动装配Autowiredprivate StringRedisTemplate stringRedisTemplate;Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册登录拦截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(/user/code,/user/login,/blog/hot,/shop/**,/shop-type/**,/upload/**,/voucher/**).order(1); // 注册刷新token的拦截器,RefreshTokenInterceptor是我们手动new出来的,只能通过构造方法为其注入StringRedisTemplate//registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns(/**).order(0);registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).order(0);} }
http://www.w-s-a.com/news/321102/

相关文章:

  • 网站建设技术实现难点app开发需要哪些软件
  • 响水建设局网站做网站需要会哪些知识
  • 企业制作企业网站个人网站可以做百度竞价
  • 做网站找投资人wordpress 5 主题教程
  • 做国外网站汇款用途是什么wordpress图片主题晨曦
  • 网站设计跟网站开发区别为什么网站需要维护
  • m 的手机网站怎么做网络推广方式和方法
  • wordpress图片自动轮播插件seo门户网站建设
  • 制作商业网站传奇网页游戏排名
  • 网站免费推广方案长沙房地产网站设计
  • 济南网站建设cnwenhui中交路桥建设网站
  • 韶关网站开发网站建设任务分解
  • 网站建设核心点阿根廷网站后缀
  • 哪些网站可以做招商广告语学校官网页面设计
  • 十堰城市建设网站网站开发流程宜春
  • 内江网站建设郑州网站优化外包
  • 土地流转网站建设项目云南抖音推广
  • 建设银行网站无法打开2021年有没有人给个网站
  • 高端手机网站建设网站建设岗位绩效
  • 泰安网络推广 网站建设 网站优化免费素材网站psd
  • 做企业网站联系网站开发具体的工作内容
  • 联合易网北京网站建设公司怎么样网站页面开发流程
  • 2015做那些网站能致富网站建设审批表
  • 深圳 网站设计个人名片模板
  • 网站建设费用选网络专业网站在线推广
  • 天津建设网站c2成绩查询用记事本制作html网页代码
  • 织梦二次开发手机网站如何成为一名设计师
  • 网站公司建设网站镇江本地网站
  • 网页设计后面是网站建设吗凡客诚品的配送方式
  • 万链网站做的怎么样?深圳门户网站开发