springmvc学习笔记1

springmvc是基于Model2实现的技术框架。
这里写图片描述
springmvc的整个流程大致如下:

  1. 客户端发起一个请求,web应用服务器接收这个请求,如果匹配DispatcherServlet的请求映射路径,则将请求转交给DispatcherServlet处理。
  2. DispatcherServlet接收到这个请求后,将根据请求信息及HandlerMapping的配置找到处理请求的处理器Handler。
  3. 得到Handler后,通过HandlerAdapter对Handler进行封装,再以统一的适配器接口调用Handler。
  4. 处理器完成业务逻辑的处理后返回一个ModelAndView给DispatcherServlet。
  5. DispatcherServlet借由ViewResolver完成逻辑视图名到真实试图对象的解析工作。
  6. 得到真实的逻辑视图对象之后,DispatcherServlet使用这个View对象对ModelAndView中的模型数据进行视图渲染。
  7. 最终客户端得到的响应消息可能是一个普通的HTML页面,也可能是一个XML,JSON串或者其他的媒体形式。

注意点

  • Web层spring容器作为业务层spring容器的子容器,web层容器可以访问业务层容器的bean,但反过来不可以。
  • 一个web.xml可以配置多个DispatcherServlet,通过<servlet-mapping>配置,让每个DispatcherServlet处理不同的请求。

DispatcherServlet的属性

  • namespace:命名空间。默认为<servlet-name>-servlet,用于构造spring配置文件的路径。显示指定该属性后,对应的路径为WEB-INF/namespace.xml。
  • contextConfigLocation:配置文件的路径。可以指定多个。
  • publishContext:默认为true.表示将WebApplicationContext发布到ServletContext的属性列表中。以便调用者可以通过ServletContext找到WebApplicationContext实例。对用 的属性名为DispatcherServlet#getServletContextAttributeName()方法的返回值。
  • publishEvents:布尔型的属性。当DispatcherServlet处理完一个请求后,是否需要向容器发布一个ServletRequestHandlerEvent事件。默认为true.

servlet3.0环境编程方式配置

WebApplicationInitializer是一个接口,只有一个方法:

void onStartup(ServletContext servletContext) throws ServletException;

可以实现它来配置:

public class MyApplicationInitializer implements WebApplicationInitializer{

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        ServletRegistration.Dynamic registration = 
                servletContext.addServlet("dispatcher", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("*.hmtl");

    }

}

原理:在Servlet3.0环境下,容器会在类路径下查找实现了javax.servelt.ServeltContainerInitializer接口的类。如果能发现就用它来配置Servlet容器。

Spring提供了这个接口的实现,即SpringServletContainerInitializer.而这个类又会去查找实现WebApplicationInitializer的类并将配置的任务交给他们来完成。 Spring3.2引入了一个WebApplicationInitializer的基础实现。也就是AbstractAnnotationConfigDispatcherServletInitializer。
可以继承它来配置:

public class SpittAppWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{RootConfig.class};
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{WebConfig.class};
    }
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

DispatcherServlet的initStrategies方法

spring如何将spring MVC组件装配到DispatcherServlet中呢?看以下方法:

protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

这个方法将在WebApplicationContext 初始化后自动执行,此时Spring上下文的Bean已经初始化完毕。该方法的工作原理是:通过反射机制查找并装配Spring容器中用户显示定义的组件Bean,如果找不到就装配默认的组件实例。

在org.springframework.web.servlet类路径下,有个DispatcherServlet.properties文件。那里定义了默认的组件。有些组件最多只允许存在一个实例。有些则允许存在多个。这些组件都实现了Ordered接口,通过order属性确定优先级顺序。

HttpMessageConverter

HttpMessageConverter是一个消息转换器接口。他有如下方法:

boolean canRead(Class<?> clazz, MediaType mediaType);  
boolean canWrite(Class<?> clazz, MediaType mediaType); 
List<MediaType> getSupportedMediaTypes(); 
 T read(Class<? extends T> clazz, HttpInputMessage inputMessage)  throws IOException, HttpMessageNotReadableException;  
 void write(T t, MediaType contentType, HttpOutputMessage outputMessage)  throws IOException, HttpMessageNotWritableException; 

spring有很多HttpMessageConverter实现类。RequestMappingHandlerAdapter默认装配了:

  • StringHttpMessageConverter
  • ByteArrayHttpMessageConverter
  • SourceHttpMessageConverter
  • AllEncompassingFormHttpMessageConverter

如果要装配其他类型的HttpMessageConverter,可在spring的web容器上下文中定义一个RequestMappingHandlerAdapter。

  <bean
            class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"
            p:messageConverters-ref="messageConverters">
    </bean>


    <util:list id="messageConverters">
        <bean
                class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
        <bean
                class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter" />

        <bean
                class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
        <bean
                class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"
                p:marshaller-ref="xmlMarshaller" p:unmarshaller-ref="xmlMarshaller">
        </bean>
        <bean
                class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
    </util:list>
  <bean id="xmlMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
        <property name="streamDriver">
            <bean class="com.thoughtworks.xstream.io.xml.StaxDriver"/>
        </property>
        <property name="annotatedClasses">
            <list>
                <value>com.smart.domain.User</value>
            </list>
        </property>
    </bean>

如何使用HttpMessageConverter将请求信息转换并绑定到处理方法的入参中?spring mvc提供了两种方法:

  • 使用@ResponseBody,@RequestBody对处理方法进行标注
  • 使用HttpEntity<T>,ResponseEntity<T>作为处理方法的入参或返回值。

@ModelAttribute

他可以标注在方法入参。表示把入参对象添加到模型中,即request.setAttribute方法。也可以放在方法定义之上。表示:springmvc在调用目标处理方法之前,会逐个调用在方法级上标注了@ModelAttribute注解的方法,并将这些方法的返回值添加到模型中。再调用目标处理方法。

springmvc在调用方法前会创建一个隐含的模型对象,作为模型数据的储存容器。如果处理方法的入参为Map或Model对象,则会将隐含模型的引用传递给这些入参。

@SessionAttributes

如果希望在多个请求之间共用某个模型属性数据,可以在控制器中标注一个@SessionAttributes,springmvc会将对应的属性暂存在HttpSession中。

springmvc处理@SessionAttributes和@ModelAttribute的流程:
1. springmvc在调用处理方法前,在请求线程中自动创建一个隐含的模型对象。
2. 调用所有标注了@ModelAttribute的方法,并将方法返回值添加到隐含模型中。
3. 查看Session中是否存在@SessionAttributes(“xx”)所指定的xx属性,如果有,则将其添加到隐含模型中。
4. 对标注了@ModelAttribute处理方法的入参按如下流程处理:
4.1:如果隐含模型中拥有名为xx的属性,则将其赋给入参。再用请求消息填充该入参对象直接返回。否则转到4.2.
4.2:如果xx是会话属性,则尝试从会话中获取该属性,并将其赋给入参,如果会话中找不到对应的属性,则抛出异常。否则转到4.3
4.3:如果隐含模型不存在xx属性,且xx也不是会话属性,则创建入参实例,然后再填充。

所以对@SessionAttributes要小心。

数据绑定

这里写图片描述

springmvc将servletRequest对象及处理方法的入参对象实例传递给DataBinder,DataBinder首先调用ConversionService组件进行数据类型转换,数据格式化等工作。将servletRequest中的消息填充到入参对象中,然后调用validation组件对入参对象进行数据合法性校验。最终生成数据绑定结果BindingResult对象。BindingResult包含已经完成数据绑定的入参对象和相应的校验错误对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值