看过之前的springMVC初体验,相信你对springMVC有了一定的认识。今天我们继续来学习springMVC相关的核心知识,springMVC执行流程,掌握web框架的正确学习办法,帮助你快速起飞,完成蜕变。
猿蜕变同样是一个原创系列文章,帮助你从一个普通的小白,开始掌握一些行业内通用的框架技术知识以及锻炼你对系统设计能力的提升,完成属于你的蜕变,更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取!
在这章节之前,我们已经编写了第一个SpringMVC的程序—HelloSpringWebMVC,也对它做了简单的流程分析,实际上SpringMVC还有其他的执行流程,下面这幅图,就是springMVC的执行流程图:
0.在应用启动时,我们配置的前端控制器DispatcherServlet加载spring MVC相关的配置文件,完成应用的初始化工作,这个事情只会在应用启动时做一次,。
1.用户发起请求http://127.0.0.1/helloWebMvc.do,所有满足DispatcherServlet 的URL规则的请求,都会被匹配转发到DispatcherServlet。
2.DispatcherServlet将Url交由处理器映射器(HandlerMapping)处理。
3. 处理器映射器(HandlerMapping)会返回一个执行链(这个请求需要执行哪些步骤,包括公共部分和我们自己编写的Controller)给DispatcherServlet。
4. DispatcherServlet根据之前返回的执行链,再次请求处理适配器(HandlerAdper)。
5. 处理适配器(HandlerAdper)将执行链交由相匹配的处理器(Handler)执行。
6. 处理器(Handler)执行具体的处理流程并且返回ModelAndView对象
7. 处理适配器(HandlerAdper)将处理器(Handler)返回的ModelAndView对象返回给前端控制器DispatcherServlet。
8. 前端控制器DispatcherServlet请求视图解析器(ViewResolver)查找对应的视图。
9. 视图解析器(ViewResolver)将对应的视图对象(View)返回给前端控制器DispatcherServlet
10.前端控制器将视图对象(View)转发给对应的视图组件。视图组件(比如jsp、velocity等等具体的视图组件)完成渲染工作,将渲染结果(很多时候是HTML文档)返回给前端控制器DispatcherServlet。
11. 前端控制器DispatcherServlet将最后的结果返回给用户(浏览器)。
配置url-pattern为*.do,这个是最常用的方式,其实你要是配置为*.xxx都是可以的,只要url能匹配,没什么问题,程序可以执行,但是,很多时候可能习惯成自然,大家都这么干,你也就必须这么干,因为在中国大家是最厉害的群体,不敢轻易得罪,得罪了容易没饭吃啦。
如果将url-pattern配置为/*,那么所有的请求都会到达DispatcherServlet,如果你直接请求一个jsp页面,也会被当作是一个Controller去处理,而DispatcherServlet找不到你请求的jsp页面(因为它会认为你请求的是一个Controller),就会造成404错误。所以在实际的开发过程中,最好不要去做/*的配置
如果将url-pattern配置为/,那么应用中涉及的静态资源:比如html页面、css文件、js文件、图片等等,都会交由DispatcherServlet处理。这种配置方式不会拦截.jsp文件和.jspx文件,因为这个在tomcat中的conf目录里面的web.xml文件中已经做了相关配置处理,这些请求会交给org.apache.jasper.servlet.JspServlet去处理,能够正常的访问到jsp页面。
解决静态资源不能访问的问题,解决方式有三种:
使用defaultServlet:
在tomcat中的conf/web.xml中配置,增加一个DefaultServlet的配置,当某个请求系统找不到由谁去处理时,就会让DefaultServlet去处理。我们可以DefaultServlet去处理静态资源,如果你要配置在应用中配置也是可以的,只是由一个要求:必须配置在DispatcherServlet之前:
default
*.jpg
default
*.js
default
*.css
使用mvc:default-servlet-handler:
在Spring MVC的配置文件中(spring-servlet.xml)增加配置即可,这种方式会将所有的请求交由对应的servlet进行处理,当然,最终也是由DefaultServlet来处理:
使用mvc:resources:
SpringMVC提供了mvc:resources标签来专门解决解决静态资源无法访问的问题,只需要在Spring MVC的配置文件中(spring-servlet.xml)增加以下配置即可,这样这些静态资源会交给Spring MVC提供的ResourceHttpRequestHandler进行处理:
mapping表示对静态资源url请求的要求。需要特别注意的是,/后是两个星号**。
location表示静态资源存放的目录,这个路径是一个相对路径,相对于应用的webapp目录的一个路径,要求资源位于webapp目录下,我们配置成了/ static /,所以我们可以在应用的webapp目录下创建一个static文件夹,然以后将所有的静态资源放进去,一般来说我们对静态文件需要做下分类,所以会在static目录下再建立子目录:css,js,images,分别存放css文件,js文件,和图片。推荐使用该配置。
我们之前编写Spring MVC 程序,需要在spring-servlet.xml中配置我们的Controller,比如:
随着我们需要开发的功能增加,我们会编写更多的Controller,这样一来,每增加一个Controller,我们就需要增加一行类似的配置,spring-servlet.xml就会越来越大,慢慢的变得难以维护。,而实际上,Spring MVC提供了基于注解的方式来解决这个问题,让配置文件变得更加简洁明了。接下来,我们就使用注解的方式来编写我们的Controller。
使用注解编写spring MVC 的Controller程序,和使用配置文件的方式基本一致,也需要在web.xml配置DispatherServlet(咱们之前已经加过了,暂时不用动了)。我们需要在对SpringMVC的配置文件做一些修改就好:
配置组件扫描器
我们在配置文件中增加组件扫描器就好了。修改spring-servlet.xml配置文件,增加配置:
以上配置增加以后,在应用启动时,SpringMVC 会扫描com.pz.web.study.springmvc.controller包下所有类,并对所有增加了Spring MVC 能够识别的Controller的Annotation的类做实例化操作(大家想想咱的小框架,是不是很类似?)。
配置注解驱动(如果你使用了mvc:resources标签就需要增加这个配置,要不会有404错误)
修改spring-servlet.xml配置文件,增加配置:
编写Controller代码在com.pz.web.study.springmvc.controller包下创建AnnotationControllerDemo类:
package com.pz.web.study.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class AnnotationControllerDemo {
@RequestMapping("/helloByAnnotation.do")
public ModelAndViewhelloAnnotation(HttpServletRequest req, HttpServletResponse res) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "hello spring web mvc by helloAnnotation");
mv.setViewName("helloByAnnotation");
return mv;
}
}
编写页面代码helloByAnnotation.jsp,测试页面嘛可以简单点,启动tomcat,我们访问下:
http://127.0.0.1/helloByAnnotation.do页面输出
hello spring web mvc by helloAnnotation
我们打开之前编写的AnnotationControllerDemo类,这类没有实现任何接口,只是在类名和方法上添加了两个注解:
@Controller(需要引入org.springframework.stereotype.Controller):使用在类名上,表示是一个Controller。
@RequestMapping(需要引入org.springframework.web.bind.annotation.RequestMapping):使用在方法上,表示该方法为Controller提供的方法,属性值value,为一个URI,表示这个方法响应对应的URL,这个URL是一个相对路径,相对于webapp,方法名可以随意命名。一个方法也可以处理多个请求,只用定义多个url就好。
@RequestMapping也可以被使用在类名上,表示这个Controller类下的所有方法,都属于一个目录。当@RequestMapping被使用在类名上时,方法上的@RequestMapping就相对于类名上定义的路径。为了加深大家的理解我们看下面的例子。
package com.pz.web.study.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping("/demo/")
publicclass AnnotationControllerDemo2 {
@RequestMapping("/hello.do")
public ModelAndView hello(HttpServletRequest req,HttpServletResponse res) throws Exception{
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "hello spring web mvc by helloAnnotation");
mv.setViewName("helloByAnnotation");
return mv;
}
@RequestMapping({"/hello2.do","/hello3.do"})
public ModelAndView hello2(HttpServletRequest req,HttpServletResponse res) throws Exception{
ModelAndView mv = new ModelAndView();
mv.addObject("hello", "one method for multiple urls");
mv.setViewName("helloByAnnotation");
return mv;
}
}
启动tomcat分别访问:
http://127.0.0.1/demo/hello.do
http://127.0.0.1/demo/hello2.do
http://127.0.0.1/demo/hello3.do
我建了一个群,群里有很多高手,欢迎大家入群探讨。