springMVC学习(七)RESTful API和拦截器

RESTful API

RESTful结构:

  • 每一个URI代表一种资源;

  • 客户端和服务器之间,传递这种资源的某种表现层;

  • 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"

非RESTful的http的url:http://localhost:8080/items/editItems.action?id=1&….

RESTful的url是简洁的:http:// localhost:8080/items/editItems/1

RESTful结构开发步骤:

  • 更改DispatcherServlet的配置,修改web.xml的url匹配模式

  <servlet-mapping>
   <servlet-name>DispatcherServlet</servlet-name>
   <url-pattern>/</url-pattern>
 </servlet-mapping>
  • 配置对静态资源的解析,当DispatcherServlet拦截/开头的所有请求,对静态资源的访问就报错,添加静态资源配置

    <!-- 静态资源 解析 -->
   <mvc:resources location="/js/" mapping="/js/**" />
   <mvc:resources location="/img/" mapping="/img/**" />

/**就表示不管有多少层,都对其进行解析,/*代表的是当前层的所有资源

  • 在Controller上使用PathVariable注解来绑定对应的参数

@PathVariable 可以将URL中占位符参数{xx}绑定到处理器类的方法形参中@PathVariable(“xx“),两个参数名必须相同

    //根据商品id查看商品信息rest接口
   //@RequestMapping中指定restful方式的url中的参数,参数需要用{}包起来
   //@PathVariable将url中的{}中的参数和形参进行绑定
   @RequestMapping("/viewItems/{id}")
   public @ResponseBody ItemsCustom viewItems(@PathVariable("id") Integer id) throws Exception{
       //调用 service查询商品信息
       ItemsCustom itemsCustom = itemsService.findItemsById(id);
       return itemsCustom;
  }

springMVC拦截器

用户请求到DispatherServlet中,DispatherServlet调用HandlerMapping查找Handler,HandlerMapping返回一个拦截链(多个拦截),springmvc中的拦截器是通过HandlerMapping发起的

开发步骤:

  • 自定义拦截器,实现 HandlerInterceptor

public class HandlerInterceptor1 implements HandlerInterceptor {
   //在执行handler之前来执行的
   //用于用户认证校验、用户权限校验
   @Override
   public boolean preHandle(HttpServletRequest request,
           HttpServletResponse response, Object handler) throws Exception {
       System.out.println("HandlerInterceptor1...preHandle");
       //如果返回false表示拦截,不继续执行handler;如果返回true表示放行
       return false;
  }
   //在执行handler返回modelAndView之前来执行
   //如果需要向页面提供一些公用 的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
   @Override
   public void postHandle(HttpServletRequest request,
           HttpServletResponse response, Object handler,
           ModelAndView modelAndView) throws Exception {
       System.out.println("HandlerInterceptor1...postHandle");
  }
   //执行handler之后执行此方法
   //作系统统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
   //实现 系统统一日志记录
   @Override
   public void afterCompletion(HttpServletRequest request,
           HttpServletResponse response, Object handler, Exception ex)
           throws Exception {
       System.out.println("HandlerInterceptor1...afterCompletion");
  }
}
  • 配置拦截器

    <!--拦截器 -->
   <mvc:interceptors>
       <!--多个拦截器,顺序执行 -->
        <mvc:interceptor>
           <mvc:mapping path="/**" />
           <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor1"/>
       </mvc:interceptor>
       <mvc:interceptor>
           <mvc:mapping path="/**" />
           <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"/>
       </mvc:interceptor>

       <mvc:interceptor>
           <!-- /**可以拦截路径不管多少层 -->
           <mvc:mapping path="/**" />
           <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"/>
       </mvc:interceptor>
   </mvc:interceptors>
  • 拦截器链是按配置的拦截器顺序执行,执行preHandle是顺序执行。执行postHandle、afterCompletion是倒序执行

  • 如果preHandle不放行,postHandle、afterCompletion都不执行。只要有一个拦截器不放行,controller不能执行完成

  • 只有前边的拦截器preHandle方法放行,下边的拦截器的preHandle才执行。

日志拦截器或异常拦截器要求

  • 将日志拦截器或异常拦截器放在拦截器链中第一个位置,且preHandle方法放行

身份认证

拦截器

public class LoginInterceptor implements HandlerInterceptor {

   //在执行handler之前来执行的
   //用于用户认证校验、用户权限校验
   @Override
   public boolean preHandle(HttpServletRequest request,
           HttpServletResponse response, Object handler) throws Exception {

       //得到请求的url
       String url = request.getRequestURI();

       //判断是否是公开 地址
       //实际开发中需要公开 地址配置在配置文件中
       //...
       if(url.indexOf("login.action")>=0){
           //如果是公开 地址则放行
           return true;
      }

       //判断用户身份在session中是否存在
       HttpSession session = request.getSession();
       String usercode = (String) session.getAttribute("usercode");
       //如果用户身份在session中存在放行
       if(usercode!=null){
           return true;
      }
       //执行到这里拦截,跳转到登陆页面,用户进行身份认证
       request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);

       //如果返回false表示拦截不继续执行handler,如果返回true表示放行
       return false;
  }
   //在执行handler返回modelAndView之前来执行
   //如果需要向页面提供一些公用 的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
   @Override
   public void postHandle(HttpServletRequest request,
           HttpServletResponse response, Object handler,
           ModelAndView modelAndView) throws Exception {
       System.out.println("HandlerInterceptor1...postHandle");

  }
   //执行handler之后执行此方法
   //作系统 统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
   //实现 系统 统一日志记录
   @Override
   public void afterCompletion(HttpServletRequest request,
           HttpServletResponse response, Object handler, Exception ex)
           throws Exception {
       System.out.println("HandlerInterceptor1...afterCompletion");
  }

}

Controller

@Controller
public class LoginController {
   //用户登陆提交方法
   @RequestMapping("/login")
   public String login(HttpSession session, String usercode,String password)throws Exception{

       //调用service校验用户账号和密码的正确性
       //..

       //如果service校验通过,将用户身份记录到session
       session.setAttribute("usercode", usercode);
       //重定向到商品查询页面
       return "redirect:/items/queryItems.action";
  }

   //用户退出
   @RequestMapping("/logout")
   public String logout(HttpSession session)throws Exception{

       //session失效
       session.invalidate();
       //重定向到商品查询页面
       return "redirect:/items/queryItems.action";
  }
}

 

 

posted @ 2020-12-20 18:12  hjy1995  阅读(212)  评论(0编辑  收藏  举报