SpringMVC-01-HelloSpringMVC
一、回顾MVC与Servlet
1.1 回顾MVC
-
什么是MVC?
- MVC的全称是Model-View-Controller(模型-视图-控制器)
- Model(模型) —— 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
- View(视图) —— 视图代表模型包含的数据的可视化。
- Controller(控制器) —— 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。
-
为什么要使用MVC?
- MVC要实现的目标是将软件用户界面和业务逻辑分离以使代码可扩展性、可复用性、可维护性、灵活性加强。
-
正确的认识MVC
-
我一开始对MVC的认识:
- Model对应实体类和数据库操作,View负责界面,Controller则负责业务处理逻辑。相信这也是很多人对于MVC的认识和理解
-
这种认识存在一个中误区,把MVC当成了三层架构(表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL))
-
实际上,这根本不是MVC的定义
-
V即View视图是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。
-
M即model模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
-
C即controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
-
摘自百度百科
-
-
简单的概括一下,
- Controller层,只(ONLY),负责把View中的业务交给正确的Model去做,真正的业务逻辑在Model中
-
-
使用MVC框架的目的:
- 将URL映射到java的类或者方法上
- 封装用户提交的数据
- 处理用户请求,调用相应的业务处理,封装响应后的数据
- 渲染页面
1.2 回顾Servlet
-
什么是Servlet?
- Servlet是sun公司提供的一门用于开发动态web资源的技术 。Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
1、编写一个Java类,实现servlet接口。
2、把开发好的Java类部署到web服务器中。 - 通常我们也把实现了servlet接口的java程序,称之为Servlet
- Servlet是sun公司提供的一门用于开发动态web资源的技术 。Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:
-
Servlet的运行流程
-
web服务器收到客户端的Servlet访问请求后会调用Servlet程序
- Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
- 装载并创建该Servlet的一个实例对象。
- 调用Servlet实例对象的init()方法。
- 创建一个用于封装HTTP请求消息的HttpServletRequest对象和一个代表HTTP响应消息的HttpServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。
- WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。
-
图解
-
二、什么是SpringMVC
2.1 简介
- SpringMVC是Spring Framework中的一部分,基于Java实现的一种轻量级Web框架
- SpringMVC和Servlet关系
- Servlet做的就是实现页面的跳转,负责给出请求对于的响应
- SpringMVC只是将Servlet进行封装,产出是DispatcherServlet。在使用SpringMVC的时候,我们只需要配置这么一个Servlet即可。
- DispatcherServlet负责帮我们完成所有页面的跳转
- 本质:还是使用了Servlet进行跳转,只不过SpringMVC将它进行封装,我们不需要手动去配置各种mapping映射,只需要告诉Spring容器,哪个页面对应哪个Java类即可
2.2 DispatcherServlet
- Spring的web框架围绕DispatcherServlet设计。 DispatcherServlet的作用是将请求分发到不同的处 理器。
- 从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式。
- Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个Servlet的具体实现类(它继承自HttpServlet 基类)。
2.3 SpringMVC执行流程
- DispatcherServlet接收到用户请求
- 通过HandleMapping和HandlerAdapter找到对应的Handler处理请求
- Handler处理完之后,返回ModelAndView
- 解析ModelAndView,生成对应的视图
- 将视图返回给用户
三、Hello SpringMVC
3.1 Servlet版
-
编写一个Servlet类
package com.pbx.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author BruceXu * @date 2020/12/4 */ public class Hello extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String id = req.getParameter("id"); if ("1".equals(id)) { req.getSession().setAttribute("msg", "id = 1"); } else { req.getSession().setAttribute("msg", "id != 1"); } // 进行视图跳转 req.getRequestDispatcher("WEB-INF/jsp/hello.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }
-
写一个jsp作为View
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Hello</title> </head> <body> ${msg} </body> </html>
-
配置ServletMapping
<servlet> <servlet-name>hello</servlet-name> <servlet-class>com.pbx.servlet.Hello</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping>
-
测试:
-
部署一个Servlet的步骤
- 编写Servlet的具体实现类
- 编写View文件
- 在web.xml中配置Servlet
3.2 配置版
-
在web.xml中配置DispatcherServlet
<!--注册DispatcherServlet--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> </servlet> <!--SpringMVC的DispatcherServlet需要拦截所有请求,然后进行再分配--> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
实现一个Controller
package com.pbx.controller; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author BruceXu * @date 2020/12/5 */ public class Hello implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception { ModelAndView mv = new ModelAndView(); mv.addObject("msg", "Hello World SpringMVC"); // 在这里进行视图跳转 mv.setViewName("hello"); return mv; } }
-
在Spring中注册
HandlerMapping
、HandlerAdapter
、ResourceViewResolve
、Handler
(前三个是SpringMVC中不可获取的三大件)<!--处理器映射器 HandlerMapping--> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!--处理器适配器 HandlerAdapter--> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!--视图解析器 ResourceViewResolver--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--注册Handler--> <bean id="/hello" class="com.pbx.controller.Hello"/>
-
测试
-
这么看起来,使用配置的SpringMVC并没有怎么简化
-
不要着急,我们别忘了Java中注解这个“作弊手段”
3.3 注解版
-
老样子,先注册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-servlet.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>
-
添加SpringMVC配置文件
<!--自动扫描注解--> <context:component-scan base-package="com.pbx.controller"/> <!--过滤掉静态资源,防止访问静态资源时也要被DispatcherServlet处理--> <mvc:default-servlet-handler/> <!--开启注解驱动--> <mvc:annotation-driven/> <!--视图处理器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
-
实现一个Controller
package com.pbx.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; /** * @author BruceXu * @date 2020/12/5 */ @Controller public class Hello { // 返回值为需要跳转到的视图文件名 @RequestMapping("/hello") public String method(Model model) { model.addAttribute("msg", "Hello World Real SpringMVC"); return "hello"; } }
-
测试
3.4 总结
-
SpringMVC三大组件:
HandlerMapping
、HandlerAdapter
、ResourceViewResolve
-
在使用注解进行开发时,需要我们配置的只有视图解析器,其他的完全可以通过注解来代替配置文件的功能
-
SpringMVC开发的一般流程
- 注册DispatcherServlet
- 配置SpringMVC
- 实现Controller类