SpringMVC第七篇【RESTful支持、拦截器】

RESTful支持

咱们在学习webservice的时候可能就听过RESTful这么一个名词,当时候与SOAP进行对比的…那么RESTful到底是什么东东呢???css

RESTful(Representational State Transfer)软件开发理念,RESTful对http进行很是好的诠释java

若是一个架构支持RESTful,那么就称它为RESTful架构…web

如下的文章供咱们了解:spring

http://www.ruanyifeng.com/blog/2011/09/restful服务器

综合上面的解释,咱们总结一下什么是RESTful架构:restful

  •   (1)每个URI表明一种资源;
  •   (2)客户端和服务器之间,传递这种资源的某种表现层;
  •   (3)客户端经过四个HTTP动词,对服务器端资源进行操做,实现”表现层状态转化”

其实通常的架构并不能彻底支持RESTful的,所以,只要咱们的系统支持RESTful的某些功能,咱们通常就称做为支持RESTful架构markdown

url的RESTful实现

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

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

更改DispatcherServlet的配置

从上面咱们能够发现,url并无.action后缀的,所以咱们要修改核心分配器的配置mvc

<!-- restful的配置 -->
    <servlet>
        <servlet-name>springmvc_rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 加载springmvc配置 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 配置文件的地址 若是不配置contextConfigLocation, 默认查找的配置文件名称classpath下的:servlet名称+"-serlvet.xml"即:springmvc-serlvet.xml -->
            <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>

    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc_rest</servlet-name>
        <!-- rest方式配置为/ -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

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

//根据商品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;

    }

当DispatcherServlet拦截/开头的全部请求,对静态资源的访问就报错:咱们须要配置对静态资源的解析

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

/**就表示无论有多少层,都对其进行解析,/*表明的是当前层的全部资源..


SpringMVC拦截器

在Struts2中拦截器就是咱们当时的核心,原来在SpringMVC中也是有拦截器的

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

实现拦截器的接口:

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"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> -->

        <mvc:interceptor>
            <!-- /**能够拦截路径无论多少层 -->
            <mvc:mapping path="/**" />
            <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

测试执行顺序

若是两个拦截器都放行

测试结果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion

总结:
执行preHandle是顺序执行。
执行postHandle、afterCompletion是倒序执行

1 号放行和2号不放行

测试结果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion

总结:
若是preHandle不放行,postHandle、afterCompletion都不执行。
只要有一个拦截器不放行,controller不能执行完成

1 号不放行和2号不放行

测试结果:
HandlerInterceptor1...preHandle
总结:
只有前边的拦截器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";

    }


}
相关文章
相关标签/搜索