SpringMVC

一、工作原理

核心控制器为DispatcherServlet

1. 客户端的所有请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其他模块来真正处理用户的请求。

2.DispatcherServlet收到请求后,将根据请求的信息(包括URL、HTTP协议方法、请求头、请求参数、Cookie等)以及HandlerMapping的配置找到处理该请求的Handler(任何一个对象都可以作为请求的Handler)。当然,在这个地方Spring会通过HandlerAdapter对该处理器进行封装,HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用。

3. Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,

ModelAndView顾名思义,包含了数据模型以及相应的视图的信息。当然,这里的视图是逻辑视图,DispatcherServlet还要借助ViewResolver完成从逻辑视图到真实视图对象的解析工作。

4. 当得到真正的视图对象后,Dispatcher会利用视图对象对模型数据进行渲染。

5. 客户端得到响应,可能是一个普通的HTML页面,也可以是XML或JSON字符串,还可以是一张图片或者一个PDF文件。

二、核心类与接口

1、DispatcherServlet   -- 前置控制器

2、HandlerMapping接口 -- 处理请求的映射

HandlerMapping接口的实现类:

SimpleUrlHandlerMapping  通过配置文件,把一个URL映射到Controller

DefaultAnnotationHandlerMapping  通过注解,把一个URL映射到Controller类上

3、HandlerAdapter接口 -- 处理请求的映射

AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

4、Controller接口 -- 控制器

由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,

所以我们并没有用到这个接口。

5、HandlerInterceptor 接口--拦截器

我们自己实现这个接口,来完成拦截的器的工作。

6、ViewResolver接口的实现类

UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理

InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

7、View接口

JstlView类

8、HandlerExceptionResolver接口 --异常处理

SimpleMappingExceptionResolver实现类

9、ModelAndView类

三、DispatcherServlet配置说明

DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet

<servlet>  

    <servlet-name>springMVC</servlet-name>  

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  

    <init-param>  

        <param-name>contextConfigLocation</param-name>  

        <param-value>classpath*:/springMVC.xml</param-value>  

    </init-param>  

    <load-on-startup>1</load-on-startup>  

</servlet>  

<servlet-mapping>  

    <servlet-name>springMVC</servlet-name>  

    <url-pattern>/</url-pattern>  

</servlet-mapping>  

1、<init-param> 指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。

2、<load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servletp容器一起启动。

3、 <url-pattern>/</url-pattern> 会拦截请求。

①拦截*.do、*.htm, 例如:/user/add.do

这是最传统的方式,最简单也最实用。不会导致静态文件(jpg,js,css)被拦截。

②拦截/,例如:/user/add

可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。

弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。想实现REST风格,事情就是麻烦一些。后面有解决办法还算简单。

四、SpringMVC配置说明

1、自动扫描

2、加载资源文件

3、默认的注释驱动

4、视图解析器

5、拦截器

6、配置全局异常处理器

7、配置静态资源映射

1、<context:component-scanbase-package="com.yuhui" />

2、<context:property-placeholderlocation="classpath:db.properties"/>

3、<mvc:annotation-driven />

4、<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  

        <property name="prefix" value="/WEB-INF/jsp/"/>  

        <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->  

        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> 

</bean> 

5、<mvc:interceptors>

        <beanclass="com.yuhui.interceptor.MyInterceptor"></bean> <!-- 拦截所有springmvc的url! -->

        <mvc:interceptor>

            <mvc:mappingpath="/user.do" />

            <!-- <mvc:mappingpath="/test/*" /> -->

            <beanclass="com.yuhui.interceptor.MyInterceptor2"></bean>

        </mvc:interceptor>

    </mvc:interceptors> 

6、<bean class="com.yuhui.GlobalExceptionResolver"></bean>

7、<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>  

<mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>  

<mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/>

<context:component-scan/> 扫描指定的包中的类上的注解,常用的注解有:

@Controller 声明Action组件
@Service    声明Service组件    @Service("myMovieLister") 
@Repository 声明Dao组件
@Component   泛指组件, 当不好归类时. 
@RequestMapping("/menu")  请求映射
@Resource  用于注入,( j2ee提供的) 默认按名称装配,@Resource(name="beanName") 
@Autowired 用于注入,(srping提供的) 默认按类型装配 
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype")   设定bean的作用域

@RequestParam 请求参数

<mvc:annotation-driven/> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。
并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。

<mvc:interceptors/>是一种简写形式。通过看前面的大图,知道,我们可以配置多个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也可以手动配置为每个HandlerMapping注入一个拦截器。

<mvc:resourcesmapping="/images/**" location="/images/"cache-period="31556926"/> 匹配URL  /images/**  的URL被当做静态资源,由Spring读出到内存中再响应http。

五、拦截器和全局异常处理

拦截器:

1、实现HandlerInterceptor接口

2、三个方法

perHandle:Action之前执行,可进行编码、安全控制等处理

postHandler:生成视图之前执行,有机会修改ModelAndView

afterCompletion:最后执行,可用于释放资源,可以根据ex是否为null判断是否发生了异常,进行日志记录

参数中的Object handler是下一个拦截器

3、配置拦截器

全局异常处理:

1、实现HandlerExceptionResolver接口

2、在方法resolveException中定义异常处理(打印异常、日志文件、发邮件、发短信、展示错误页面)

3、配置全局异常处理器

六、父子上下文

使用了listener监听器来加载配置,Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器),保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

DispatcherServlet是一个Servlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。它也保存在 ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是DispatcherServlet.class.getName()+ ".CONTEXT"。

可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);

说明 :Spring 并没有限制我们,必须使用父子上下文。我们可以自己决定如何使用。

方案一,传统型:

父上下文容器中保存数据源、服务层、DAO层、事务的Bean。

子上下文容器中保存Mvc相关的Action的Bean.

事务控制在服务层。

由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。

当然,做为“传统型”方案,也没有必要这要做。

方案二,激进型:

不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,事情就简单了。

Java--大项目能做好--按传统方式做,规规矩矩的做,好扩展,好维护。

Java--小项目能做快--按激进方式做,一周时间就可以出一个版本,先上线接受市场(用户)的反馈,再改进,再反馈,时间就是生命(成本)。

七、ajax、转发与重定向

Ajax:

1、使用Jackson包

2、<mvc:annotation-driven />支持JSon

3、使用@ResponseBody注解绑定

转发与重定向:

可以通过redirect/forward:url方式转到另一个Action进行连续的处理。

可以通过redirect:url 防止表单重复提交 。

写法如下:

return "forward:/order/add";

return "redirect:/index.jsp";

带参数重定向—RedirectAttributes

redirectAttributes.addFlashAttribute("message", "操作成功");  

 return "redirect:/account/group/";  


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值