• SringMVC中个常见的几个问题


    一、SpringMVC的底层工作流程

    在这里插入图片描述
    1、用户发送请求至前端控制器DispatcherServlet
    2、DispatcherServlet收到请求调用HandleMapping处理器映射器
    3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器及处理拦截器(如果有则生成)一并返回给DispatcherServlet
    4、DispatcherServlet调用HandlerAdapter处理器适配器
    5、HandlerAdapater经过适配器调用具体处理的Controller,也就后端处理器
    6、Controller执行完返回ModelAndView
    7、HandleAdapter将Controller执行结果ModelAndView返回给DispatcherServlet
    8、DispatcherServlet将ModelAndView传给ViewReslove视图解析器
    9、ViewReslover解析后返回具体的view
    10、DispatcherServlet根据view进行渲染视图(即将模型数据填充至视图中)
    11、DispatcherServlet响应用户

    二、SpringMVC这种的九大组件

    Handler:也就是处理器。他直接应对着MVC中的C,也就是Controller层。它的具体表现形式有很多,可以是类,也可以是方法。在Conntroller层中@RequestMapping标注的所有方法都可以看做是一个Handler,只要可以实际处理请求就可以是Handler

    1、HandlerMapping
    initHandlerMappings(context),处理器映射器,根据用户请求的资源url来查找Handler的,在SpringMVC中会有很多请求,每个请求都需要一个Handler处理,具体接收到一个请求之后使用哪个Handler进行,这里就是HandlerMapping需要做的事。
    可以理解为维护url到handle的一个映射

    2、HandlerAdapter
    initHandlerAdapters(context),适配器。因为SpringMVC中的Handler可以是任意形式的,只要能处理请求就OK,但是Servlet需要的处理方法结构确实固定的,都是以request和response为参数的方法,如何让固定的Servlet处理方法调用灵活的Handler来进行处理呢?这就是HandlerAdapter要做的事情

    Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人

    3、HandlerExceptionResolver
    initHandlerExceptionResolver(context),其他组件都是用来干活的,在干活的过程中难免会出现问题,出问题后怎么办呢?这就需要有一个专门的角色对异常情况进行处理,在SpringMVC中就是HandlerExceptionResolver。具体来说,此组件的作用就是根据异常设置ModelAndView,之后再交给render方法进行渲染。

    4、ViewResolver
    initViewResolver(context),ViewResolver用来将String类型的视图名和Locale解析为View类型的视图,view是用来渲染页面的,也就是将程序返回的参数填入模板里,生成html(也可能是其他类型)文件。这里就有两个关键问题:使用那个模板?用什么技术(规则)填入参数?这其实是ViewResolver主要做的工作。viewResolver需要找到渲染所有的模板和所用的技术(也就是视图的类型)进行渲染,具体的渲染过程则交由不同的视图自己完成

    5、ResquestToViewNameTranslator
    initResquestToViewNameTranslator(context),ViewResolver是根据ViewName查找view,但有的Handler处理完成后并没有设置view,也没有设置viewName,这是就需要从request中获取viewName了,如何从request中获取ViewName就是ResquestToViewNameTranslator需要做的事情了。ResquestToViewNameTranslator在SpringMVC容器里面只可以配置一个,所以所有request到viewName的转换规则都需要在一个Trandlator里面完成

    6、LocaleResolver
    initLocaleResolver(context),解析视图需要两个参数:一个是视图名,另一个是Locale。视图名是处理器返回的,Locale是从哪里来的呢?这就是LocaleResolver需要做的事情了。LocaleResolver用于从request中解析出Locale,Locale就是zh-cn之类,表示你一个区域,有了这个就可以对不同区域的用户显示不同的结果。SpringMVC主要有两个地方用到了Locale:一是VIewResolver视图解释的时候,二是利用到国际化资源或者主题的时候

    7、ThemeResolver
    initThemeResolver(context),用于解析主题。SpringMVC中一个主题对应一个properties文件,里面存放着跟当前主题相关的所有资源,如图片、css样式等。SpringMVC的主题也支持国际化,同一个主题不同区域也是可以显示不同的风格。SpringMVC中跟主题相关的类有ThemeResolver、ThemeSource和Theme。主题是通过一系列资源来具体体现的,要得到一个主题的资源,首先要得到资源的名称,这是ThemeResolver的工作,然后通过主题名称找到对应的主题(可以理解为一个配置)文件,这是ThemeSource的工作,最后从主题中获取资源就可以了。

    8、MultipartResolver
    initMultipartResolver(context),用于处理上传请求。处理方法是将普通的request包装成MultipartHttpRequest,后者可以直接调用getFile方法获取File,如果上传多个文件,还可以调用getFileMap得到FileName->File结构的Map。此组件中一共有三个方法,作用分别是:判断是不是上传请求、将request包装成MulitpartHttpServletRequest、处理完成后清理上传过程中产生的临时文件

    9、FlashMapManager
    initFlashMapManager(contect),用来管理FlashMap的。FalshMap主要用在redirect(重定向)中传递参数

    三、SpringMVC中的控制器是不是单例模式?如果是,如何保证线程安全?

    SpringMVC中的控制器是单例模式。
    如何保证线程安全?
    将控制器设置成无状态模式,不要携带数据,但是可以引用无状态的service和dao

    比如一下代码,有属性B,可以携带不同的数据,那么UserController就是有状态的。

    @Component
    public class UserController {
    	
    	@Autowired
    	private B b;
    	
    	public void test(){
    		System.out.println("==================");
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    若存在一个实例,多个线程操作的话,就会造成线程安全问题
    所有,不要B属性了,那么UserController就是无状态的,不管有多少个线程来操作,这个实例携带的数据不会发生变化,所有不会有线程安全问题。

    到这里,很多小伙伴可能就有疑问了。平时我们在写controller的时候,都会注入不同的service类,注入的service会不会影响userController的状态呢?前面说有属性就是有状态,有了service不就有属性了么,从而不就有状态了么?
    这里我们需要理解下,再往下面看,service也是无状态的,service中引用的dao也是无状态的。 而无状态的数据直接引用,最终就还是无状态的。

    四、转发和重定向

    类型 请求转发 请求重定向 定时刷新
    请求路径可以不写虚拟路径 需要些虚拟路径 需要些虚拟路径
    请求响应次数一次请求
    一次响应
    两次请求
    两次响应
    两次请求
    两次响应
    Request对象同一个request对象 两个request对象 两个request对象
    地址栏内容不会发生变化 会发生变化会发生变化
    资源跳转只能用于服务器内部的资源跳转, 并且只能是同一应用中的不同资源上进行跳转, 不可用在不同应用和不同服务器中的资源跳转 可以用于服务器内部的资源跳转, 也可以用于不同应用和不同服务器之间的资源跳转可以用于服务器内部的资源跳转, 也可以用于不同应用和不同服务器之间的资源跳转
    时间立即转发 立即跳转指定时间后跳转

    五、Cookie和session

    Session保存数据的原理:
    浏览器向服务器发送请求,将需要保存的数据带给服务器,服务器通过请求获取数据,接着去服务器内部检查有没有为当前浏览器服务的session,如果有直接拿过来用,如果没有,那就创建一个session对象为当前的浏览器服务,将数据保存在session内部。
    当浏览器再次访问服务器时,服务器可以找到为当前浏览器服务的session。从中取出数据, 通过这种方式也可以保存会话中产生的数据!
          由于session技术是将会话中产生的数据保存在服务器内部的session中, 每一个浏览器都会有各自的session, 因此也不会发生混乱!

    Cookie保存数据的原理:
    浏览器向服务器发送请求,请求中包含着需要保存的数据,服务器获取数据,通过Cookie响应头将数据再响应给浏览器,让浏览器自己保存。
    浏览器再次访问服务器时,会在请求中,通过Cookie请求头将上次保存的数据再带给服务器, 服务器通过Cookie头来获取数据, 通过这种方式可以保存会话中产生的数据!
          由于Cookies技术是将会话产生的数据保存在客户端,客户端各自保存各自的数据。再次访问服务器时会带着自己的数据, 每个客户端持有自己的数据, 因此就不会发生混乱了。

    Session和Cookie的区别和使用场景
    Session和cookie都是会话跟踪技术,cookie是客户端技术,session是服务器端技术。但是session的实现依赖于cookie,Session是基于一个特殊的名为JSESSIONID的cookie工作的。
    区别:
    session放在服务器,而cookie放在浏览器
    cookie不是很安全,别人可以通过分析本地的cookie进行cookie的欺诈,考虑到安全,我们用session
    session会在服务器保存一定的时间,也就是说,当访问增多的时候,会比较占用服务器的性能,如果将来考虑到服务器压力的时候,我们要用cookie。
    Cookie保存的数据不能超过4k,很多浏览器都限制一个站点最多保存20个cookie
    个人建议:
    要将个人信息保存到session当中
    其他的信息,如果需要保留我们放到cookie:购物车信息。

  • 相关阅读:
    数据库操作
    好用的WPF开源UI框架项目
    阿里云RDS 读写分离
    云原生之Kubernetes:17.详解Apiserver和RBAC
    golang 高阶函数
    数据结构:7、队列
    基于 Scriptable 从零开始美化iOS桌面(集合篇)
    孩子们的游戏(圆圈中最后剩下的数)(C++)
    家用摄像头选择
    2.运行时数据区概述及线程
  • 原文地址:https://blog.csdn.net/sxl123sxl/article/details/126004375