SpringMVC 入门

SpringMVC开发步骤

添加依赖


<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.springmvc_demo</groupId>
  <artifactId>springmvc_01_quickstart</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>80</port>
          <path>/</path>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

说明:servlet的坐标为什么需要添加<scope>provided</scope>?

  • scope是maven中jar包依赖作用范围的描述,

  • 如果不设置默认是compile在在编译、运行、测试时均有效

  • 如果运行有效的话就会和tomcat中的servlet-api包发生冲突,导致启动报错

  • provided代表的是该包只在编译和测试的时候用,运行的时候无效直接使用tomcat中的,就避免冲突

创建配置类


@Configuration
@ComponentScan("com.springmvc_demo.controller")
public class SpringMvcConfig {
}

创建controller

@Controller
public class UserController {
    
    @RequestMapping("/save")
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'info':'springmvc'}";
    }
}

  • @ResponseBody:表示把返回值直接作为body输出
  • 如果没有使用@ResponseBody,返回值被当作页面文件名,找不到对应的文件,就会报404错误
  • @ResponseBody可以注解方法,也可以直接注解整个类,相当于类型所有方法都使用了@ResponseBody
  • @RequestMapping指定访问路径,也可以注解整个类,这样,会把类上注解的路径 + 方法上的路径,构成完整的访问路径

创建容器配置类代替web.xml,因此可以删除web.xml

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //加载springmvc配置类
    protected WebApplicationContext createServletApplicationContext() {
        //初始化WebApplicationContext对象
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //加载指定配置类
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    //设置由springmvc控制器处理的请求映射路径
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    //加载spring配置类
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}
  • tomcat启动后会自动加载此配置类

启动

  • 注意:启动命令选择tomcat7:run

注意事项

  • SpringMVC是基于Spring的,在pom.xml只导入了spring-webmvcjar包的原因是它会自动依赖spring相关坐标
  • AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类
  • AbstractDispatcherServletInitializer提供了三个接口方法供用户实现
    • createServletApplicationContext方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围
    • createServletApplicationContext用来加载SpringMVC环境
    • getServletMappings方法,设定SpringMVC对应的请求映射路径,即SpringMVC拦截哪些请求
    • createRootApplicationContext方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
    • createRootApplicationContext用来加载Spring环境

SpringMVC服务启动流程

  1. 服务器启动,执行ServletContainersInitConfig类,初始化web容器

    • 功能类似于以前的web.xml
  2. 执行createServletApplicationContext方法,创建了WebApplicationContext对象

    • 该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器
  3. 加载SpringMvcConfig配置类

  4. 执行@ComponentScan加载对应的bean

    • 扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解
  5. 加载UserController,每个@RequestMapping的名称对应一个具体的方法

    • 此时就建立了 /save 和 save方法的对应关系
  6. 执行getServletMappings方法,设定SpringMVC拦截请求的路径规则

    • /代表所拦截请求的路径规则,只有被拦截后才能交给SpringMVC来处理请求

用户请求处理流程

  1. 发送请求http://localhost/save
  2. web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理
  3. 解析请求路径/save
  4. 由/save匹配执行对应的方法save()
    • 上面的第五步已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法
  5. 执行save()

Spring 与 SpringMVC

  • SpringMVC只扫描加载其表现层相关bean,也就是controller包下的类
  • Spring控制的bean就包括了:业务bean(Service),功能bean(DataSource,SqlSessionFactoryBean,MapperScannerConfigurer等)
  • 所有在Spring的配置类中,注意控制@ComponentScan的扫描范围,避免扫描到表现层的bean
    • @ComponentScan作用:设置spring配置类扫描路径,用于加载使用注解格式定义的bean,可以设置以下属性:
      • excludeFilters: 排除扫描路径中加载的bean,需要指定类别(type)和具体项(classes)
      • includeFilters: 加载指定的bean,需要指定类别(type)和具体项(classes)
  • 在SpringMVC项目中如何引入Spring的配置:在容器配置类中
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    protected WebApplicationContext createRootApplicationContext() {
      AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);  // 这里加载Spring的配置类
        return ctx;
    }
}
  • 上面类的简写方式,继承AbstractAnnotationConfigDispatcherServletInitializer,这样就可以不用再去创建AnnotationConfigWebApplicationContext对象,不用手动register对应的配置类
  public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

参数传递

  • 普通参数

  • POJO类型参数

  • 嵌套POJO类型参数

  • 数组类型参数

  • 集合类型参数

  • @RequestParam:获取路径?后面的参数,或者form表单参数(application/x-www-form-urlencoded)

  • @RequestBody:获取请求体参数

  • @PathVariable:获取路径变量

  • 注意:SpringMVC接收JSON数据的实现步骤为:

(1)导入jackson包

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.0</version>
</dependency>

(2)使用PostMan发送JSON数据

(3)开启SpringMVC注解驱动,在配置类上添加@EnableWebMvc注解

(4)Controller方法的参数前添加@RequestBody注解

日期类型的参数

  • 可以使用@DateTimeFormat(pattern="yyyy-MM-dd")指定参数传入的格式
  • 以上各种参数,SpringMVC内部都有对应的转换类,它们都实现了:org.springframework.core.convert.converter.Converter接口

响应

  • 不使用注解@ReponseBody, 方法的返回值当作页面名称

  • 使用@ReponseBody

    • 该注解可以写在类上或者方法上
    • 写在类上就是该类下的所有方法都有@ReponseBody功能
    • 当方法上有@ReponseBody注解后
      • 方法的返回值为字符串,会将其作为文本内容直接响应给前端
      • 方法的返回值为对象,会将对象转换成JSON响应给前端

    此处又使用到了类型转换,内部还是通过Converter接口的实现类完成的,所以Converter除了前面所说的功能外,它还可以实现:

    • 对象转Json数据(POJO -> json)
    • 集合转Json数据(Collection -> json)

Rest风格

  • 按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
    • http://localhost/users 查询全部用户信息 GET(查询)
    • http://localhost/users/1 查询指定用户信息 GET(查询)
    • http://localhost/users 添加用户信息 POST(新增/保存)
    • http://localhost/users 修改用户信息 PUT(修改/更新)
    • http://localhost/users/1 删除用户信息 DELETE(删除)

请求的方式比较多,但是比较常用的就4种,分别是GET,POST,PUT,DELETE

按照不同的请求方式代表不同的操作类型。

  • 发送GET请求是用来做查询
  • 发送POST请求是用来做新增
  • 发送PUT请求是用来做修改
  • 发送DELETE请求是用来做删除

但是注意:

  • 上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
    • REST提供了对应的架构方式,按照这种架构设计项目可以降低开发的复杂性,提高系统的可伸缩性
    • REST中规定GET/POST/PUT/DELETE针对的是查询/新增/修改/删除,但是我们如果非要用GET请求做删除,这点在程序上运行是可以实现的
    • 但是如果绝大多数人都遵循这种风格,你写的代码让别人读起来就有点莫名其妙了。
  • 描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts......

步骤

  • 使用@RestController注解类,替换@Controller与@ResponseBody注解,简化书写
  • 将@RequestMapping提到类上面,用来定义所有方法共同的访问路径
  • 使用@GetMapping @PostMapping @PutMapping @DeleteMapping,分别对应GET,POST,PUT,DELETE各种http操作
posted @ 2025-03-12 21:59  liDB  阅读(19)  评论(0)    收藏  举报