SpringMVC 概述

1 简介

SpringMVC是一种基于Java实现MVC模型的轻量级Web框架
SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装。
SpringMVC是处于Web层的框架,所以其主要的作用就是用来接收前端发过来的请求和数据然后经过处理并将处理的结果响应给前端。
REST是一种软件架构风格,可以降低开发的复杂性,提高系统的可伸缩性,后期的应用也是非常广泛。
SSM整合是把SpringMVC+Spring+Mybatis整合在一起来完成业务开发,是对这三个框架的一个综合应用。

 

2 快速入门

(1) 导入jar包

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
        <!--servlet的坐标需要添加<scope>provided</scope>-->
        <!--如果运行有效的话就会和tomcat中的servlet-api包发生冲突,导致启动报错。-->
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
    <!--SpringMVC是基于Spring的,在pom.xml只导入了 spring-webmvcjar包的原因是它会自动依赖spring相关坐标。-->
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <port>8080</port>
                <path>/</path>
            </configuration>
        </plugin>
    </plugins>
</build>

(2) 创建配置类

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

(3) 创建Controller类

@Controller
public class UserController {
    @RequestMapping("/save")
    //设置当前控制器方法请求访问路径
    @ResponseBody
    //设置当前控制器方法响应内容为当前返回值,无需解析为页面。
    //写在类上,该类的所有方法都有该注解功能。
    //若返回值为字符串,则字符串为响应体。若为对象或者数组、集合则转换为json作为响应体(需要添加jackson坐标)。
    //若不添加该注解,方法直接返回字符串,springmvc会把字符串当成页面的名称在项目中进行查找返回,因为不存在对应返回值名称的页面,所以会报404错误,找不到资源。
    public String save(){
    //若该方法没有返回值void,页面会报错,页面报错的原因是后台没有指定返回的页面。
        System.out.println("UserController_save");
        return "{'info':'springmvc'}";
    }
}

(4) 使用配置类替换web.xml

//将web.xml删除,换成ServletContainersInitConfig。
//这个servlet配置文件就是用的servlet,它的作用是告诉tomcat用SpringMVC的封装的方式来处理Servlet。
//AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类。
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
//加载SpringMVC容器,即用来加载SpringMVC环境。
//创建SpringMVC容器时,会通过加载SpringMVC配置类来扫描SpringMVC对应的bean并放入WebApplicationContext对象(即SpringMVC容器)范围中,而WebApplicationContext的作用范围为ServletContext(web容器)范围。
    protected WebApplicationContext createServletApplicationContext() {
    //初始化WebApplicationContext对象
        AnnotationConfigWebApplicationContext acwac = new AnnotationConfigWebApplicationContext();
        //加载指定配置类
        acwac.register(SpringMvcConfig.class);
        //相当于AnnotationConfigWebApplicationContext acwac = new AnnotationConfigWebApplicationContext(SpringMvcConfig.class);
        return acwac;
    }
    //设定SpringMVC对应的请求映射路径,即SpringMVC拦截哪些请求。
    //意为将所有接收到的数据都拦截,交给springmvc处理。
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    //加载spring容器,即用来加载Spring环境。
    protected WebApplicationContext createRootApplicationContext() {
    //如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式和createServletApplicationContext相同。
        AnnotationConfigWebApplicationContext acwac = new AnnotationConfigWebApplicationContext();
        acwac.register(SpringConfig.class);
        return acwac;
    }
}

(5) 配置Tomcat环境,启动运行项目

(6) 浏览器访问

(7) 浏览器输入http://localhost/save进行访问


3 工作流程

(1) 启动服务器初始化过程

<1> 服务器启动,执行ServletContainersInitConfig类,初始化web容器(即servlet容器)。
//功能类似于以前的web.xml。
<2> 执行createServletApplicationContext方法,创建了WebApplicationContext对象(即springMVC容器)。
//该方法加载SpringMVC的配置类SpringMvcConfig来初始化SpringMVC的容器。
//SpringMVC容器在web容器中。
<3> 创建SpringMvc容器时,需要加载SpringMvcConfig配置类。

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

<4> 加载SpringMvcConfig配置类时,需要执行@ComponentScan加载对应的bean。
//扫描指定包及其子包下所有类上的注解,如Controller类上的@Controller注解。
<5> 此时加载UserController,每个@RequestMapping的名称对应一个具体的方法。
//此时就建立了/save和save方法的对应关系

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

<6> 执行getServletMappings方法,设定SpringMVC拦截请求的路径规则。
//"/"代表所拦截请求的路径规则,只有被拦截后才能交给SpringMVC来处理请求。

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

(2) 单次请求过程

<1> 发送请求http://localhost/save
<2> web容器发现该请求满足SpringMVC拦截规则,将请求交给SpringMVC处理。
<3> 解析请求路径/save。
<4> 由/save匹配执行对应的方法save()。
//在服务器初始化过程中已经将请求路径和方法建立了对应关系,通过/save就能找到对应的save方法。
<5> 执行save()。
<6> 检测到有@ResponseBody直接将save()方法的返回值作为响应体返回给请求方。

 

4 bean加载控制

(1) 问题

在Spring的配置类SpringConfig中使用注解@ComponentScan,当时扫描的范围中其实是已经包含了controller,Spring已经把SpringMVC的controller类也给扫描到。
因为功能不同,应避免Spring错误加载到SpringMVC的bean。

(2) 思路分析

//加载Spring控制的bean的时候排除掉SpringMVC控制的bean
方式一:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
方式二:Spring加载的bean设定扫描范围为com.itheima,排除掉controller包中的bean
方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中[了解即可]

(3) 设置bean加载控制

<1> 方式一:修改Spring配置类,设定扫描范围为精准范围

@Configuration
@ComponentScan({"com.itheima.service","comitheima.dao"})
//Dao最终是交给MapperScannerConfigurer对象来进行扫描处理的,我们只需要将其扫描到service包即可,但为了通用性,建议写上。
//若数据层未整合mybatis而是其他技术,则不会有MapperScannerConfigurer对象来进行扫描处理dao。
public class SpringConfig {
}

<2> 方式二:修改Spring配置类,设定扫描范围为com.itheima,排除掉controller包中的bean

@Configuration
@ComponentScan(value="com.itheima",
    excludeFilters=@ComponentScan.Filter(
    //excludeFilters属性:设置扫描加载bean时,排除的过滤规则。
        type = FilterType.ANNOTATION,
        //type属性:设置排除规则,当前使用按照注解类型进行排除。
        classes = Controller.class
        //classes属性:设置排除的具体注解类型,当前设置排除@Controller定义的bean。
    )
)
public class SpringConfig {
}

<3> 注意
<3.1> type属性其他排除规则
ANNOTATION:按照注解排除。
ASSIGNABLE_TYPE:按照指定的类型过滤。
ASPECTJ:按照Aspectj表达式排除,基本上不会用。
REGEX:按照正则表达式排除。
CUSTOM:按照自定义规则排除。
<3.2> 方式二使用中的问题
Spring配置类扫描的包是 com.itheima。
SpringMVC的配置类,SpringMvcConfig上有一个@Configuration注解,也会被Spring扫描到。
SpringMvcConfig上又有一个@ComponentScan,把controller类又给扫描进来了。
所以如果不把@ComponentScan注释掉,Spring配置类将Controller排除,但是因为扫描到SpringMVC的配置类,又将其加载回来,就不会起到排除效果。
解决方案:把SpringMVC的配置类移出Spring配置类的扫描范围即可。
//springconfig排除了controller包,但是springconfig会扫到SpringMVCconfig,而SpringMVCconfig会扫到controller,所以白过滤了。
//如果把两个配置类提到itheima外面,springconfig就扫不到SpringMVCconfig,所以就不会白过滤了。

 

5 Spring简化配置类开发

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[]{"/"};
    }
}

 

posted @ 2023-10-17 21:37  10kcheung  阅读(88)  评论(0)    收藏  举报