项目二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库

插件
使用方法:
下载,引入,通过样式引入


返回课程体系

posted @ 2021-07-04 15:41  LinkYup  阅读(32)  评论(0编辑  收藏  举报