SpringMVC架构原理解析

SpringMVC架构:
MVC
Spring MVC 的精髓就是她核心的执行流程~

接下来,通过整合起来的代码,解读一个个配置文件~

1.web.xml

	<filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

filter-name:当前节点的名称

filter-class:字符集编码格式的一个过滤器,用来避免乱码

filter-mapping:帮助我们做请求匹配 ,"/*"表示所有请求,意思就是所有的请求都要找这个名为encodingFilter过滤器,就可以找到上面的filter了,最终做的事情就是把所有的请求都转换为utf-8 的编码格式

为什么要这样做?

一般我们写servlet 的时候,每一个servlet的都要先写两句话:

		response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");

说白了就是把所有的请求和响应都转化为utf-8的编码格式,这个操作所有的servlet都要做,现在我们呢再web.xml中统一进行了配置,意味着不用在代码中每次都写这两句话了~

	<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

context-param取代了:

 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

由于配置spring的地方在web层中,所以她和本地的main方法有一定的区别,因为在本地有对象调对象,有方法调方法,自己写了什么要写什么自己很清楚,但是在web层,对象由tomcat创建,方法也是tomcat来调用的,所以她需要明确的时时刻刻的知道Spring中发生了什么变化,所以需要配置监听器listener

这两个东西配合起来tomcat才能帮我们管理spring

	<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

这个一看不就是servlet嘛~

这个就是用来配置springMVC的前端控制器

DispatcherServlet:之前我们有一个请求就需要对应一个处理这个请求的servlet ,现在SpringMVC做了一件很牛的事情:她全局只有一个servlet,所有的请求都往这一个servlet发,然后再从这个servlet中往出分发,这就是这个前端控制器的作用~

原理

为什么要用servlet?

没有servlet前端和后台的代码就无法交互了,就是一个桥梁,为什么要有多个servlet,因为我们有多个请求,一个请求对应一个servlet,就意味着一个请求有一种处理方式,但是spring不这样认为,spring提出,一个请求对应一种处理方式肯定没问题,但是处理请求不一定要放在servlet中啊,或者说处理请求就不应该放在servlet中,这是后端代码的事情~

发送请求,接收请求是servlet,但是处理请求就不一定要用servlet了啊,因为请求servlet已经接上了,接上之后,可不可以用另外一个东西处理请求,servlet只要把数据给到他不就好了,servlet只做一个中转站,只需要把数据拿上,然后传到处理请求的地方,处理请求的地方拿到数据就可以进行处理了,servlet只是扮演了一个搬运工的角色。

Spring做了一件很牛的事情,就是所有的请求都往一个servlet中发,因为我们可以发现一件事情,就是只要把请求发到servlet中,其实就已经到后台了,那么servlet再怎么跟别的类交互,就不受前端后台这个跨度的影响了,所以,所有的请求都往一个servlet中发, 然后这一个servlet,再往你自己创建的类里面分发,因为请求只有servlet可以处理,servlet拿到的是数据,所以servlet分发的是数据,只要把数据给了后台处理就行了!

而对于后台代码来讲,不行啊~你把数据给了我,我不知道这个请求是谁鸭,刚刚不是提到对应的请求有对应的处理嘛。现在再来讲,请求是什么?servlet不是可以截获到你请求的路径嘛,之前玩servlet的时候,最后一个"/"后面的就是你的请求,那OK,servlet直接把这个请求截获,不就可以进行匹配了?这其中只有两件事,第一件事:DispatcherServlet她必须知道你要做的事情是什么,因为这个servlet中有请求,她要知道你要做的是什么,你是处理哪个请求的方法,所以DispatcherServlet需要知道的是你要处理哪个请求,第二件事:DispatcherServlet要做数据的抽取和封装,她要从请求中把数据拿出来,拿出来之后,她还能进行格式转换,因为前端传到后后台的数据全都是String类型的,但是后台的数据类型又有很多的区分,都是String类型的肯定是不行的,对后台很不友好,DispatcherServlet要做的就是,拿到数据之后,转换为它本身的数据类型,其他的就可以交给后台处理了。

所以,DispatcherServlet的作用就是,接收请求,剥离数据,转换数据(SpringMVC的内置转换器)转换为对应的类型,分发请求到后台处理对应请求的方法上去,她前期的工作就结束了,后台拿到请求处理完数据是有返回值的,这个返回值是要返回前端页面的,但是无法直接传给前端,这时候DispatcherServlet就又出来工作了,你把数据返回给DispatcherServlet,DispatcherServlet可以和前端页面进行交互啊,所以后台把结果返回给DispatcherServlet,然后DispatcherServlet把结果送到前端页面上去。

后台业务产生的结果肯定是不一样的所以给DispatcherServlet返回一个String或者int她不认识,因为这是后台业务类型的东西,无法公用,而DispatcherServlet工作的时候只能处理公用的东西,返回个String它是不公用的,为什么?因为换个业务返回值不一样了,这个String什么都无法代表。

这时候,Spring又想了个办法,她自己封装了一个类:ModelAndView,Model:指的是模型层(业务层+dao),View:视图。所以你给DispatcherServlet返回的数据,DispatcherServlet要两部分,第一部分,Model,就是dao,业务层处理完返回的数据,第二部分,做完数据处理,有了返回值之后,你要返回哪个页面,要给一个View 。

DispatcherServlet是一个中间人,对于这个请求处理完要去哪个页面是我们根据自己的业务做决定的,所以需要告诉DispatcherServlet你要去哪个页面,你还得告诉DispatcherServlet产生了哪些数据,所以Spring把这两个东西封装成了Model(只有数据),View(只有页面),ModelAndView(两个都有)

这就是DispatcherServlet的所有工作,当你把ModelAndView给了DispatcherServlet后,你的工作就结束了。

SpringMVC也需要配置,所以在param-value中指定了SpringMVC配置文件的路径。servlet-mapping中的url-pattern,这个"/"表示所有的请求都有走这个servlet。所有的SpringMVC的玩法都基于DispatcherServlet。

2.spring-mvc.xml

 	<!--启动SpringMVC注解驱动-->
    <mvc:annotation-driven/>
    <!--扫描包-->
    <context:component-scan base-package="com.shy.controller"/>
    <!--静态资源过滤-->
    <mvc:resources mapping="/statics/**" location="/statics/" />

不做静态资源过滤,DispatcherServlet不认识是啥,会直接拦下扔到一边去。

所以加上静态资源过滤表示,这个文件夹下的东西别动。

	<!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

ViewResolver:视图解析器,理解你View中写的是什么东西,把你写的View和前端页面进行匹配,说白了就是,她把你写的东西转换为页面了。因为她要去找页面。

Adapter:适配器,Handler:控制器

全局异常处理

	<!-- 全局异常处理,出现未处理的异常统统会到这里来,error表示页面名字 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" >
		<property name="exceptionMappings">
			<props>
				<prop key="java.lang.RuntimeException">error</prop>
			</props>
		</property>
	</bean>

key表示出现什么异常的时候去什么页面,就算出错也不会暴露源代码

数据库配置,和Mybatis的配置就不说了,之前都有发过~

行了,就到这吧~

小知识点

1.@RequestMapping("/allUser"),用来标记当前方法可以处理什么请求,在类上标记的话是用来分包的。

2.真正的springMVC的方法要做返回值,通常是String类型的,String类型返回的是View对象,写的是String,但是到了DispatcherServlet中会把它包装成一个View对象,这个String的值就是逻辑视图名,所以你返回一个逻辑视图名他就会自动去找这个页面。这是真正常用的用法,想要存放信息,你可以在参数列表中接收一个Model对象,这个Model对象是SpringMVC给你提供的,当它发现方法参数中又Model,View,ModelAndView对象的时候,它会帮助你自动提供,可以直接用,你可以把它当作request用。

@RequestMapping("/allUser")
public String list(Model model){}

3.前端页面可以接收一个键值对,这个键值对并不是从前端页面接收过来的而是跟刚刚的Model是一个效果

@RequestMapping("/allUser")
public String list(Map<String,String> map){}

从页面传过来的东西只有值,没有键,这个键值对也可以当request用,放到map中的东西就会进入request范围内,提示代码的扩展性和移植性可以用这个。

4.真正在实际开发中,后台要传给前端的是json字符串,json对象,这样前端才能解析

5.@ResponseBody,直接把当前信息返回到页面上,不要做包装,为了让方法返回异步请求,返回json对象

6.@RestController=@ResponseBody+@Controller

7.前端发出的请求是异步的,所以后端做出的也是异步响应

8.controller层不要写业务,只返回json字符串

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

用法:JSON.toJSONString()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值