> For the complete documentation index, see [llms.txt](https://jun-wang.gitbook.io/learnjava/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/spring/springmvc-ru-men-bi-ji.md).

# SpringMVC入门笔记

## 1. 简介

Spring MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架 ，是Spring系开源项目中的一个，和IoC配合使用。通过策略接口，Spring框架是高度可配置的，而且支持多种视图技术。Spring分离了控制器、模型对象、分派器以及处理程序对象的角色，这种分离让他们更容易进行定制。Spring MVC解决的问题如下：

* 将web页面的请求传给服务器；
* 根据不同的请求处理不同的逻辑单元；
* 返回处理结果数据并跳转至响应页面；

通过下面这样图可以看到Spring MVC在Spring全家桶中的位置：

![](/files/-M7h5eP8OoKXA2Vc38yo)

## 2. Spring MVC实例

现在总结一下搭建一个完整SpringMVC的步骤，期间遇到了很多坑，404的问题坑了好久，先来记录一下成功的搭建步骤，后面附上源码。本文使用eclipse（Version: Photon Release (4.8.0)）搭建SpringMVC。

### 2.1 新建maven工程

新建一个maven project。

![](/files/-M7h5eP9yzfF8OE372ZF)

![](/files/-M7h5ePA5pHLwYEOV5TM)

![](/files/-M7h5ePBwyLN965qIi0h)

新建好的工程结构应该是这样的：

```
│  .classpath
│  .project
│  pom.xml
│
├─.settings
│      .jsdtscope
│      org.eclipse.jdt.core.prefs
│      org.eclipse.m2e.core.prefs
│      org.eclipse.wst.common.component
│      org.eclipse.wst.common.project.facet.core.xml
│      org.eclipse.wst.jsdt.ui.superType.container
│      org.eclipse.wst.jsdt.ui.superType.name
│      org.eclipse.wst.validation.prefs
│
├─src
│  └─main
│      ├─resources
│      └─webapp
│          │  index.jsp
│          │
│          └─WEB-INF
│                  web.xml
│
└─target
    ├─classes
    ├─m2e-wtp
    │  └─web-resources
    │      └─META-INF
    │          │  MANIFEST.MF
    │          │
    │          └─maven
    │              └─com.wangjun
    │                  └─learnSpringMVC
    │                          pom.properties
    │                          pom.xml
    │
    └─test-classes
```

### 2.2 添加pom依赖

既然是SpringMVC工程，肯定要添加SpringMVC的包，可以去<http://mvnrepository.com/查找，除了SpringMVC还需要添加javax.servlet的包。搞不懂为什么网上很多教程都添加了spring的bean，aop，core这些基础包，这些基础包已经被springmvc依赖了，已经包含进来了，就不用再pom文件手动依赖了。>

pom.xml

```markup
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.wangjun</groupId>
  <artifactId>learnSpringMVC</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>learnSpringMVC Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>4.3.18.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.0-b01</version>
        <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <finalName>learnSpringMVC</finalName>
  </build>
</project>
```

### 2.3 配置web.xml

在web.xml中需要添加使用的servlet和映射规则。

web.xml

```markup
<!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>
  <display-name>Archetype Created Web Application</display-name>

  <!-- DispatcherServlet是SpringMVC框架的核心，它的作用就是讲请求分发给不同的后端处理器 -->
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

   <servlet-mapping>
      <servlet-name>springmvc</servlet-name>  <!-- 需要和上面的servlet-name保持一致 -->
      <url-pattern>/</url-pattern> <!-- url的匹配规则，/ 就是匹配所有 -->
   </servlet-mapping>
</web-app>
```

### 2.4 新建springmvc-servlet.xml文件

在web.xml同级目录下新建springmvc-servlet.xml文件（就是在web.xml配置的servletName+servlet）。这里面负责配置映射类和视图适配器等。

springmvc-servlet.xml

```markup
<?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:tx="http://www.springframework.org/schema/tx" 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 
       http://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
          http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

   <!-- 注册HandlerMapper、HandlerAdapter两个映射类（不写会导致404问题） -->
   <mvc:annotation-driven/>

    <!-- 下面是配置扫描包的位置,包名为com.learnspringmvc,也就是说我们的视图解析器应该放在com.learnspringmvc包下 -->
   <context:component-scan base-package="com.learnspringmvc" />

   <mvc:default-servlet-handler/>

   <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <!-- 前缀,我们的视图文件应该放到/WEB-INF/jsp/目录下,这里我们需要在WEB-INF下面创建jsp文件夹 -->  
      <property name="prefix" value="/WEB-INF/jsp/" />
      <!-- 设置后缀为.jsp -->
      <property name="suffix" value=".jsp" />
   </bean>
</beans>
```

### 2.5 新建页面jsp文件

在WEB-INF下新建jsp文件夹，然后在jsp下新建demo.jsp

demo.jsp

```
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Hello springMVC!
</body>
</html>
```

### 2.6 新建controller控制类

在main文件夹下新建java文件夹，在新建HelloController.java文件，包名为com.learnspringmvc.controllers。

```java
package com.learnspringmvc.controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

//控制器注解
@Controller
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/showdemo")
    public String getString() {

        // 必须在配置的view路径下存在demo.jsp,否则返回404
        return "demo";
    }

}
```

### 2.7 编译打包

进入到项目的根目录下（pom.xml存在的文件夹），打开doc，执行`mvc install`，出现`BUILD SUCCESS`表示打包成功，在target文件夹下生成`learnSpringMVC.war`，将此war包移动到tomcat的webapps下面，重启服务器，访问<http://localhost:8080/learnSpringMVC/hello/showdemo：（注意：8080：后面紧跟的不是在web.xml中配置的servlet-name，而是在pom.xml中build的finalName属性）>

![](https://github.com/wangjun-scu/learnjava/tree/2973c09efb72ce0cb0c23353f29cc8550aeefc2a/assets/springmvc4.png)

### 2.8 关于404问题的坑

在搭建工程的时候，访问页面显示404，困扰了很久，也在网上搜了很多答案，这是一篇质量比较高的：<https://blog.csdn.net/baidu_15275441/article/details/73930961。404问题很难排查，因为并没有报错和堆栈信息，只能一个一个的排查可能的问题，写这边博客的时候又发现了一个导致404的原因，就是上面2.7写到的：8080：后面紧跟的不是在web.xml中配置的servlet-name，而是在pom.xml中build的finalName属性。可见404问题无处不见，由于自己对SpringMVC框架只是个小白，只能搜索加尝试。希望后面能成为大神级别的。这种问题都是小case。>

补充（2018年9月17日）：今天又遇到了一个404的问题，集成mybaits的时候在web.xml添加了

```markup
<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath:spring*.xml
    </param-value>
</init-param>
```

搞了半天mybaits集成好了，结果访问controller又404了，排查了很久，发现这个参数有问题，上网查了一下，这个参数是定义了要装入的 Spring 配置文件。因为在没有这个配置的时候默认读取的是{servleName}-servlet.xml这个文件，添加此配置后就会读取配置的路径，而不再读取{servleName}-servlet.xml，这就是导致404的问题，我们可以把{servleName}-servlet.xml的路径也配进去，以英文逗号隔开。

> **源码：**<https://github.com/WangJun-SCU/LearnSpringMVC>

## 3. SSH个SSM两个框架的区别

SSH(Spring，Struts，Hibernate)和SSM(Spring，SpringMVC，MyBatis)的区别其实就是SpringMVC和Struts，Hibernate和MyBatis的区别。

### 3.1 SpringMVC和Struts的区别

1. Struct和Spring-MVC都是负责取转发的，但是两者针对request的请求上面区别很大，Struct是针对一个Action类来进行请求的，即一个Action类对应于一个请求，所以类拦截，请求的数据类共享。而Spring-MVC则是针对于方法级别的请求的，也就是一个方法对应于一个请求，属于方法拦截，请求的数据方法不共享。
2. Spring-MVC的配置文件相对来说较为少，容易上手，可以加快软件开发的速度。
3. Spring-MVC的入口是Servlet级别的而Struct的级别是Filter级别的。

### 3.2 Hibernate和MyBatis的区别

1. Hibernate是一种O/R关系型，即完成数据库表和持久化类之间的映射，而MyBitas是针对的SQL-Mapping，Hibernate把数据库给封装好以后，可以调用相应的数据库操作语句SQL，而MyBitas则是用的原始的数据库操作语句。基于此原因，Hibernate优化起来相对MyBitas较难。
2. MyBitas入门较快，而Hibernate掌握起来相对较难。
3. 针对高级查询，Mybatis需要手动编写SQL语句，以及ResultMap。而Hibernate有良好的映射机制，开发者无需关心SQL的生成与结果映射，可以更专注于业务流程。
4. Hibernate数据库移植性很好，MyBatis的数据库移植性不好，不同的数据库需要写不同SQL。

### 3.3 总结：

SSH很笨重，现在除了一些老系统，很少有人使用SSH了，SSM则是现在的主流，当前还有SpringBoot，SpringCloud微服务这些。

## 4. SpringMVC常用注解

### 4.1 @RequestMapping

前端URL访问映射

### 4.2 @ResponseBody

该方法的返回结果直接写入HTTP响应正文（ResponseBody）

### 4.3 @RequestBody \#

将htttp请求正文插入到方法中。比如：

```
@RequestMapping(value = "user/login")
@ResponseBody
public User login(@RequestBody User user) {   
    ...
}
```

### 4.4 @RequestParam

直接从http获取数据，比如：

```java
@RequestMapping("/")
public String Demo1(@RequestParam String id){
    return null;
}
// 等同于这样获取id
@RequestMapping("/")
public String Demo1(HttpServletRequest request){
    String id = request.getParameter("id");
    return null;
}
```

### 4.5 @Autowired

自动装配Bean，生成一个可用实例。

### 4.6 @Service

用于标注业务层组件，在类上使用此注解就不需要在xml中配置`<bean/>`了。和@Autowired配合使用。

### 4.7 @Repository

注解可以标记在任何的类上，用来表明该类是用来执行与数据库相关的操作（即dao对象），并支持自动处理数据库操作产生的异常。

### 4.8 @Component

@Component是一个通用的Spring容器管理的单例bean组件。而`@Repository`, `@Service`, `@Controller`就是针对不同的使用场景所采取的特定功能化的注解组件，可以说是 @Component的超集。

几种注解的区别：

| 注解          | 含义                        |
| ----------- | ------------------------- |
| @Component  | 最普通的组件，可以被注入到spring容器进行管理 |
| @Repository | 作用于持久层                    |
| @Service    | 作用于业务逻辑层                  |
| @Controller | 作用于表现层（spring-mvc的注解）     |

**总结：**

`@Component`, `@Service`, `@Controller`, `@Repository`是spring注解，注解后可以被spring框架所扫描并注入到spring容器来进行管理 `@Component`是通用注解，其他三个注解是这个注解的拓展，并且具有了特定的功能 `@Repository`注解在持久层中，具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。 `@Controller`层是spring-mvc的注解，具有将请求进行转发，重定向的功能。 `@Service`层是业务逻辑层注解，这个注解只是标注该类处于业务逻辑层。 用这些注解对应用进行分层之后，就能将请求处理，义务逻辑处理，数据库操作处理分离出来，为代码解耦，也方便了以后项目的维护和开发。

> 参考：
>
> <https://www.cnblogs.com/ysocean/p/7375405.html>
>
> <https://blog.csdn.net/horero/article/details/54236833>
>
> SpringMVC映射的前端后台数据交互总结：<https://blog.csdn.net/xiansky2015/article/details/79050772>
>
> 基于注解的入门实例：<https://www.cnblogs.com/ysocean/p/7400987.html>
>
> @Component, @Repository, @Service的区别：<https://blog.csdn.net/fansili/article/details/78740877>
