SpringMVC笔记

前言:一年前看视频学习这个框架的时候做的笔记。。。现在自己看来觉得还是有点蛋疼。。。想了想还是放上来了,万一开发要看呢,求勿喷。。。

springmvc

  • 执行流程的过程图:
SpringMVC笔记_第1张图片
基本流程
  • 具体执行流程(这个就是现在自己手写的啦):

1.用户提交请求。
2.DispatchServlet接收到请求,将请求交给 HandlerMapping处理,而HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象。
3.DispatchSerlvet调用HandlerAdapter来调用Handler(Controller),HandlerAdapter将会把处理器包装为适配器,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名)
4.DispatchServlet调用ViewResolver,ViewResolver将把逻辑视图名解析为具体的View。
5.将Model的数据渲染到View上。
6.将View返回到用户。

  • 基本配置(xml版):
    • 先导入jar包,如下:
      commons-logging.jar
      org.springframework.asm-3.0.5.RELEASE.jar
      org.springframework.beans-3.0.5.RELEASE.jar
      org.springframework.context-3.0.5.RELEASE.jar
      org.springframework.core-3.0.5.RELEASE.jar
      org.springframework.expression-3.0.5.RELEASE.jar
      org.springframework.web.servlet-3.0.5.RELEASE.jar
      org.springframework.web-3.0.5.RELEASE.jar

    • 在web.xml中配置核心过滤器:

      DispatcherServlet
      org.springframework.web.servlet.DispatcherServlet


      DispatcherServlet
      // 确保了只有action后缀名的请求才可以提交到后台
      *.action

    • 开发action(实现controller接口):

      public class HelloAction implements Controller{
      // 构造函数,下文有惊喜
      public HelloAction() {
      System.out.println("HelloAction():"+this.hashCode());
      }
      @Override
      public ModelAndView handleRequest(HttpServletRequest request,
      HttpServletResponse response) throws Exception {
      // ModelAndView表示封装的Model数据和View视图
      System.out.println("handleRequest()");
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.addObject("message", "this is my first springmvc app");
      // 没配置逻辑视图的要配置文件路径
      // 如:modelAndView.setViewName("./jsp/success.jsp");
      modelAndView.setViewName("success");
      return modelAndView;
      }
      }

    • 在配置xml中配置映射(要注意的是,上面的配置核心过滤器步骤,没有指定配置文件,所以默认叫做DispatcherServlet-servlet.xml,而且是放在WEB-INF目录下):

    • 自定义配置文件路径:


      DispatcherServlet
      org.springframework.web.servlet.DispatcherServlet

      contextConfigLocation
      classpath:springmvc.xml


    • 配置逻辑视图(直接返回页面的名字),需要在springmvc.xml(我的配置叫这个名字而已)那里配置:

      class="org.springframework.web.servlet.view.InternalResourceViewResolver">



      结果
SpringMVC笔记_第2张图片
访问了两次,HelloAction的构造函数只执行一次,可以看到构造函数下面一行红字上写着,XXXSingletons,证明Controller是单例的。而且创建这个单例的时间,还是在HandlerMapping工作之前的(同样可以看红字看出来,Mapped URL XXXX)
  • 注解版:
    • 直接加注解,无需在springmvc.xml那里配置action,只需要配置好扫描的包就可以直接使用,贼他妈迅速。
      代码:
      @Controller
      @RequestMapping(value="/json")
      public class JsonAction

      @Controller的意思是把类声明为controller。@RequestMapping是请求的控制,比如value就是控制namespace(映射路径),还有method之类的参数。

    • 扫描配置:



      这个的前提:
      xmlns:context="http://www.springframework.org/schema/context"
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
      在xml那里配置声明,不然用不了context标签

收集参数(不分版本):

  • 收集参数并封装为对象

    @RequestMapping(value="/register",method=RequestMethod.POST)
    public String register(Model model, User user){
    System.out.println(user.getUsername()+":"+user.getPassword()+
    ":"+user.getJoinDate().toLocaleString());
    model.addAttribute("message", "注册成功");
    model.addAttribute("user", user);
    return "success";
    }

    直接在函数的参数列表里面写上就好了,参数名字与提交的值的名字必须对应,例子中的user是直接将参数封装成User对象,注意参数的名字在user类里面必须有setter方法
    参数里面里面有个model,这个就是可以操作request域数据的对象
    ![可以直接收集提交的数据,也可以收集URL中的数据,后者需要在value上用{}标注关键词名字,在参数列表中使用@PathVariable收集到该参数

  • 收集多类型参数:

    • list:

      在表单那里:

      // action中的方法
      public String getArray(Model model, Bean bean){
      // 在代码中直接获取list或者数组就可以了
      List userList = bean.getUserList();
      }
      // Bean对象
      public class Bean {
      private List userList;
      public List getUserList() {
      return userList;
      }
      public void setUserList(List userList) {
      this.userList = userList;
      }
      }

      其实这个和收集并封装成user是一样的,因为封装user的时候是用表单中提交的值来完成user的实例化操作,其中表单的name和user的属性名是一致的。
      而封装list的话,表单名字中的userList[0]正好作为bean里面的setList(List userList)的参数,也就是用userList来完成实例化操作。

    • 数组:
      // 表单
      1
      sivan
      2

      tom
      // action 方法
      @RequestMapping(value="/getArray")
      public String getArray(Model model, String[] ids){
      System.out.print("被选中的序号是:");
      for (String string : ids) {
      System.out.print(string+" ");
      }
      model.addAttribute("message", "xuanzhong成功");
      return "success";
      }

返回Json数据

SpringMVC笔记_第3张图片
示例
  • 首先需要导包
    jackson-core-asl-1.9.11.jar
    jackson-mapper-asl-1.9.11.jar
  • 然后在action函数返回值那里加一个类型标签@ResponseBody,返回值直接返回某个对象,不返回字符串

    @RequestMapping(value="/map2json")
    public @ResponseBody Map map2Json(){
    Map userMap = new HashMap<>();
    for(int i = 0;i<4;i++){
    User user = new User();
    user.setId(i);
    user.setJoinDate(new Date());
    user.setUsername("Liming");
    user.setAge(i*6-i+3);
    userMap.put(i+"", user);
    }
    return userMap;
    }
  • 最后在springmvc.xml配置下适配器(不然会报找不到适配器的错误):
    class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">





springmvc拦截器

  • 创建拦截器,实现HandlerInterceptor接口(也可以实现WebRequestInterceptor接口):
    public class FirstInterceptor implements HandlerInterceptor{
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
    throws Exception {
    System.out.println("执行afterCompletion方法");
    }
    // modelAndView参数:可以控制需要显示的视图
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView modelAndView)
    throws Exception {
    System.out.println("执行postHandle方法");
    }
    /* 返回值:表示我们是否需要将当前的请求拦截下来
    false: 请求被中止
    true: 请求继续
    obj参数:表示的当前被拦截的请求目标(请求对应的类,比如说user2json请求,即obj是UserAction类)
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
    System.out.println("执行preHandle方法");
    return true;
    }
    }
    jieguo :
    FirstInterceptor执行preHandle方法
    FirstInterceptor执行postHandle方法
    FirstInterceptor执行afterCompletion方法

    其中,preHandle方法是在请求被处理之前执行,postHandle在请求被处理之后执行,afterCompletion方法是在请求结束之后执行
  • 在springmvc的配置文件中注册拦截器:









  • 当有多个拦截器一起工作的时候,工作流程如图:

    SpringMVC笔记_第4张图片
    先按照拦截器的配置顺序执行拦截器的preHandle方法,然后执行业务方法,然后按拦截器配置顺序的倒序来执行拦截器的postHandle方法,执行完所有拦截器的postHandle方法在,再按倒序执行afterCompletion方法(个人猜测是责任链模式。。)
















    结果:
    FirstInterceptor执行preHandle方法
    SecondInterceptor执行preHandle方法
    1 Liming 注册于 :26 Mon Mar 13 17:59:40 CST 2017
    SecondInterceptor执行postHandle方法
    FirstInterceptor执行postHandle方法
    SecondInterceptor执行afterCompletion方法
    FirstInterceptor执行afterCompletion方法

  • 拦截起使用场景:解决业务共性问题

比如:
1)字符编码例如request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");(假设没配置字符串过滤器,)
2)权限校验(request.getSession().getAttribute("user")!=null等)
方法和struts2都是一样的,通过request或者response加以控制来实现。

  • 提一下过滤器
    配置字符过滤器:

    encoding
    org.springframework.web.filter.CharacterEncodingFilter

    encoding
    utf8



    encoding
    *
  • 拦截器与过滤器区别:
    ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
    ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
    ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
    ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
    ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
    ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑

你可能感兴趣的:(SpringMVC笔记)