1. SpringMVC介绍
-
Spring MVC首先是一个MVC框架。
在Web模型中,MVC是一种很流行的框架,目的就是为了简化web开发。通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的若干部分,简化开发,减少出错。同时,有助于组内开发人员之间的配合。总之,MVC就是一种分层工作的办法。
-
Spring MVC是Spring的一个子框架,拥有Spring的特性,如依赖注入。
Spring MVC是一种基于Java实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。
官方文档:
https://docs.spring.io/spring/docs/5.2.7.RELEASE/spring-framework-reference/web.html#spring-web
中文文档:
http://blog.didispace.com/books/spring-mvc-4-tutorial/
2. SpringMVC入门程序
2.1. 入门案例
实现效果:
详细步骤:
- 新建maven web项目
- 导入依赖jar包
- 添加核心配置文件
- 添加前端控制器
- 编写Controller
- 配置SpringMVC的包扫描和视图解析器
- 编写视图jsp页面
- 配置Tomcat服务
- 启动项目
2.1.1. 新建maven项目
- 改造成web项目
- 说动新建webapp/WEB-INF目录
2.1.2 导入依赖
删除工具自动添加的properties、dependencies、build内容,添加如下配置
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.2.6.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
2.1.3. 添加核心配置文件
在resources目录下添加SpringMVC.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
2.1.4. 配置前端控制器
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<!--SpringMVC的核心控制器-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!--配置servlet的初始化参数 读取springmvc的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--配置servletq启动的优先级,数值越低优先级越高-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
注意:
*.do表示只拦截请求路径以.do结尾的请求,例如:/user/selectAll.do
/user/update.do
/order/select.do
2.1.5. 编写controller
package com.czxy.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(String username,String password){
System.out.println("用户名: "+ username+" 密码:"+password);
return "main";
}
}
2.1.6. 包扫描和视图解析器
配置包扫描和视图解析器
- 在resources目录下添加SpringMVC.xml
<!--spring容器的包扫描-->
<context:component-scan base-package="com.czxy.mvc.controller"/>
<!--视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
<property name="contentType" value="text/html;charset=UTF-8"/>
</bean>
2.1.7. 编写视图页面
index.jsp
<%@ page language="java" contentType="text/html; UTF-8" pageEncoding="UTF-8" %>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h2>Hello World!</h2>
<form action="/hello.do" method="post">
<table>
<tr>
<td>用户名:</td>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<td>密 码:</td>
<td>
<input type="password" name="password">
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="登录">
</td>
</tr>
</table>
</form>
</body>
</html>
main.jsp,注意在WEB-INF目录下新建pages目录
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
</head>
<body>
<h2>主页</h2>
欢迎登录访问
</body>
</html>
2.1.8. 配置Tomcat
- 部署项目
2.1.9. 启动项目
点击启动/调试 按钮启动服务
页面登录
控制台输出:
用户名: tom 密码:123
2.3. Spring MVC运行原理
- 浏览器发送请求,被 DispatherServlet 捕获,该 Servlet 并不处理请求,
- DispatcherServlet而是把请求转发出去。由HandlerMapping根据请求 URL,匹配@RequestMapping 中的内容。
- HandlerMapping找到处理请求的Controller中的方法
- DispatcherServlet将客户端传递的参数提供给HandlerAdapter,HandlerAdapter执行Controller中的方法
- Controller调用业务逻辑处理后,返回ModelAndView
- ViewResolver根据ModelAndView 渲染视图
- DispatcherServlet将视图渲染结果显示到客户端
2.4. springMVC不拦截静态资源的配置
如果配置为/表示拦截所以请求,包括静态资源html、css、img、js等,此时需要再springmvc.xml明确哪些资源不拦截
2.4.1. 方式1:mvc:resources来设置静态资源
在springmvc.xml增加对应静态资源的配置
<!--
当配置了mvc:annotation-driven/后,Spring就知道了我们启用注解驱动。然后Spring通过context:component-scan/标签的配置,会自动为我们将扫描到的@Component,@Controller,@Service,@Repository等注解标记的组件注册到工厂中,来处理我们的请求。
如果在web.xml中servlet-mapping的url-pattern设置的是/,而不是如.do。表示将所有的文件,包含静态资源文件都交给spring mvc处理。就需要用到<mvc:annotation-driven />了。如果不加,DispatcherServlet则无法区分请求是资源文件还是mvc的注解,而导致controller的请求报404错误。
-->
<mvc:annotation-driven/>
<!-- 对客户端请求的静态资源如图片、JS文件等的请求交由 默认的servlet进行处理 -->
<mvc:default-servlet-handler />
<!--
以下配置不能解决DispatcherServlet拦截"/",实现REST风格
因为静态资源先被DispatcherServlet拦截了
-->
location表示路径,mapping表示文件,**表示该目录下的文件以及子目录的文件
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/scripts/" mapping="/javascript/**"/>
-->
<!-- cache-period 使用本地缓存,单位是秒
<mvc:resources location="/images/" mapping="/images/**" cache-period="360000"/>
-->
2.4.2. 方式2:修改全局控制器拦截*.do请求
<!--SpringMVC的核心控制器-->
<servlet>
...
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 所有请求必须以*.do结尾 /user/list.do /order/1001.do -->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2.5. 注解释义
2.5.1. @Controller注解
- 使用位置:标注在类上
- 作用:表示当前类交给Spring容器管理,对象的创建和销毁由容器负责,默认以单例模式管理
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
通过查看源码可以清楚该注解其实就是标注类是一个Component组件。
-
同等作用的注解:
@Service
@Repository
@Component
上述注解作用都一样,将类交给Spring容器管理,名称只是用于在不同层开发进行区分
2.5.2. @RequestMapping
-
使用位置:类或者方法上
-
作用:描述URL的请求路径
- 标注在类上:一般用于模块区分,可以省略
//user模块 @RequestMapping("/user") //物流模块 @RequestMapping("/wms") //商品模块 @RequestMapping("/product")
- 标注在方法上:确定要访问的具体业务,不能省略
//添加 @RequestMapping("/add") //根据手机号查询 @RequestMapping("/select/phone")
通过类和方法上的RequestMapping拼接请求URL,如下代码要访问selectByPhone()的url = /user/select/phone
@Controller @RequestMapping("/user") public class UserController { @RequestMapping("/select/phone") public String selectByPhone(String phone){ //... return "res"; } }
-
属性
- value:用于指定请求的 URL。它和 path属性的作用是一样的。如果只有value一个属性可以省略不写
- path:用于指定请求的 URL,它和value的属性作用一样,但是不能省略
- method:用于指定请求的方式
- params:用于指定限制请求参数的条件
- hereders:用于指定限制请求消息头的条件
示例1:path、method
JSP:
<a href="/user/select/phone.do">测试requestMapping</a>
Controller:
@Controller
@RequestMapping(path = "/user")
public class UserController {
@RequestMapping(value = "/select/phone",method = RequestMethod.GET)
public String selectByPhone(String phone){
//...
System.out.println("测试requestMapping");
return null;
}
}
示例:params
<a href="/user/select/phone.do?phone=13666666666">测试requestMapping</a>
@Controller
@RequestMapping(path = "/user")
public class UserController {
@RequestMapping(value = "/select/phone",method = RequestMethod.GET,params = {"phone"})
public String selectByPhone(String phone){
//...
System.out.println("测试requestMapping");
return "main";
}
}
示例:hereders
@RequestMapping(value = "/select/phone",method = RequestMethod.
GET,params = {"phone","key"},headers = {"Cookie"})
public String selectByPhone(String phone){
//...
System.out.println("测试requestMapping");
return "main";
}