Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework中的spring web MVC模块

spring framework中的spring web MVC模块

1.概述

    • spring web mvc是spring框架中的一个模块
    • spring web mvc实现了web的MVC架构模式,可以被用于开发web网站
    • spring web mvc 实现web网站的原理,如下图:

2.使用spring web mvc开发web应用的步骤

  step1:在自己的工程中引入spring web mvc模块

  step2:配置spring web mvc模块 中的DispatcherServlet,告诉他要拦截哪些请求

  step3:编写controller类

3.spring web mvc中相关知识点  

  3.1关于spring web mvc 中的DispatcherServlet

    • DispatcherServlet是spring web mvc 模块的核心部分,DispatcherServlet有如下功能

      • 接收用户请求,并将其分发给controller中的handling method

    • The DispatcherServlet is an actual Servlet (it inherits from the HttpServlet base class), 

    • 一个web application中可以有多个DispatcherServlet 实例,
    • 每个DispatcherServlet实例都有他自己的

      WebApplicationContext实例,The WebApplicationContext is an extension of the plain ApplicationContext that has some extra features necessary for web applications.

    • 所有的WebApplicationContext实例都继承自root WebApplicationContext实例,
    •  The root WebApplicationContext 应该包含 all the infrastructure【基础】 beans that should be shared between your other contexts and Servlet instances. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.
    • Figure 22.2. Typical context hierarchy in Spring Web MVC

    • It is also possible to have just one root context for single DispatcherServlet scenarios.
    • Figure 22.3. Single root context in Spring Web MVC

      mvc root context
    • Table 22.1. Special bean types in the WebApplicationContext

      Bean typeExplanation

      HandlerMapping

      Maps incoming requests to handlers and a list of pre- and post-processors (handler interceptors) based on some criteria the details of which vary by HandlerMapping implementation. The most popular implementation supports annotated controllers but other implementations exists as well.

      HandlerAdapter

      Helps the DispatcherServlet to invoke a handler mapped to a request regardless of the handler is actually invoked. For example, invoking an annotated controller requires resolving various annotations. Thus the main purpose of a HandlerAdapter is to shield theDispatcherServlet from such details.

      HandlerExceptionResolver

      Maps exceptions to views also allowing for more complex exception handling code.

      ViewResolver

      Resolves logical String-based view names to actual View types.

      LocaleResolver &LocaleContextResolver

      Resolves the locale a client is using and possibly their time zone, in order to be able to offer internationalized views

      ThemeResolver

      Resolves themes your web application can use, for example, to offer personalized layouts

      MultipartResolver

      Parses multi-part requests for example to support processing file uploads from HTML forms.

      FlashMapManager

      Stores and retrieves the "input" and the "output" FlashMap that can be used to pass attributes from one request to another, usually across a redirect.

    • 要想DispatcherServlet 能够拦截到用户的请求,还需要做一些相应的配置,如使用URL mapping的方式将用户请求映射到DispatcherServlet。可以有多种方法来使得用户请求被映射到DispatcherServlet上,

      • 方法一,直接继承spring MVC 模块的WebApplicationInitializer接口,来配置spring MVC模块的DispatcherServlet,使其可以接收到用户请求

        •   MyWebApplicationInitializer.java

        •       将用户请求以URL方式映射到spring web mvc模块的 DispatcherServlet 上,从而使得用户请求能够通过DispatcherServlet被转交给controller来进行处理,并得到处理结果作为响应反馈给用户

        •       下面的例子中all requests starting with /example will be handled by the DispatcherServlet instance named example.
        • /*
            1)WebApplicationInitializer is an interface provided by Spring MVC that ensures your code-based configuration is detected and automatically used to initialize any Servlet 3 container. 
          2)
          */
          public
          class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { ServletRegistration.Dynamic registration = container.addServlet("example", new DispatcherServlet()); registration.setLoadOnStartup(1); registration.addMapping("/example/*"); } }

          使用上述方法(即Java代码的方法)配置URL映射,将用户请求交给DispatcherServlet来分发给对应的Controller,这与传统情况下使用web.xml文件配置相应映射的效果是一样的,如本例中上述代码的效果和下面的web.xml的配置代码是等价的(传统模式下使用web.xml配置用户请求URL,使得用户请求能够被Servlet拦截(如被spring web mvc的DispatcherServlet拦截))

      • 方法二:传统模式下使用web.xml将用户请求URL映射待DispatcherServlet上
        • 传统模式下在web.xml中配置请求URL和servlet的映射关系,如下所示:
        • <!--上面的Java代码和传统模式下web.xml文件下这一段代码是等效的  都是将用户请求/example/*交给web应用的servlet(例子中指的是spring web mvc中的DispatcherServlet)去处理   让servlet把接收到的用户请求交给controller层相应的handling method去处理-->

          <
          web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>example</servlet-name> <url-pattern>/example/*</url-pattern> </servlet-mapping> </web-app>
        • You can customize individual DispatcherServlet instances by adding Servlet initialization parameters ( init-param elements) to the Servlet declaration in theweb.xml file. See the following table for the list of supported parameters.
          ParameterExplanation

          contextClass

          Class that implements WebApplicationContext, which instantiates the context used by this Servlet. By default, theXmlWebApplicationContext is used.

          contextConfigLocation

          String that is passed to the context instance (specified by contextClass) to indicate where context(s) can be found. The string consists potentially of multiple strings (using a comma as a delimiter) to support multiple contexts. In case of multiple context locations with beans that are defined twice, the latest location takes precedence.

          namespace

          Namespace of the WebApplicationContext. Defaults to [servlet-name]-servlet.

      • 方法三,实现WebApplicationInitializer接口
      • import org.springframework.web.WebApplicationInitializer;
        
        public class MyWebApplicationInitializer implements WebApplicationInitializer {
        
            @Override
            public void onStartup(ServletContext container) {
                XmlWebApplicationContext appContext = new XmlWebApplicationContext();
                appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        
                ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
                registration.setLoadOnStartup(1);
                registration.addMapping("/");
            }
        
        }
      • (推荐使用本方法)方法四,继承AbstractAnnotationConfigDispatcherServletInitializer类(方法三中所提及的WebApplicationInitializer接口的实现类)

        • example1,使用Java-based Spring configuration:

          public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
          
              @Override
              protected Class<?>[] getRootConfigClasses() {
                  return null;
              }
          
              @Override
              protected Class<?>[] getServletConfigClasses() {
                  return new Class[] { MyWebConfig.class };
              }
          
              @Override
              protected String[] getServletMappings() {
                  return new String[] { "/" };
              }
          
          }
        • example2,If using XML-based Spring configuration, you should extend directly from AbstractDispatcherServletInitializer:

          public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
          
              @Override
              protected WebApplicationContext createRootApplicationContext() {
                  return null;
              }
          
              @Override
              protected WebApplicationContext createServletApplicationContext() {
                  XmlWebApplicationContext cxt = new XmlWebApplicationContext();
                  cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
                  return cxt;
              }
          
              @Override
              protected String[] getServletMappings() {
                  return new String[] { "/" };
              }
          
          }

          AbstractDispatcherServletInitializer also provides a convenient way to add Filter instances and have them automatically mapped to theDispatcherServlet:

          public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {
          
              // ...
          
              @Override
              protected Filter[] getServletFilters() {
                  return new Filter[] { new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
              }
          
          }

  3.2 Implementing Controllers 

  方法一:annotion-based Controller

        概述:使用 @RequestMapping@RequestParam,@ModelAttribute,等注解可以定义一个类为controller类,使得该类可以处理用户的请求。

        编程思路:

        • step1,要想spring能够识别上述注解,必须要先在配置文件中开启上述注解的识别方式
            • <?xml version="1.0" encoding="UTF-8"?>
              <beans xmlns="http://www.springframework.org/schema/beans"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:p="http://www.springframework.org/schema/p"
                  xmlns:context="http://www.springframework.org/schema/context"
                  xsi:schemaLocation="
                      http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/context
                      http://www.springframework.org/schema/context/spring-context.xsd">
              
                  <context:component-scan base-package="org.springframework.samples.petclinic.web"/>
              
                  <!-- ... -->
              
              </beans>
        • step2,The @Controller annotation indicates that a particular class serves the role of a controller
            • The ServletDispatcher scans such annotated classes for mapped methods and detects @RequestMapping annotations (see the next section).
        • step3,  

          @GetMapping
          @PostMapping
          @PutMapping
          @DeleteMapping
          @PatchMapping

        • 例如,
          @Controller
          public class HelloWorldController {
          
              @RequestMapping("/helloWorld")
              public String helloWorld(Model model) {
                  model.addAttribute("message", "Hello World!");
                  return "helloWorld";
              }
          }
          @Controller
          @RequestMapping("/appointments")
          public class AppointmentsController {
          
              private final AppointmentBook appointmentBook;
          
              @Autowired
              public AppointmentsController(AppointmentBook appointmentBook) {
                  this.appointmentBook = appointmentBook;
              }
          
              @RequestMapping(method = RequestMethod.GET)
              public Map<String, Appointment> get() {
                  return appointmentBook.getAppointmentsForToday();
              }
          
              @RequestMapping(path = "/{day}", method = RequestMethod.GET)
              public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
                  return appointmentBook.getAppointmentsForDay(day);
              }
          
              @RequestMapping(path = "/new", method = RequestMethod.GET)
              public AppointmentForm getNewForm() {
                  return new AppointmentForm();
              }
          
              @RequestMapping(method = RequestMethod.POST)
              public String add(@Valid AppointmentForm appointment, BindingResult result) {
                  if (result.hasErrors()) {
                      return "appointments/new";
                  }
                  appointmentBook.addAppointment(appointment);
                  return "redirect:/appointments";
              }
          }

          上面的例子和下面的例子等价:

          @Controller
          @RequestMapping("/appointments")
          public class AppointmentsController {
          
              private final AppointmentBook appointmentBook;
          
              @Autowired
              public AppointmentsController(AppointmentBook appointmentBook) {
                  this.appointmentBook = appointmentBook;
              }
          
              @GetMapping
              public Map<String, Appointment> get() {
                  return appointmentBook.getAppointmentsForToday();
              }
          
              @GetMapping("/{day}")
              public Map<String, Appointment> getForDay(@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
                  return appointmentBook.getAppointmentsForDay(day);
              }
          
              @GetMapping("/new")
              public AppointmentForm getNewForm() {
                  return new AppointmentForm();
              }
          
              @PostMapping
              public String add(@Valid AppointmentForm appointment, BindingResult result) {
                  if (result.hasErrors()) {
                      return "appointments/new";
                  }
                  appointmentBook.addAppointment(appointment);
                  return "redirect:/appointments";
              }
          }

          In the above example, @RequestMapping is used in a number of places. The first usage is on the type (class) level, which indicates that all handler methods in this controller are relative to the /appointments path. The get() method has a further @RequestMapping refinement: it only accepts GET requests, meaning that an HTTPGET for /appointments invokes this method. The add() has a similar refinement, and the getNewForm() combines the definition of HTTP method and path into one, so that GET requests for appointments/new are handled by that method.

          The getForDay() method shows another usage of @RequestMapping: URI templates. (See the section called “URI Template Patterns”).

          @RequestMapping on the class level is not required. Without it, all paths are simply absolute, and not relative. The following example from the PetClinic sample application shows a multi-action controller using @RequestMapping:

          @Controller
          public class ClinicController {
          
              private final Clinic clinic;
          
              @Autowired
              public ClinicController(Clinic clinic) {
                  this.clinic = clinic;
              }
          
              @RequestMapping("/")
              public void welcomeHandler() {
              }
          
              @RequestMapping("/vets")
              public ModelMap vetsHandler() {
                  return new ModelMap(this.clinic.getVets());
              }
          
          }

        实际使用实例:

        • spring-projects Org on Github,网站上有一些使用注解方式开发的controllers实例,包括MvcShowcaseMvcAjaxMvcBasicPetClinicPetCare, and others.                

  

     

学习的过程中总会得到一些心得体会,认真地将它们记录下来并分享给每一个愿意花费时间去阅读它们的人,然后意外地收获某个读者的评论,从而激发出新的感想,是一件十分令人欢快的事。如果你也在研习这方面的知识,欢迎加入到我们的队伍中来,和我们一起进步吧(^_^)
原文地址:https://www.cnblogs.com/lxrm/p/6253736.html