电影售票系统遇到的问题(*暂时名字)
-
实现分页
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" @prev-click="handlePrevClick" @next-click="handleNextClick" :current-page="currentPage" :page-sizes="[10, 20, 30, 40, 50]" :page-size="10" layout=" prev, pager, next, jumper, sizes, total" :total='total'> </el-pagination>
queryForPage(current, size){ axios.get("/user/" + current + "/" + size).then((res) => { this.tableData = res.data.data.records; this.total = res.data.data.total; }) },
current为当前页码,size为每页显示的条数
-
实现从一个框架中控制另外一个框架显示的页面
通过在另外一个框架中使用a标签利用href属性填写要跳转的页面,target中填要指定框架的名字
<el-menu-item index="1-1"><a href="./user/list.html" target="main">用户</a></el-menu-item>
-
实现从一个框架中将参数传至另外一个框架
以往一直在编写的都是前台的UI,不多使用到frameset、iframe,对其了解也是十分有限,只是知道其能够为其当前页面引入html文件成为当前页的一部分,可是这两天在作后台UI界面的时候,发现这样的框架也是有至关多知识点在里面的。那框架是啥?能够这样说:经过使用框架,你能够在同一个浏览器窗口中显示不止一个页面。每份HTML文档称为一个框架,而且每一个框架都独立于其余的框架。那么关于框架,有几个方面是须要我了解的:html (1)得到html页面上的frame浏览器 window.frames能够得到本页面上全部frame集合,用法与document.forms,document.imgs的用法类似,这是这里用的是window对象,获取某个框架能够这样作window.frames[0]、window.frames['frameName']、frames['frameName']、frames[0]、self.frames[0],此处self与window等价,至关于本页面的window对象。框架 这里也还要再看两个属性,contentWindow、contentDocument两个属性,也是能够用来获取子窗口,框架的window对象的。函数 contentWindow 兼容各个浏览器,可取得子窗口的 window 对象。spa contentDocument Firefox 支持,> ie8 的ie支持。可取得子窗口的 document 对象。code 假如我要刷新本页面中第一个框架的页面,能够怎么作:orm window.frames[0].contentWindow.location.reload(); (2)父框架调用子框架的变量或函数htm 结合上面说的得到页面上的frame,那么调用子框架的变量或是函数能够这样来:对象 frames[0].a; frames[0].refresh(); alert(frames[0].location.href); 这是调用第一个框架里面的a变量和refresh函数。blog (3)子框架调用父框架的变量或函数 对于子框架调用父框架的这种状况下,window有个属性叫parent,用来调用上层框架的,因此能够这样来: window.parent.a; window.parent.refresh(); 这是调用子框架调用父框架的a变量和refresh函数。 (4)兄弟框架之间的调用 能够经过它们的父框架来相互调用,能够这样作 self.parent.frames['child1']; self.parent.frames['child2']; (5)多层框架的调用 window.frames[0].frames[2]; window.frames['child_1'].frames['sub_child_3']; (6)顶层框架 首先须要判断是否为顶层框架,也就是根,能够这样来作: if(self==window.top){ //.... } /*window的另一个属性top,它表示对顶层框架的引用,这能够用来判断一个框架自身是否为顶层框架*/
-
实现将vue中的参数传至js中
this.selectDataVisible = self.toggle; 将js中的参数传至vue同理
-
实现定时获取即定义方法,每隔一段时间刷新,在钩子函数created中调用即可,注意写的位置不同不影响结果
fresh:function (){ setInterval(() =>{ this.selectDataVisible = self.toggle; }, 500) },
特别注意:data中的数据只会执行一次
-
实现对话框通过关闭选项关闭
-
编译错误
- 考虑是内容格式不对,注意要使用英文下的字符
-
将表中查询的对象转化为前端要显示的对象
/** * 转换一个对象 * @param source * @param target * @param <O> * @param <V> * @return */ public static <O,V> V copyBean(O source, Class<V> target){ //创建目标对象 V result = null; try { result = target.newInstance(); //实现属性copy BeanUtils.copyProperties(source, result); } catch (Exception e) { e.printStackTrace(); } //返回结果 return result; } /** * 转换一个列表 * @param list * @param target * @param <O> * @param <V> * @return */ public static <O,V> List<V> copyBeanList(List<O> list, Class<V> target){ return list.stream() .map(o -> copyBean(o, target)) .collect(Collectors.toList()); } /** * 将获取的参数转化为输出对象 * @return */ @GetMapping public Result getAll(){ List<Role> roles = roleService.list(null); List<RoleVo> roleVos = BeanCopyUtils.copyBeanList(roles, RoleVo.class); return new Result(null, roleVos, null); }
-
如何用vue给img的src属性绑定变量
利用v-bind与字符串拼接将变量绑定上去注意,整个字符串是在双引号里,然后内部用+号把单引号拼接起来,特别注意src前面要加:
<a href="#" @click="redirect(tableData[0].id)"> <img :src="'/images/film_img/' + tableData[0].img"> </a>
-
根据值灵活给class绑定对应的属性
<el-row class="seat" v-for="(item, index) in seats" :gutter="20"> <el-col :span="2" :offset="0">{{index+1}}</el-col> <el-col :span="1" v-for="(i, j) in seats[index]" :offset="1" :class="'i[j].userId' == null ? 'element' : 'en_element'" @click="swift()"></el-col> </el-row>
特别注意:原生的元素要用引号括起来,不然会识别成Vue中的变量或方法
-
mysql报错Out of range value for column ‘user_id’ at row 1] with root cause,数据库修改数据或插入数据的时候发生错误,找错要明确错误发生的位置是前端接口写错,还是后端不能识别,又或者是在识别后写入服务器发生错误。要注意数据库中bigint类型不能写入负数,然后要进行接口测试时最好使用postman
-
Vue中通过点击当前元素,的到当前元素位置,并设置属性
@click="swift(index, j, $event)"//元素中给方法形参添加$event属性
swift:function (i, j, event){ if(this.addSeats.length < 4){ //通过event.target获取当前元素 event.target.setAttribute('class', 'on_element') this.addSeats.push(this.seats[i][j]); this.sum += this.session.sellingPrice; }else{ this.$message.warning("一次性最多能购买四张票!"); } },
API #当前点击的元素 e.target #是你绑定事件的元素 e.currentTarget #获得点击元素的前一个元素 e.currentTarget.previousElementSibling.innerHTML #获得点击元素的第一个子元素 e.currentTarget.firstElementChild # 获得点击元素的下一个元素 e.currentTarget.nextElementSibling # 获得点击元素中id为string的元素 e.currentTarget.getElementById("string") # 获得点击元素的string属性 e.currentTarget.getAttributeNode('string') # 获得点击元素的父级元素 e.currentTarget.parentElement # 获得点击元素的前一个元素的第一个子元素的HTML值 e.currentTarget.previousElementSibling.firstElementChild.innerHTML
注意:如果要使用框架的话能用框架自带的方法尽量用自带的方法,要不然转换很麻烦
-
将日期全部改成指定的格式
配置
package com.liuwei.config; import com.alibaba.fastjson.serializer.SerializeConfig; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebConfig implements WebMvcConfigurer { @Bean public HttpMessageConverter fastJsonHttpMessageConverters(){ //需要定义一个Convert转换消息对象 FastJsonHttpMessageConverter fastConvert = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); //SerializeConfig.getGlobalInstance().put(Long.class, ToStringSerializer.instance); fastJsonConfig.setSerializeConfig(SerializeConfig.getGlobalInstance()); fastConvert.setFastJsonConfig(fastJsonConfig); HttpMessageConverter<?> converter = fastConvert; return converter; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(fastJsonHttpMessageConverters()); } // @Override // public void addCorsMappings(CorsRegistry registry) { // //允许跨域路径 // registry.addMapping("/**") // //允许域名 // .allowedOrigins("*") // //允许cookie // .allowCredentials(true) // //允许请求的方式 // .allowedMethods("GET", "POST", "DELETE", "PUT") // //允许header属性 // .allowedHeaders("*") // //允许跨域时间 // .maxAge(3600); // // } }
注意:之后开发Web项目先将后端开发完,再集成权限管理系统、再实现登录注册
-
SpringSecurity报empty encoded password
原因是未获到值,将User中的password字段的不查询密码注解删除就可以了 @Override public String getPassword() { return user.getPassword(); }
-
授权问题
-
主配置类
package com.liuwei.config; import com.liuwei.filter.AuthenticationTokenFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.annotation.Resource; @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 自定义用户认证逻辑 */ @Resource private UserDetailsService userDetailsService; /** * 注入passwordEncorder到spring容器 * @return */ @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } @Resource private AuthenticationEntryPoint authenticationEntryPoint; @Resource private AccessDeniedHandler accessDeniedHandler; @Resource AuthenticationTokenFilter authenticationTokenFilter; @Override protected void configure(HttpSecurity http) throws Exception { //解决frame框架不能嵌套 http.headers().frameOptions().disable(); //设置没有权限访问跳转自定义页面 http.exceptionHandling().accessDeniedPage("/pages/unauth.html"); //退出,这里是退出前端接口的约定 http.logout().logoutUrl("/login/logout").logoutSuccessUrl("/index.html").permitAll(); //表单登录 http.formLogin(). //设置登录页面 loginPage("/pages/login.html") //设置登录接口地址 .loginProcessingUrl("/user/login") //登录成功跳转 .defaultSuccessUrl("/pages/router.html") //失败跳转 .failureForwardUrl("/fail") .permitAll(); //都需要身份验证 http.authorizeRequests() //对于登录接口允许匿名访问 //既可以写接口也可以静态资源 .antMatchers("/login", "/login/register", "/captcha/code", "/pages/regist.html").anonymous() .antMatchers("/pages/**").hasAnyRole("ROLE_管理员", "ROLE_会员") //所有静态资源允许匿名访问 .antMatchers("/css/**", "/js/**", "/images/**", "/plugins/**", "/index.html").permitAll() //其它全部请求需要鉴权认证 .anyRequest().authenticated(); //关闭csrf http.csrf().disable(); //把token校验过滤器添加到过滤器中 http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); //配置异常处理类 http.exceptionHandling() //配置认证失败处理器 .authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler); } @Bean @Override protected AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } /** * 身份认证接口 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //告诉SpringSecurity 我们要使用自己定义的userDetailService来通过 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } }
-
实现UserDetail查询用户是否存在,及授权
package com.liuwei.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.liuwei.domain.*; import com.liuwei.service.MenuService; import com.liuwei.service.RoleMenuService; import com.liuwei.service.RoleService; import com.liuwei.service.UserService; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; //该类的主要目的是用于获取用户,如果连账号都找不到 @Service public class UserDetailServiceImpl implements UserDetailsService { @Resource private UserService userService; @Resource private RoleMenuService roleMenuService; @Resource private MenuService menuService; @Resource private RoleService roleService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //根据用户名查询信息 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.eq(User::getUsername, username); User user = userService.getOne(lambdaQueryWrapper); //如果查询不到数据就通过抛出异常来给出信息 if(Objects.isNull(user)) throw new RuntimeException("用户名或密码错误!"); //TODO 根据用户查询权限信息,添加到LoginUser中 LambdaQueryWrapper<RoleMenu> lambdaQueryWrapper1 = new LambdaQueryWrapper<>(); lambdaQueryWrapper1.eq(RoleMenu::getRoleId, user.getRole()); LambdaQueryWrapper<Role> queryWrapperRole = new LambdaQueryWrapper<>(); //获取用户角色 queryWrapperRole.eq(Role::getId, user.getRole()); Role role = roleService.getOne(queryWrapperRole); //角色列表 List<String> menus = new ArrayList<>(); //将角色加到权限表中 menus.add("ROLE_" + role.getName()); roleMenuService.list(lambdaQueryWrapper1).stream() .forEach(roleMenu -> { LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>(); menuLambdaQueryWrapper.eq(Menu::getId, roleMenu.getMenuId()); menus.add(menuService.getOne(menuLambdaQueryWrapper).getMenuName()); }); //根据当前用户的roleId去权限角色关联表中将对应的权限id查询出来,最后再将所有权限封装给list return new LoginUser(user, menus); } }
-
LoginUser实现对用户信息的封装,包括权限以及一些配置信息
package com.liuwei.domain; import com.alibaba.fastjson.annotation.JSONField; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @Data @AllArgsConstructor @NoArgsConstructor @Service public class LoginUser implements UserDetails { private User user; //存储权限信息 private List<String> permissions; public LoginUser(User user, List<String> permissions){ this.user = user; this.permissions = permissions; } //存储SpringSecurity所需要的权限信息的集合 @JSONField(serialize = false) private List<GrantedAuthority> authorities; @Override public Collection<? extends GrantedAuthority> getAuthorities() { if(authorities != null) return authorities; //把permissions中字符串类型的权限信息转换成GrantedAuthority对象存入authorities中 authorities = permissions.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); return authorities; } @Override public String getPassword() { return user.getPassword(); } @Override public String getUsername() { return user.getUsername(); } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
-
token权限认证过滤器
package com.liuwei.filter; import com.liuwei.domain.LoginUser; import com.liuwei.utils.JwtUtil; import com.liuwei.utils.RedisCache; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.Objects; @Component public class AuthenticationTokenFilter extends OncePerRequestFilter { @Autowired private RedisCache redisCache; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { //获取token String token = request.getHeader("token"); if(!StringUtils.hasText(token)){ //放行 filterChain.doFilter(request, response); return; } //解析token String userid; //从session中获取用户信息 try { Claims claims = JwtUtil.parseJWT(token); userid = claims.getSubject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("token非法"); } //从redis中获取用户信息 String redisKey = "login:" + userid; LoginUser loginUser = redisCache.getCacheObject(redisKey); if(Objects.isNull(loginUser)){ throw new RuntimeException("用户未登录!"); } //存入SecurityContextHolder //todo 获取权限信息Authentication中 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); //放行 filterChain.doFilter(request, response); } }
-
认证失败处理
package com.liuwei.exception; import com.alibaba.fastjson.JSON; import com.liuwei.utils.Result; import com.liuwei.utils.WebUtils; import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { Result result = new Result(HttpStatus.UNAUTHORIZED.value(), null, "认证失败请重新登录"); //通过JSON。toJsonString将对象转化为JSON对象 String json = JSON.toJSONString(result); WebUtils.renderString(httpServletResponse, json); } }
-
权限不足处理
package com.liuwei.exception; import com.alibaba.fastjson.JSON; import com.liuwei.utils.Result; import com.liuwei.utils.WebUtils; import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class AccessDeniedHandlerImpl implements AccessDeniedHandler { @Override public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { Result result = new Result(HttpStatus.FORBIDDEN.value(), null, "权限不足"); String json = JSON.toJSONString(result); WebUtils.renderString(httpServletResponse, json); } }
-
接口授权
/** * 将获取的参数转化为输出对象 * * * @return */ @GetMapping @PreAuthorize("hasRole('ROLE_管理员')") public Result getAll(){ List<Menu> menus = menuService.list(); List<MenuVo> menuVos = BeanCopyUtils.copyBeanList(menus, MenuVo.class); return new Result(null, menuVos, null); }
-
Redis序列化
package com.liuwei.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import com.alibaba.fastjson.parser.ParserConfig; import org.springframework.util.Assert; import java.nio.charset.Charset; /** * Redis使用FastJson序列化 * * @author sg */ public class FastJsonRedisSerializer<T> implements RedisSerializer<T> { public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private Class<T> clazz; static { ParserConfig.getGlobalInstance().setAutoTypeSupport(true); } public FastJsonRedisSerializer(Class<T> clazz) { super(); this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return JSON.parseObject(str, clazz); } protected JavaType getJavaType(Class<?> clazz) { return TypeFactory.defaultInstance().constructType(clazz); } }
-
JWT工具类
package com.liuwei.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; import java.util.Date; import java.util.UUID; /** * JWT工具类 */ public class JwtUtil { //有效期为 public static final Long JWT_TTL = 60 * 60 *1000L;// 60 * 60 *1000 一个小时 //设置秘钥明文 public static final String JWT_KEY = "liuwei"; public static String getUUID(){ String token = UUID.randomUUID().toString().replaceAll("-", ""); return token; } /** * 生成jtw * @param subject token中要存放的数据(json格式) * @return */ public static String createJWT(String subject) { JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间 return builder.compact(); } /** * 生成jtw * @param subject token中要存放的数据(json格式) * @param ttlMillis token超时时间 * @return */ public static String createJWT(String subject, Long ttlMillis) { JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间 return builder.compact(); } private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; SecretKey secretKey = generalKey(); long nowMillis = System.currentTimeMillis(); Date now = new Date(nowMillis); if(ttlMillis==null){ ttlMillis=JwtUtil.JWT_TTL; } long expMillis = nowMillis + ttlMillis; Date expDate = new Date(expMillis); return Jwts.builder() .setId(uuid) //唯一的ID .setSubject(subject) // 主题 可以是JSON数据 .setIssuer("sg") // 签发者 .setIssuedAt(now) // 签发时间 .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥 .setExpiration(expDate); } /** * 创建token * @param id * @param subject * @param ttlMillis * @return */ public static String createJWT(String id, String subject, Long ttlMillis) { JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间 return builder.compact(); } public static void main(String[] args) throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjYWM2ZDVhZi1mNjVlLTQ0MDAtYjcxMi0zYWEwOGIyOTIwYjQiLCJzdWIiOiJzZyIsImlzcyI6InNnIiwiaWF0IjoxNjM4MTA2NzEyLCJleHAiOjE2MzgxMTAzMTJ9.JVsSbkP94wuczb4QryQbAke3ysBDIL5ou8fWsbt_ebg"; Claims claims = parseJWT(token); System.out.println(claims); } /** * 生成加密后的秘钥 secretKey * @return */ public static SecretKey generalKey() { byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); return key; } /** * 解析 * * @param jwt * @return * @throws Exception */ public static Claims parseJWT(String jwt) throws Exception { SecretKey secretKey = generalKey(); return Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(jwt) .getBody(); } }
-
Redis缓存配置
package com.liuwei.utils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.TimeUnit; @SuppressWarnings(value = { "unchecked", "rawtypes" }) @Component public class RedisCache { @Autowired public RedisTemplate redisTemplate; /** * 缓存基本的对象,Integer、String、实体类等 * * @param key 缓存的键值 * @param value 缓存的值 */ public <T> void setCacheObject(final String key, final T value) { redisTemplate.opsForValue().set(key, value); } /** * 缓存基本的对象,Integer、String、实体类等 * * @param key 缓存的键值 * @param value 缓存的值 * @param timeout 时间 * @param timeUnit 时间颗粒度 */ public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); } /** * 设置有效时间 * * @param key Redis键 * @param timeout 超时时间 * @return true=设置成功;false=设置失败 */ public boolean expire(final String key, final long timeout) { return expire(key, timeout, TimeUnit.SECONDS); } /** * 设置有效时间 * * @param key Redis键 * @param timeout 超时时间 * @param unit 时间单位 * @return true=设置成功;false=设置失败 */ public boolean expire(final String key, final long timeout, final TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } /** * 获得缓存的基本对象。 * * @param key 缓存键值 * @return 缓存键值对应的数据 */ public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); } /** * 删除单个对象 * * @param key */ public boolean deleteObject(final String key) { return redisTemplate.delete(key); } /** * 删除集合对象 * * @param collection 多个对象 * @return */ public long deleteObject(final Collection collection) { return redisTemplate.delete(collection); } /** * 缓存List数据 * * @param key 缓存的键值 * @param dataList 待缓存的List数据 * @return 缓存的对象 */ public <T> long setCacheList(final String key, final List<T> dataList) { Long count = redisTemplate.opsForList().rightPushAll(key, dataList); return count == null ? 0 : count; } /** * 获得缓存的list对象 * * @param key 缓存的键值 * @return 缓存键值对应的数据 */ public <T> List<T> getCacheList(final String key) { return redisTemplate.opsForList().range(key, 0, -1); } /** * 缓存Set * * @param key 缓存键值 * @param dataSet 缓存的数据 * @return 缓存数据的对象 */ public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) { BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key); Iterator<T> it = dataSet.iterator(); while (it.hasNext()) { setOperation.add(it.next()); } return setOperation; } /** * 获得缓存的set * * @param key * @return */ public <T> Set<T> getCacheSet(final String key) { return redisTemplate.opsForSet().members(key); } /** * 缓存Map * * @param key * @param dataMap */ public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { if (dataMap != null) { redisTemplate.opsForHash().putAll(key, dataMap); } } /** * 获得缓存的Map * * @param key * @return */ public <T> Map<String, T> getCacheMap(final String key) { return redisTemplate.opsForHash().entries(key); } /** * 往Hash中存入数据 * * @param key Redis键 * @param hKey Hash键 * @param value 值 */ public <T> void setCacheMapValue(final String key, final String hKey, final T value) { redisTemplate.opsForHash().put(key, hKey, value); } /** * 获取Hash中的数据 * * @param key Redis键 * @param hKey Hash键 * @return Hash中的对象 */ public <T> T getCacheMapValue(final String key, final String hKey) { HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); return opsForHash.get(key, hKey); } /** * 删除Hash中的数据 * * @param key * @param hkey */ public void delCacheMapValue(final String key, final String hkey) { HashOperations hashOperations = redisTemplate.opsForHash(); hashOperations.delete(key, hkey); } /** * 获取多个Hash中的数据 * * @param key Redis键 * @param hKeys Hash键集合 * @return Hash对象集合 */ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { return redisTemplate.opsForHash().multiGet(key, hKeys); } /** * 获得缓存的基本对象列表 * * @param pattern 字符串前缀 * @return 对象列表 */ public Collection<String> keys(final String pattern) { return redisTemplate.keys(pattern); } }
-
Redis配置
package com.liuwei.utils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { @Bean @SuppressWarnings(value = { "unchecked", "rawtypes" }) public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class); // 使用StringRedisSerializer来序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); // Hash的key也采用StringRedisSerializer的序列化方式 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } }
-
WebUtils
package com.liuwei.utils; import javax.servlet.http.HttpServletResponse; public class WebUtils { /** * 将字符串渲染到前端 * @param response * @param string * @return */ public static String renderString(HttpServletResponse response, String string){ try{ response.setStatus(200); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); response.getWriter().print(string); } catch (Exception e){ e.printStackTrace(); } return null; } }
-
依赖配置
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>
-
-
前端携带token