项目二03
1.优化请求
1.1.解决问题
发送异步请求方式的弊端:
使用原先的ajax发送异步请求
服务端获取
@RequiredLogin
@GetMapping("/currentUser")
public JsonResult currentUser(HttpServletRequest request) {
//获取token
String token = request.getHeader("token");
System.out.println(token);
//根据token获取UserInfo对象
UserInfo userInfo = userInfoRedisSerivce.getUserByToken(token);
//返回封装UserInfo对象的JsonResult对象
return JsonResult.success(userInfo);
}
缓存中获取
@Override
public UserInfo getUserByToken(String token) {
//判空
if(!StringUtils.hasText(token)){
return null;
}
token = RedisKeys.USER_LOGIN_TOKEN.join(token);
String userString = redisTemplate.opsForValue().get(token);
UserInfo userInfo = JSON.parseObject(userString,UserInfo.class);
//重新设置key值
redisTemplate.expire(token,RedisKeys.USER_LOGIN_TOKEN.getTime(),TimeUnit.SECONDS);
return userInfo;
}
1.2.封装
2.登录
目的:做权限判断
权限判断:过滤器->拦截器->Shiro->网关
2.1.组件介绍
tomcat三大组件和框架
2.2.拦截器实现
代码实现
public class CheckLoginInterceptor implements HandlerInterceptor {
@Autowired
private IUserInfoRedisSerivce userInfoRedisSerivce;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//if (!(handler instanceof HandlerMethod)) {
// return true;
//}
//if (((HandlerMethod) handler).hasMethodAnnotation(RequiredLogin.class)) {
//获取token
String token = request.getHeader("token");
//获取缓存的用户信息
UserInfo userByToken = userInfoRedisSerivce.getUserByToken(token);
if (userByToken == null) {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
return false;
}
//}
return true;
}
}
配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean
public CheckLoginInterceptor checkLoginInterceptor() {
return new CheckLoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkLoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/users/login")
.excludePathPatterns("/users/checkPhone")
.excludePathPatterns("/users/sendVerifyCode")
.excludePathPatterns("/users/regist");
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
//重写父类提供的跨域请求处理的接口
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOriginPatterns("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Header1", "Header2");
}
};
}
}
2.3.跨域问题
1.发起请求,协议,ip,端口不一致为跨域请求
2.跨域请求的methods为options,域请求不会携带原本请求的token信息
3.服务器接受跨域请求,与事先的跨域配置进行匹配,匹配成功,允许跨域访问,否则不允许,最后服务器向浏览器响应跨域信息
4.服务器如果不允许则报错,浏览器如果没有接受响应或者无法解析响应结果也会报错
域请求方法springMVC使用PreFlightHandler类来封装,需要过滤掉
if (!(handler instanceof HandlerMethod)) {
return true;
}
域请求明细
方法对象分类
HandlerMethod方法与拦截器关系
1.springMVC启动后,会扫描带有@Request注解的方法,将该方法的信息封装到HandlerMethod对象中
2.将HandlerMethod对象封装到一个类似Map集合的容器中
3.浏览器发起请求,前端控制器根据路径的key值获取该容器的HandlerMethod对象
4.拦截器逻辑判断,如果路径的key值符合拦截器的拦截规则,创建拦截器对象,执行拦截器方法,再执行HandlerMethod方法
2.4.权限优化
拦截器拦截所有请求,执行的方法都是放行,如果方法头上有注解,则需要进行判断,如果没有token,则不允许放行
拦截注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredLogin {
}
代码实现
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
if (((HandlerMethod) handler).hasMethodAnnotation(RequiredLogin.class)) {
//获取token
String token = request.getHeader("token");
//获取缓存的用户信息
//每次访问重新设置缓存时间
UserInfo userByToken = userInfoRedisSerivce.getUserByToken(token);
if (userByToken == null) {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
return false;
}
}
return true;
}
3.项目
3.1.表设计
1.所见字段
2.隐藏字段(时间,序号:控制排序,状态:可能有多个,比如热门)
3.与现有表存在的关联关系(区域地 ->目的地)
3.2.数据库三范式
3.3.步骤
准备模型,Mapper,Service,QueryObject,静态文件,启动类
后端项目添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>cn.wolfcode.com</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
添加依赖
server.port=9999
#freemarker
spring.freemarker.suffix=.ftl
spring.freemarker.settings.number_format=0.##
#elasticsearch
#spring.data.elasticsearch.cluster-name=elasticsearch
#spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
#spring.data.elasticsearch.repositories.enable=true
分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true); //合理化
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
Controller代码
@Autowired
private IRegionSerivce regionSerivce;
@Autowired
private IDestinationSerivce destinationSerivce;
@RequestMapping("/list")
public String list(Model model, @ModelAttribute("qo") RegionQuery regionQuery){
model.addAttribute("page",regionSerivce.queryPage(regionQuery));
model.addAttribute("dests",destinationSerivce.list());
return "region/list";
}
@RequestMapping("/saveOrUpdate")
@ResponseBody
public JsonResult SaveOrUpdate(Region region){
regionSerivce.saveOrUpdate(region);
return JsonResult.success();
}
@RequestMapping("/delete")
@ResponseBody
public JsonResult delete(Long id){
if(id!=null){
regionSerivce.removeById(id);
}
return JsonResult.success();
}
ServiceImpl
@Override
public IPage<Region> queryPage(RegionQuery regionQuery) {
IPage<Region> page = new Page<>(regionQuery.getCurrentPage(), regionQuery.getPageSize());
QueryWrapper<Region> wrapper = new QueryWrapper<>();
return page(page,wrapper);
}
springMVC细节,后端传递过来的数组,尽管实体类的字段不是数组和集合类型springMVC也会自动封装成数组
4.jQuery库
插件
使用方法:
下载,引入,通过样式引入