文章目录
SpringMVC
关注微信公众号:
回复 springMVC
,获取详细介绍文章
传统 JavaEE 项目中,对于不同的请求,我们都要去写一个 Servlet,一旦请求增多,Servlet 的量就会十分巨大(比如说对用户的增删改查,我们就需要去写4个servlet),有没有办法,可以将对同一个类的操作,写在一个类(控制器)里呢?这,就需要用到我们的 SpringMVC 了。
在看这个文档之前,我强烈建议各位,去看一下我之前写的一个简易的 MVC 框架,就是模仿 SpringMVC框架来编写的,但是十分的轻量级,可以帮助我们很好的取了解 SpringMVC 的执行流程,和实现方式
一、快速开始
入门案例
在去学习 SpringMVC 的知识之前,我们先去尝试配置一下SpringMVC
1、创建 Maven 格式的 web 项目
这里的步骤我就跳过了
2、编写 Spring 和 SpringMVC 的配置文件
之所以要将二者区分开来,是因为 SpringMVC 设定为专门控制 controller,而 Spring 用来管理其他对象。这样可以让我们的项目结构更加清晰
配置文件内容如下:
spring:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--spring所要管理的部分-->
<context:component-scan base-package="top.faroz.service,top.faroz.dao"/>
</beans>
springMVC:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--mvc所要管理的部分-->
<context:component-scan base-package="top.faroz.controller"/>
<!--开启注解驱动,说明 top.faroz.controller 中的注解,都是有用的-->
<mvc:annotation-driven/>
</beans>
3、编写 web.xml
虽然我们上面写了 spring 和 springMVC 的配置文件,但是没有去实例化二者的容器。根据 JavaEE 的生命周期可知,在项目开启的时候,Tomcat 会去创建 Servlet ,并且,监听器也会在项目开启后,开始工作。
所以,我们就要用到 监听器,和JavaEE的生命周期,去创建 Spring 和 SpringMVC 的容器
web.xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.spring配置 相当于我们之前去 new ClassPathXmlApplicationContext()-->
<!--1.1. spring 配置文件的位置-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--1.2. 监听器,这样当web容器开启是时候,就会去注册我们的spring容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--2.springmvc配置 配置中央控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<!--指定要被创建的中央控制器的位置-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--要指定 springmvc 的配置文件位置-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--在 tomcat 开启的时候,就创建该servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!--为 中央控制器 配置访问路径-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
4、配置视图解析器
视图解析器的作用,在于,告诉我们的 SpringMVC,该去访问什么类型的视图(html jsp…)
<!--视图解析器,告诉我们的 SpringMVC,该去访问什么类型的视图(html jsp...)-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
如果我们最后,所有的视图位置,在一个叫 jsp 的文件夹下
那我们的视图解析器配置,就要修改为:
5、测试
编写 controller 代码,service、dao 代码,进行测试
controller 代码如下:
最外层要加上 @Controller 注解,告诉Spring,这是应该被托管的对象
调用的 Service 对象,也要加上 @Resource 注解,保证依赖注入
@Controller
public class UserController {
@Resource
private UserService userService;
@RequestMapping("add.do")
public ModelAndView add() {
System.out.println("执行 add.do");
userService.getAll();
ModelAndView mv = new ModelAndView();
/**
* 相当于 request.setAttribute(..)
*/
mv.addObject("user",new User(1,"haha",22));
/**
* 会经过 springMVC的视图解析器,转换成我们的物理路径
* 相当于 request.getRequestDispatcher("index.html").forword..
*/
mv.setViewName("index");
return mv;
}
}
idex.jsp如下:
我们在页面上,显示从后端接口传来的参数
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>--index ${user.name}</h1>
</body>
</html>
测试结果如下:
开启服务器,访问 add.do
案例解析
当 Spring 和 SpringMVC 同时出现,我们的项目中将存在两个容器,一个是 Spring 容器,另一个是 SpringMVC 容器,Spring 容器通过 ContextLoaderListener 来加载,SpringMVC 容器则通过 DispatcherServlet 来加载,这两个容器不一样:
1.Spring容器中不能扫描所有Bean嘛?
不可以。当用户发送的请求达到服务端后,会寻找前端控制器DispatcherServlet去处理,只在
SpringMVC容器中找,所以Controller必须在SpringMVC容器中扫描。
2.SpringMVC容器中可以扫描所有Bean嘛?
可以。可以在SpringMVC容器中扫描所有Bean。但是实际开发中一般不会这么做,原因如下:
(1)为了方便配置文件的管理
(2)未来在 Spring+SpringMVC+Mybatis组合中,要写的配置内容很多,一般都会根据功能分开编写
二、SpringMVC 执行流程
三、SpringMVC 的组件
四、@RequestMapping
作用范围
打开源码,我们来看一下:
使用方式
了解了上面的作用范围,我们就知道,可以在类最外层,限定请求的对象了
限定请求方法
可以使用 @RequestMapping
的 Method 属性,指定请求方法
@RequestMapping(value = "/add.do" , method = RequestMethod.GET) //指定使用 get 方法,可以请求
但我们常营的方法,还是对于不同请求类型,使用不同注解
@PostMapping
@GetMapping
@PutMapping
@DeleteMapping
...
五、url-pattern解析
为什么不能用 /
我们之前在配置的时候,访问路径后面是加上 .do
的
但是,我们也看到有项目,使用 /
作为访问路径,它们是经过配置的