前言
Spring官网的MVC模块介绍:
Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,” comes from the name of its source module (spring-webmvc), but it is more commonly known as “Spring MVC”.
Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就已包含在Spring框架中。正式名称“ Spring Web MVC”来自其源模块的名称(spring-webmvc),但它通常被称为“ Spring MVC”。
Web框架升级是一个不断偷懒的过程
从最开始的Servlet到现在的SpringMVC、SpringBoot等等
SpringMVC:可以从Servlet - 》继承类 - 》注解 过程了解其中的变化
本篇不适合完全初学者入门,而是简述SpringMVC的简化过程
基本配置
- 新建一个普通Maven项目,Maven配置(webmvc 、servlet、jsp、jstl)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--lombok 注解-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
</dependencies>
- Tomcat
- 模块化
随便添加Id
这样就可以在一个Project里分隔开不同的环境
注意Maven项目不是Web项目,需要添加
勾选Web Application:
这样就会多出web文件夹:
传统Servlet
以SpringMVC的格式来写Servlet:
- 设置Servlet
package learn.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//业务逻辑
req.getSession().setAttribute("msg","Hello Servlet");
//视图跳转
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- web.xml注册servlet
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>learn.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
- 编写一个hello.jsp接收信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
- 运行Tomcat : 输入地址http://localhost:8080/hello
这里做了哪些工作呢?
网站访问 - 》 根据网址请求,Web.xml分发请求到helloServlet - 》Servlet处理业务 - 》携带request跳转到test.jsp - 》test.jsp接收msg信息 - 》返回test.jsp到前端
Servlet繁琐在
- 每一个Servlet都需要继承Servlet接口,实现对应的方法
- 每一个Servlet都需要手动注册到Web.xml上
- 传递信息到页面很复杂(Request、Session等传递)
从类的角度看SpringMVC
我们可能习惯了注解,现在换个角度,以Spring和继承类的方法实现SpringMVC
控制层:Controller
@Controller和实现Controller接口效果是一样的:
package com.learn.controller;
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 {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
//业务代码
String result = "HelloSpringMVC";
mv.addObject("msg",result);
//视图跳转
mv.setViewName("test");
return mv;
}
}
在Controller中,不再使用Request、Session,而是使用ModelAndView跳转页面、传递信息
(会有视图解析器处理)
- web.xml注册DispatcherServlet
以后所有的分发处理都由DispatcherServlet完成
<!--配置dispatcherServlet:这个是springMVC的核心(请求分发器、前端控制器)-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--DispatcherServlet要绑定spring的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<!--springmvc:url里
/ : 只匹配所有的请求,不会匹配jsp
/* : 匹配所有的请求,包括匹配jsp
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- springmvc-servlet.xml
因为我们是以类形式实现,就需要Spring的IoC容器装配bean
dispatcherServlet会调用处理器映射器、处理器适配器完成Controller的业务处理、跳转,视图解析
(实际上SpringMVC内置了默认实现处理器映射器、处理器适配器)
处理器映射器BeanNameUrlHandlerMapping : 根据url请求去匹配bean的name属性url,从而获取Controller
处理器适配器SimpleControllerHandlerAdapter: 调用controller里面方法,返回modelAndView
<?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 class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter "/>
<!--视图解析器 : 模板引擎thymeleaf-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--BeanNameUrlHandlerMapping:bean-->
<bean id="/hello" class="com.learn.controller.HelloController"/>
</beans>
实现接口完成SpringMVC,虽然简便了Web.xml,但是Spring的配置复杂了,需要BeanNameUrlHandlerMapping对应bean
且依然需要很多个Controller:一个URL请求对应一个Controller类与bean
实际上,SpringMVC就是这么实现的,只是可以通过注解简化
注解简化
- Controller类简化
使用@Controller注解代替实现接口
使用@RequestMapping注解实现一个Controller类中可以对应多个URL请求
package com.learn.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
//封装数据
model.addAttribute("msg","Hello SpringMVC Annotation");
return "hello";//被视图解析器处理
}
}
- springmvc-servlet.xml简化
因为使用了注解,需要开启注解扫描
使用mvc的自动注入映射器、适配器mvc:annotation-driven
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.learn.controller"/>
<!-- 支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系 要
想使@RequestMapping注解生效 必须向上下文中注册RequestMappingHandlerMapping和RequestMappingHandlerAdapter实例
这两个实例分别在类级别和方法级别处理。
而annotation-driven配置帮助我们自动完成上述两个实例的注入。 -->
<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>
再进行测试:
这就是我们最熟悉的SpringMVC了
这一步简化了什么?
- 简化了Controller类,不需要实现Controller接口
mvc:annotation-driven
自动注入了映射器和适配器,使RequestMapping注解生效,即不用在一个url请求一个Controller类,而是一个方法映射一个url请求- Spring配置类中设置自动扫描包,不需要手动配置bean
总结
Servlet阶段:一个Servlet处理一个URL请求,手动配置转发,手动注册
SpringMVC类阶段:一个Controller处理一个URL请求,简单的转发,只需要在web.xml注册前端转发器,但需要在Spring配置文件配置视图解析器、url映射对应的Controller类
SpringMVC注解阶段: Controller变成普通类(注解标记),简单的转发,只需要在web.xml注册前端转发器,Spring配置文件配置自动扫描,一个Controller可以通过@RequestMapping注解方法去映射对应的url请求,即一个方法映射一个请求
从Servlet到SpringMVC的注解是一个不断偷懒的过程
学海无涯苦作舟
都看到这了,点个赞呗(^_−)☆