• SpringMVC基础篇:引言


    第一章:SpringMVC引言

    一:什么是SpringMVC

    概念:SpringMVC是在Spring框架基础上衍生而来的一个MVC框架,主要解决了原有的MVC框架过程中控制器(Controller)的问题。
    SpringMVC是Java开发当中最主流的web技术,决定了对web开发的掌握的深度。

    1:什么是MVC

    概念:MVC是一个架构思想,广泛应用于JavaWeb领域。

    1. MVC是一个架构思想,在JavaEE开发中多用于Web开发。
    2. 应用MVC架构思想开发应用,会把一个项目划分为了3个层次,M(Model) 模型层,V(View) 
    视图层,C(Controller) 控制层。
    		View       JSP
    		Model      Service+DAO
    		Controller Servlet
    3. MVC这种分层开发,体现了面向对象各司其职的设计思想,也更加有利于后续的项目维护(修改)
    补充说明:
    controller控制层:纵览全局,进行调度,他就是控制器,使用servlet
    view:进行相关展示,主要使用jsp进行展示,
    model:业务和相关数据处理
    **特定的类,只关注于特定的工作**
    对于jsp来讲,他擅长的是将html和数据进行结合,进行相应的渲染,servlet来讲可以接受用户的请求,并进行相应的跳转,
    这个时候,servelet适合做为控制层,service和dao完成业务的处理和数据的存储,这样三者之间是没有相互相应的,
    这样的话,及时我们后续更改技术,有太大的影响,方便进行后续项目的维护
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2:SpringMVC为什么要基于Spring框架

    1):站在巨人的肩膀上

    他基于Spring框架,就能获取Spring为我们带来的一系列的好处。Spring的牛逼之处就在于他的IOC和AOP,基于Spring也就可以大大简化MVC的开发(不必将这些优秀的功能在封装一遍)

    2):独木难成桥

    在Spring这个优秀的技术平台上,更加方便与其他的优秀的框架进行整合。

    通过工厂(容器)创建对象,解耦合 (IOC DI)。
    通过AOP的方式,为目标类(原始类),增加额外功能。
    方便与第三方框架的集成:MyBatis.JPA.MQ
    
    • 1
    • 2
    • 3

    3:原有MVC开发中控制器

    1):原有MVC开发控制器技术实现

    servlet技术【Java Model2模式中提到的技术】
    strus2当中的action也是控制器
    Java Model2模式,是十几年前,sun公司提出的,servlet作为控制器,Jfb做展示,这种模式称为model2。
    servlet就是原有控制器的一种实现方式,strus2当中的Action也是控制器的一种实现方式
    
    • 1
    • 2
    • 3
    • 4

    2):控制器核心作用

    接收用户的请求,调用业务功能,根据处理的结果控制程序的运行流程。
    控制器里都需要实现的核心代码:接收用户请求,处理业务逻辑,控制程序流程运转。
    1、接收client请求参数,
    2、调用业务对象,
    3、流程跳转。或者是页面跳转。
    不论是原生Servlet,SpringMVC,还是Structs,这些MVC工具都是要做这些是几个事情,如果说我们的代码
    超出了这个范畴的话,说明我们的代码写的位置不是很合理。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3):这些控制器时存在的问题

    A:接收参数时的问题
    1、代码冗余
    2、只能接收字符串类型的数据,其他类型需要进行手工转换
    3、无法自动封装对象。
    以上这两行代码,大量内容都是重复的。读取文本文件,通过应用层协议,传递过来的数据传递过来的时候,
    初步接收的时候都是字符串,但是后续开发过程中,我们需要吧id转换成long或者其他类型的值。
    接收数据的过程中,不能封装程一个对象。例如一个User对象。以上的缺点都是后续	
    SpringMVC帮我们做的事。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    B:调用业务对象过程中
    还得new创建对象,这样造成了耦合
    
    • 1
    C:流程跳转或者页面跳转存在的问题
    1、跳转路径耦合:我们采用的forward进行跳转。出现了路径耦合
    2、宇视图层技术耦合。
    
    • 1
    • 2

    二: SpringMVC学习要点

    1:SpringMVC的三种开发模式

    1):传统的试图开发

    通过作用域(request,session)进行数据的传递
    通过试图层技术进行数据的展示(jsp,freemaker,thymeaf)进行数据的展示
    知识点和servlet区别不大。
    
    • 1
    • 2
    • 3

    2):前后端分离的开发

    多种新的请求发送方式
    restful的访问方式。
    通过httpMessageconverter进行数据响应,不在通过jsp,free,或者thymleaf
    
    • 1
    • 2
    • 3

    3):Spring5 引入的webflux开发

    替换了传统的JavaWeb开发,一种新的web开发方式
    通过NettyServer进行web通信。

    2:创建父子工程

    1):什么叫父子工程

    父子工程就是先创建一个父工程,再在父工程地下创建若干个子工程,父工程用于管理项目结构和依赖,
    依赖全部在父工程当中进行设置。我们后续的boot和cloud都是采用父子工程的设置。
    ctrl+shift+alt+s快速进入project structure选项中。我们先设置JDK为1.8,在设置语言级别为1.8,
    然后就该创建父工程了。父子工程创建好之后如何在pom文件当中如何体现父子级关系呢?
    
    • 1
    • 2
    • 3
    • 4

    常见好的目录结构如下:
    在这里插入图片描述

    父子工程创建好时候,父工程主要是控制项目结构依赖版本,具体业务代码的开发都是在子工程当中。当我们创建好之后,我们就会发现,并没有按照标准的maven目录给我们创建。我们的src/main/下边应该还有一个java源码目录和一个resource资源目录。当然还有我们的测试目录。我们手动进行修复。

    2):web.xml

    web.xml文件基于maven骨架创建的版本他的servlet版本是2_3,我们使用Tomcat8版本,需要我们的Servlet支持3.x以上的版本,Tomcat9需要支持4.x以上的版本。我们删除掉这个配置文件,使用idea帮我们进行创建新的,基本步骤是:
    在这里插入图片描述

    3):对某个子工程进行部署

    我们是父子工程,我们将子工程当中的依赖,构建都去掉,因为父工程都为我们做好了。
    搭建好web项目之后,我们需要对他进行部署,也可能是对其中的某一个web工程进行部署,我们如何来部署一个web项目呢?打开add configuration这时候来到我们Tomcat的设置目录,点击local,选择TomcatServer
    在这里插入图片描述
    在这里插入图片描述
    然后再deployment当中选择部署应用,我们选择的不要选择war包的形式,要选择普通目录(带exploded)的方式,方便我们后续进行调试。ApplicationContext是对我们web应用的名字进行设置我们选择basic。回到Server当中,我们对VM opetions做一些设置,也就是虚拟机参数:
    -Dfile.encoding=UTF-8这个参数是防止Tomcat启动的时候控制台打印出现乱码。端口我们习惯上改为8989。基于此我们已经能够看出来,当前项目中父工程下一共有4个子工程,我们使用idea整合tomcat,并将其中的要给子项目部署到Tomcat服务器当中。我们已经搭建好了web项目的环境(web父子工程),接下来我们需要搭建一下SpringMVC环境的搭建。

    三:SpringMVC环境的搭建

    1:引入依赖jar包

    整体来讲SpringMVC是相对于Spring来讲,我们就多了一个MVC的包,值得注意的是,我们需要在父工程当中引入所有的依赖。

        <dependencies>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>javax.servlet-apiartifactId>
                <version>3.1.0version>
                <scope>providedscope>
            dependency>
    
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>jstlartifactId>
                <version>1.2version>
            dependency>
    
            <dependency>
                <groupId>javax.servlet.jspgroupId>
                <artifactId>javax.servlet.jsp-apiartifactId>
                <version>2.3.1version>
                <scope>providedscope>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-coreartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-beansartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-testartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-txartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.2version>
            dependency>
    
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>druidartifactId>
                <version>1.1.18version>
            dependency>
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>5.1.48version>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.4.6version>
            dependency>
    
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.13version>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-contextartifactId>
                <version>5.1.4.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-aopartifactId>
                <version>5.1.14.RELEASEversion>
            dependency>
    
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjrtartifactId>
                <version>1.8.8version>
            dependency>
    
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.8.3version>
            dependency>
    
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>slf4j-apiartifactId>
                <version>1.7.25version>
            dependency>
    
            <dependency>
                <groupId>org.slf4jgroupId>
                <artifactId>jcl-over-slf4jartifactId>
                <version>1.7.25version>
            dependency>
    
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-classicartifactId>
                <version>1.2.3version>
            dependency>
    
            <dependency>
                <groupId>ch.qos.logbackgroupId>
                <artifactId>logback-coreartifactId>
                <version>1.2.3version>
            dependency>
    
            <dependency>
                <groupId>org.logback-extensionsgroupId>
                <artifactId>logback-ext-springartifactId>
                <version>0.1.4version>
            dependency>
    
            <dependency>
                <groupId>org.yamlgroupId>
                <artifactId>snakeyamlartifactId>
                <version>1.25version>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154

    补充说明:
    如何设置maven依赖添加之后,自动导入:
    右边maven有一个小扳手,选择Auto-reload settings进来之后,选择any changes即可
    另外,我们所有的依赖都只在我们的父工程当中进行了配置,但是我们子工程当中的maven依赖是都能依赖到,都能看得到的,可见父工程的依赖完全可以供子工程进行使用。

    2:导入框架配置文件

    作为SpringMVC来讲,他的配置文件就是原有Spring的配置文件,SpringMVC既然衍生自Spring很多的功能都是公用的。

    两个注意事项:
    1:SpringMVC的配置文件明后名称可以随意命名,但是我们在这里叫做:dispatcher.xml
    2:SpringMVC的配置文件放置路径可以随意放置,但是这次我们放到根下,准确来讲是资源文件夹的根下。有了这两个特殊的说明之后。我们就可以在SpringMVC项目中引入他的配置文件了。
    资源文件夹的根目录下就是resources底下,这个dispatcher.xml文件本质上就是Spring的配置文件。

    3:初始化配置

    对配置文件进行相应的配置

    1):web.xml

    
    
        
        
            
            dispatcherServlet
            
            org.springframework.web.servlet.DispatcherServlet
            
            
            
                
                contextConfigLocation
                
                
                
                
                classpath:dispatcher.xml
            
            
            
            
            
            1
        
    
        
            dispatcherServlet
            /
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2):dispatcher.xml

    
    
    
        
        
    
        
        
        
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4:初始化配置当中细节

    1):dispatcher起到了什么作用

    DispacherServlet我们习惯称之为前端控制器或者叫中央控制器。他的核心作用有两点:

    1:创建Spring的工厂和容器。
    我们每次测试的时候都需要创建Spring的工厂,在工厂当中去获取我们的对象。
    然而在Web开发当中,我们Spring工厂对象是交由我们的前端控制器来创建的,所以这个在我们配置以后就等效于我们已经在Tomcat服务启动的时候就已经创建了Spring的工厂,所以这块就等效于我们进行了new ClassPathXmlApplicationContext(“dispacher.xml”);所以这里边需要配置文件的名称和路径,这也是为什么我们需要将Spring配置文件的信息写入Web.xml当中。
    因为DispathcherServlet封装的Spring工厂的创建只能通过读取XML文件的形式,所以无法迁移到纯注解的开发上。但是目前的SpringMVC是无法做到纯注解开发的,直到我们后边有了更高级的课程才能迁移到纯注解编程上去。

    2:控制SpringMVC的内部运行流程。
    内部运行流程是怎么流转的,这些相关的操作,必须等我们深入学习SpringMVC源码之后,才能会有更深入的了解。这里边只需要注意的是,他控制了SpringMVC的运行流程。

    2):SpringMVC的配置文件dispatcher.xml

    mvc:annotation-driven/作用:
    这块配置的主要作用就是:引入了SpringMVC的核心功能,主要引入了2个核心类型:RequestMappingHandlerMapping
    RequestMappingHandlerAdapter
    配置文件当中引入这个标签就是在SpringMVC项目中引入了这两个关键类。这两个类起到的作用
    RequestMappingHandlerMapping:实现了HandlerMapper接口,并将其诸注册到请求注册表当中。
    RequestMappingHandlerAdapter:实现了HandlerAdaper接口,主要作用就是处理请求适配器,他是专门处理请求的适配器,确定调用某个符合要求的控制器类中的具体服务的方法。
    所以在这,整个SpringMVC控制器的调用,都是交由这个Adapter来完成的,他会在N多个控制器当中找到那个符合要求的控制器,并且调用这个控制器当中的某个方法,对外提供服务。

    我们来验证我们以上的想法:
    首先我们将左边的任务栏调整为浮动模式:项目上右键—> view mode:floot修改为浮动模式,找到我们项目中依赖管理的地方,在找到我们webmvc的jar包
    打开下图这个文件之后,下面可以看到一组key_value这样的配置,前端的key是:http://www.springframework.org/schema/mvc这个含义就是说这一组标签都是所有核心配置文件当中mvc开头的标签都是由这个Schema来对应
    后续的Value是一个类,这个类专门用来处理这些个对标签的类,我们说一切皆对象,这些对象就是我们用来处理这些标签的对象。
    在这里插入图片描述

    package org.springframework.web.servlet.config;
    
    import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
    
    public class MvcNamespaceHandler extends NamespaceHandlerSupport {
        public MvcNamespaceHandler() {
        }
        public void init() {
            this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
            this.registerBeanDefinitionParser("default-servlet-handler", new DefaultServletHandlerBeanDefinitionParser());
            this.registerBeanDefinitionParser("interceptors", new InterceptorsBeanDefinitionParser());
            this.registerBeanDefinitionParser("resources", new ResourcesBeanDefinitionParser());
            this.registerBeanDefinitionParser("view-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("redirect-view-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("status-controller", new ViewControllerBeanDefinitionParser());
            this.registerBeanDefinitionParser("view-resolvers", new ViewResolversBeanDefinitionParser());
            this.registerBeanDefinitionParser("tiles-configurer", new TilesConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("freemarker-configurer", new FreeMarkerConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("groovy-configurer", new GroovyMarkupConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("script-template-configurer", new ScriptTemplateConfigurerBeanDefinitionParser());
            this.registerBeanDefinitionParser("cors", new CorsBeanDefinitionParser());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    打开这个类之后,我们看到了annotation-driven对应了一个新的类型。也就这样这个标签更具体的处理类是后边对应的这个。我们在进入到这个类之后,确实引入了我们上述的两个类型:

    package org.springframework.web.servlet.config;
    class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
        public static final String HANDLER_MAPPING_BEAN_NAME = RequestMappingHandlerMapping.class.getName();
        public static final String HANDLER_ADAPTER_BEAN_NAME = RequestMappingHandlerAdapter.class.getName();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    至此就证明了咱们上述表述的正确性。


    这个标签就不陌生了,他就是为了注解扫描。这里边需要注意的是什么:因为DispathcherServlet封装的Spring工厂的创建只能通过读取XML文件的形式,所以无法迁移到纯注解的开发上。这样就导致了,我们这里边开发方式是:Spring配置文件+基础注解的形式。

    基础注解: @Component,@Service,@Repository,@Controller,@Scope,@Transactional等
    高级注解: @Confiquration,@Bean,@ComponentScan等
    后续SpringMVC高级版的课程,会使用纯注解版开发,与SpringBoot的使用方式高度一致。

    第二章:编码开发

    一:思路分析

    作为SpringMVC来讲他的核心就是控制器。控制器在之前我们了解过Servlet,我们现在通过Servlet的开发推导出SringMVC的开发。

    我们编写一个类,这个类需要extends HttpServlet继承之后,我们重写其中的service方法,方法的参数时request和response。然后我们在其中进行接收请求参数、业务处理、页面跳转等操作。这就是我们需要编码的细节。
    在这里插入图片描述
    代码写完之后,我们需要在web.xml当中配置一个servlet标签:
    servlet-name:当中起一个名字,唯一就行。
    servlet-class:带包带类,实际上就是类的限定名称。
    与之对应的我们还需要配置一个servlet-mapping标签,作用就是对外暴露我们这个Servlet对应的URL。
    servlet-name:跟上边保持一致
    url-pattern:一个URL

    http://localhost:8989/basic/firstServlet
    这是一个请求的完成的URL,我们在地址栏当中输入这个路径之后,基于ip+端口+应用名。后边的/firstServlet找到对应的url-pattern,进而找到对应的servlet-name进而找到对应的servlet-class。这就是我们servlet开发的开发方式。

    对于SpringMVC来讲,他所提供的控制器就是为了替换原生Servlet的,他们在开发过程中主题思想是保持一致的。SpringMVC的控制器一定会简化现有的MVC的开发的。
    SpringMVC的控制器在开发过程当中,是不需要继承父类或者实现接口这样的要求,只需要在类上边添加一个@Controller注解(上述图右)注解可以起到接口这样约定性的作用,继承父类或者实现接口这样的方式被注解取代掉了。这就是二者在开发类上边的区别关系。
    在Servlet当中我们只能写Service方法,但是在SpringMVC当中对应的名字,他的方法名字是可以随便写的。对于SpringMVC的方法的返回值不再是void了,而是Spring就是跳转路径。

    作为SpringMVC来中的Controller来将他如何指定他的URL呢,只需要在方法上加一个注解@RequestMapping即可。这个注解当中的路径就是他对应的URI用户在通过地址栏访问的时候就是在方法上写的地址的内容。
    这个和Basic是一致的。举例来讲:Http:localhost:8989/spring-mvc1/firstController即可。

    基本开发流程:
    1:开发一个类在类上加Controller注解
    2:提供一个控制器方法。参数是:HttpServletRequest,HttpServletResponse,返回值是String的,同事加入@RequestMapping注解定义请求路径。
    3:在控制方法中,完成核心开发功能,把对应的JSP页面的路径作为返回值返回。

    二:SpringMVC程序编码

    在我们的IDEA当中我把相关的内容关掉。
    后端代码:

    @Controller
    public class FirstController {
        public FirstController() {
            System.out.println("FirstController.FirstController");
        }
        @RequestMapping("/first")
        //方位这个控制器方法的路径是first
        public String first(HttpServletRequest request, HttpServletResponse response){
            System.out.println("FirstController.first");
            //跳转到根下边的这个jsp
            return "/result.jsp";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    JSP代码

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        Result
    
    
       

    this is result jsp

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    浏览器访问地址:

    http://localhost:8989/basic/first
    
    • 1

    注意:必须要进行@Controller注解的扫描。

    三:控制器提供多个服务方法

    作为控制器来讲,Servlet当中是不允许一个控制器提供多个服务方法的。在Servlet当中一个控制器只能提供一个方法。这是因为在Servlet当中必须实现接口规定的service(HttpServletRequest,HttpServletResponse)方法,一个类中只能实现一次,所以一个类当中只能有一个服务方法。在Servlet想要提供服务就之能写Servlet接口提供的规定。所以,我们基于Servlet只能基于以下的代码结构:

    在这里插入图片描述
    作为SpringMVC的控制器一个类当红中可以提供多个对外服务的方法的。究其原因是因为SpringMVC控制器当中的服务方法对于方法名是没有任何要求的:

    @Controller
    public class FirstController {
        public FirstController() {
            System.out.println("FirstController.FirstController");
        }
        @RequestMapping("/first")
        public String first(HttpServletRequest request, HttpServletResponse response){
            System.out.println("FirstController.first");
            return "/result.jsp";
        }
    
        // http://localhost:8989/basic/suns/second
        @RequestMapping(value="suns/second")
        public String second(HttpServletRequest request,HttpServletResponse response){
            System.out.println("FirstController.second");
            return "/result.jsp";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    我们写Value等于这种形式没啥区别,如果注解当中只写一个属性,且属性为value,则value可省略。

    四:注意事项

    SpringMVC开发过程中习惯上把控制器称之为Controller,SpringMVC内部也把开发的控制器也叫做Handler因为后续我们查看源码的过程当中经常看到Handler…等等各种各样的说法。

    五:控制器创建次数

    作为Servlet来讲,他对应的控制器被创建的次数是几次呢?一中Servlet只会被Tomcat创建一次。请求过来之后,Tomcat只会创建一次这个对象。所以我们常说:Servlet是单实例的(注意这个不是单例设计模式)

    SpringMVC的控制器被Spring创建的次数是尊询Spring的规则,可以只创建一次,也可以创建多次。默认可以创建一次,也可以去创建多次。如果想创建多次,我们可以加一个@Scope注解来设定。如果是@Scope是prototype的话,那么一次请求就会对应创建一个Controller对象。

    默认SpringMVC的Controller只会被创建一次,存在线程安全的问题。如果这里边有成员变量,并且这里边成员变量是线程不安全的话,就会有问题。

    六:细节分析

    1:@RequestMapping注解

    该注解核心作用就是为控制器方法提供外部访问的URI路径。服务器就可以将用户URL当中的URL同注解当中的路径进行匹配来让客户访问对应的服务。这个工作是由RequestMappingHandlerMapping来处理的,对方法上添加这个注解的服务进行一一扫描,来进行服务注册。

    2:路径分隔符/可省略

    SpringMVC当中“/first”当中的/是可以省略的。如果是多级路径,第一个/是可以省略的。

    3:一个控制器方法上指定多个注解

    @Controller
    //@Scope("singleton")
    //@Scope("prototype")
    public class FirstController {
    
        public FirstController() {
            System.out.println("FirstController.FirstController");
        }
    
        //@RequestMapping("/first")
        //@RequestMapping("first")
        @RequestMapping(value = {"/first","/third"})
        public String first(HttpServletRequest request, HttpServletResponse response){
            System.out.println("FirstController.first");
            return "/result.jsp";
        }
    
        // http://localhost:8989/basic/suns/second
        @RequestMapping(value="suns/second")
        public String second(HttpServletRequest request,HttpServletResponse response){
            System.out.println("FirstController.second");
            return "/result.jsp";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4:类上的@RequestMapping

    可以在类上加注解,这就让URL上多加一个层级而已。
    http://localhost:8989/basid/user/addUser
    http://localhost:8989/basid/user/deteleUser

    @Controller
    @RequestMapping("/user")
    public class UserController {
    
        @RequestMapping("/addUser")
        public String addUser() {
            System.out.println("UserController.addUser");
            return "/result.jsp";
        }
        @RequestMapping("/deleteUser")
        public String deleteUser() {
            System.out.println("UserController.deleteUser");
            return "/result.jsp";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5:Controller使用@RequestMapping设计意图

    为什么SpringMVC设计的过程当中让我们在类上加这样的一个注解呢?
    为了统一服务,我们在使用的过程中,会把一组相关的操作放到同一个控制器当中。用户Controller负责用户的事,账户Controller负责账户的事。采用了这样的设计之后,用户的URL就会很规范,在访问的路径上也能体现出模块化。

  • 相关阅读:
    接入电商数据平台官方开放平台API接口获取商品实时信息数据,销量,评论,详情页演示
    c语言-手撕多级时间轮定时器(纯手写)
    前端路由中的meta、matched是什么?有哪些作用?
    威纶通触摸屏如何在报警的同时,显示出异常数据的当前值?
    【Flutter】【widget】Checkbox 和 CheckboxListTile 复选框快速学习一下
    1024 科学计数法
    如何写一份全面、易读的交互说明文档
    时间管理的本质,是少做事情
    红队攻防渗透技术实战流程:组件安全:Solr&Shiro&log4j
    【三维重建】MobileR2L:轻量化移动端三维重建(CVPR2023)
  • 原文地址:https://blog.csdn.net/Facial_Mask/article/details/127252302