1、概述
Spring MVC是Spring Framework的Web开发部分,是基于Java实现MVC的轻量级Web框架。
为什么要学习SpringMVC ?
Spring MVC的特点:
- 轻量级,简朴易学
- 高效 , 基于哀求相应的MVC框架
- 与Spring兼容性好,无缝团结
- 约定优于设置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁机动
Spring的web框架围绕DispatcherServlet [ 调理Servlet ] 计划。
DispatcherServlet的作用是将哀求分发到不同的Handler。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解情势进行开发,十分简洁;
正因为SpringMVC好 , 简朴 , 便捷 , 易学 , 天生和Spring无缝集成(可以使用IOC和AOP) , 使用约定优于设置 ,能够进行简朴的junit测试 ,支持Restful风格 ,异常处理 ,本地化 ,国际化 ,数据验证 ,范例转换 ,拦截器 等等......以是我们要学习。
最重要的一点还是用的人多 , 使用的公司多 。
2、SpringMVC 焦点组件
- 前端控制器:DispactherServlet
- 处理器映射器:HandlerMapping
- 处理器适配器:HandlerAdapter
- 处理器:Handler
- 视图剖析器:ViewResolver
组件介绍:
- DispactherServlet:用于接收所有的客户端哀求并将哀求分发给合适的Handler(Controller)进行处理。在原生JavaWeb中,分发哀求是由 Tomcat 根据 web.xml 来做的,SpringMVC使用 DispactherServlet 替代了这个功能。(不需要程序员开发)
- HandlerMapping:剖析每个哀求的URL,找到对应的 Handler。(不需要程序员开发)
- HandlerAdapter:适配器模式,适配调用具体的 Handler。(不需要程序员开发)
- Handler:Controller层组件,对客户端哀求进行逻辑处理,替代了原生JavaWeb中的 Servlet 所做的功能。(需要程序员手动开发)
- ViewResolver:将 SpringMVC 中的 逻辑视图名 拼接成具体的视图所在,简化了视图所在的编写。(不需要程序员开发)
Spring MVC框架像许多其他MVC框架一样, 以哀求为驱动 , 围绕一个中央Servlet分派哀求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继续自HttpServlet 基类)。
3、SpringMVC 执行原理
简要分析执行流程
- 当用户通过浏览器发起一个HTTP哀求,哀求直接到前端控制器 DispatcherServlet;
- 前端控制器接收到哀求以后调用处理器映射器HandlerMapping,处理器映射器根据哀求的URL剖析出URI,找到具体的Handler,并将它返回给前端控制器;
- 前端控制器调用处理器适配器HandlerAdapter去适配调用Handler;
- 处理器适配器会根据Handler去调用真正的处理器行止理哀求,并且处理对应的业务逻辑;
- 当处理器处理完业务之后,会返回一个ModelAndView对象给处理器适配器,HandlerAdapter再将该对象返回给前端控制器;ModelAndView 中的 Model 是指 被Model层执行业务处理后返回的数据对象,View 是指 将要转向的视图信息。
- 前端控制器DispatcherServlet将返回的ModelAndView对象传给视图剖析器ViewResolver进行剖析,剖析完成之后就会返回一个具体的视图所在给前端控制器;(ViewResolver根据逻辑的View查找具体的View)
- 前端控制器DispatcherServlet转向具体的视图,并进行渲染;
- 渲染完成之后相应给用户(浏览器显示);
4、HelloSpringMVC(举个实例)
4.1、设置版
- 新建一个Moudle , SpringMVC-02-HelloMVC , 添加web的支持!
- 确定导入了SpringMVC 的依靠!
- 设置web.xml , 注册DispatcherServlet
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> version="4.0">
-
- <servlet>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-name>DispatcherServlet</servlet-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><init-param>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> <param-name>contextConfigLocation</param-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> <param-value>classpath:spring-mvc.xml</param-value>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /></init-param>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-name>DispatcherServlet</servlet-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><url-pattern>/</url-pattern>
- </servlet-mapping>
- </web-app>
复制代码 设置阐明:
- init-param:当哀求进入此servlet时,会携带的初始参数
- classpath:与classpath*::前者指的是 当前项目的编译路径,后者代表的是 当前项目及其依靠jar包的所有编译路径
- load-on-startup:启动级别,当值为0或者大于0时,表示容器在应用启动时就加载这个servlet,值越小,优先级越高,当值是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。
- url-pattern 为 ‘/’:默认匹配,详见 关于tomcat中servlet的url-pattern匹配规则
- 编写SpringMVC 的 设置文件!名称:spring-mvc.xml,添加处理器映射器、 处理器适配器、 视图剖析器
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <bean />
-
- <bean />
-
- <bean >
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="prefix" value="/WEB-INF/jsp/"/>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="suffix" value=".jsp"/>
- </bean>
- </beans>
复制代码 - 编写处理器 Handler ,实现Controller接口 或者 增长注解;需要返回一个ModelAndView,装数据,封视图
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.mvc.Controller;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class HelloController implements Controller {
- @Override
- public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />ModelAndView mv = new ModelAndView();
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />mv.addObject("msg","HelloMVC");
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />mv.setViewName("hello");
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />return mv;
- }
- }
复制代码 - 将编写的 Handler 交给SpringIOC容器,注册bean,添加到spring-mvc.xml中。
- [/code]
- [*]编写要跳转的jsp页面,显示ModelandView存放的数据,以及正常页面;
- [align=center][img]https://img2023.cnblogs.com/blog/3455982/202406/3455982-20240627140629412-1908805607.png[/img][/align]
- [code]<%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>hello</title>
- </head>
- <body>
- ${msg}
- </body>
- </html>
复制代码 - 设置Tomcat,启动测试!
大概遇到的问题:访问出现404,排查步骤:
- 查看控制台输出,看一下是不是缺少了什么jar包。
- 如果缺少jar包,就在项目结构中添加相应的lib依靠!
- 重启Tomcat 即可办理!
4.2、注解版
- 新建一个Moudle,SpringMVC-03-Annotation ,添加web支持!
- 在pom.xml文件引入相关的依靠:主要有Spring框架焦点库、Spring MVC、Servlet、 JSTL等。在父项目中已经引入了!
- 设置web.xml
 - <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> version="4.0">
- <servlet>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-name>DispatcherServlet</servlet-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><init-param>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> <param-name>contextConfigLocation</param-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> <param-value>classpath:spring-mvc.xml</param-value>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /></init-param>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><servlet-name>DispatcherServlet</servlet-name>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><url-pattern>/</url-pattern>
- </servlet-mapping>
-
- </web-app>
复制代码 设置阐明:在上面的设置版讲过了,这里一样,就不说了。
- 添加Spring MVC设置文件
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <bean />
-
- <bean />
-
- <bean >
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="prefix" value="/WEB-INF/jsp/"/>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="suffix" value=".jsp"/>
- </bean>
- </beans>
复制代码 设置阐明:
- 加入了两个Xml定名空间 context、mvc
- :组件扫描
定名空间 context 下的标签,扫描指定包下所有被模板注解标注了的类,将其bean化并注册到IOC中。
模板注解 即 @component 及其 组合注解(@Controller、@Configuration……),它们大都位于 org.springframework.stereotype 包下,抽象界说为 项目的某个模块,比如 @Controller 代表 项目的 控制层,@Service 代表 项目的 服务层,@Configuration 代表 项目的 设置,@Component 代表 项目的 组件。
不想使用组件扫描,也可以将其手动一个个注册成bean- [/code]
- [*]:使用 default-servlet 来处理哀求
- 定名空间 mvc 下的标签,将 匹配到的哀求 转发到 Tomcat 内建的 default servlet 中处理。
- 一般用来处理 静态资源哀求(.html、.css、.mp3、.jpg……),使用此标签要注意 设置中多个HandlerMapping的优先级问题,省得 非静态资源哀求 被匹配上 default servlet ,那样会报 404 错误。
- 其本质是
- [code]<?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <bean />
-
- <bean />
-
- <bean >
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="prefix" value="/WEB-INF/jsp/"/>
- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><property name="suffix" value=".jsp"/>
- </bean>
- </beans><bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /><bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />
复制代码 - :使用 mvc 注解驱动
定名空间 mvc 下的标签,使用注解的方式来处理哀求。
其本质是- <bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean />
复制代码 (spring3.1之前使用的是 DefaultAnnotationHandlerMapping 与 AnnotationMethodHandlerAdapter )
(spring3.1之后替换成如上述所示)
注解方式处理哀求的简要流程:
1)Spring容器启动,RequestMappingHandlerMapping在bean加载完成后,扫描出所有带有@Controller注解的bean,进而遍历出其中所有带有@RequestMapping注解 的方法,将方法上@RequestMapping注解信息封装成RequestMappingInfo对象,其包罗了哀求路径、哀求方法、哀求参数、哀求头等信息,将方法本身封装成HandlerMethod对象,并以RequestMappingInfo为键,HandlerMethod为值,存储在一个Map结构中,以便于后续查找。
2)当一个HTTP哀求到达DispatcherServlet时,DispatcherServlet会调用RequestMappingHandlerMapping的getHandler()方法来查找到相应的 Handler,这里就是HandlerMethod。
3)如果找到了匹配的HandlerMethod,DispatcherServlet就会根据其范例选择合适的HandlerAdapter(即RequestMappingHandlerAdapter)来执行它,并返回效果;如果没有找到匹配的HandlerMethod,DispatcherServlet就会抛出异常并使用下一个 HandlerMapping 来查找 Handler 或者返回404错误页面。
4)如果被封装成HandlerMethod的方法 或者 其上的类 被@ResponseBody注解 标注,那么HandlerMethod的返回效果就是一个单纯的数据字符串,会被当成相应体直接返回给客户端浏览器,否则就是逻辑视图名,会被视图剖析器剖析后转向具体视图。
详见这篇文章的 RequestMappingHandlerMapping 部分:Spring MVC源码剖析——HandlerMapping(处理器映射器)
- 编写Controller层,创建一个Java类:com.moondream.controller.HelloController , 注意编码规范
- import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;@Controller@RequestMapping("/HelloController")public class HelloController { //真实访问所在 : 项目名/HelloController/hello @RequestMapping("/hello") public String sayHello(Model model){ //向模型中添加属性msg与值,可以在JSP页面中取出并渲染 model.addAttribute("msg","hello,SpringMVC");<bean >
-
- <property name="order" value="0"/>
- </bean>
- <bean /> // /WEB-INF/jsp/hello.jsp return "hello"; }}
复制代码 注意:
- 标注在类上的 @RequestMapping,相称于前置要求,每个RequestMappingInfo在被封装时,都会将类和对应方法上的 @RequestMapping 注解信息 整合注入自己。
- 被封装成HandlerMethod的方法,返回值必须是String范例,方法参数会被框架进行数据绑定。如果想在访问的哀求上加数据,可以设置一个Model范例的参数,这个参数对象将由框架传入,它会把自身被加入的数据封装到访问的哀求上。不要设置ModelAndView范例的参数,它在HandlerMethod中无效。
- 一个RequestMappingInfo匹配的哀求范围不能被另一个RequestMappingInfo完全覆盖,否则程序会报错。简朴来说,你要保证一个RequestMappingInfo至少有一类哀求能匹配上。
- 创建视图层
在WEB-INF/jsp目录中创建hello.jsp , 视图可以直接取出并展示从Controller带回的信息;- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>Hello</title>
- </head>
- <body>
- ${msg}
- <br/>
- <%out.print(request.getRequestURI());%>
- </body>
- </html>
复制代码 - 设置Tomcat运行,开启服务器,访问对应的哀求路径!
http://localhost:8080/spring03/HelloController/hello
运行成功!!!
4.3、小结
实现步骤:
- 新建一个web项目
- 导入相关jar包
- 编写web.xml , 注册DispatcherServlet
- 编写springmvc设置文件
- 接下来就是去创建对应的控制类 , controller
- 最后完善前端视图和controller之间的对应
- 测试运行调试.
使用springMVC必须设置的三大件:
通常,我们只需要手动设置视图剖析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,省去了大段的xml设置。
不知道有没有小伙伴注意到一个问题:
在上述注解版的案例中,我们通过定名空间mvc下的两个标签default-servlet-handler和annotation-driven,在SpringIOC中设置了多个HandlerMapping和HandlerAdapter,
那么,当哀求到达时,DispatcherServlet该使用哪个HandlerMapping和HandlerAdapter呢?
当IOC中有多个HandlerMapping时:
- DispatcherServlet会优先使用优先级高的HandlerMapping(所有HandlerMapping中,都有一个order属性,代表优先级)
- 如果HandlerMapping优先级一样,DispatcherServlet会使用先注册的
- 如果使用的HandlerMapping根据哀求找不到Handler,DispatcherServlet会继续使用下一优先级的HandlerMapping继续找,直到找到Handler
当IOC中有多个HandlerAdapter时:
- DispatcherServlet会遍历所有注册的HandlerAdapter,根据哀求的Handler范例来选择对应的HandlerAdapter
- 如果有多个HandlerAdapter都能够支持当前哀求的Handler范例,选择第一个适配成功的HandlerAdapter来执行Handler,即选择先注册的HandlerAdapter
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |