SpringMVC面试题
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
++++概述
什么是Spring MVC简单介绍下你对Spring MVC的理解
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架通过把模型-视图-控制器分离将web层进行职责解耦把复杂的web应用分成逻辑清晰的几部分简化开发减少出错方便组内开发人员之间的配合。
Spring MVC的优点
1可以支持各种视图技术,而不仅仅局限于JSP
2与Spring框架集成如IoC容器、AOP等
3清晰的角色分配前端控制器(dispatcherServlet) , 请求到处理器映射handlerMapping), 处理器适配器HandlerAdapter), 视图解析器ViewResolver。
4 支持各种请求资源的映射策略。
核心组件
Spring MVC的主要组件
1前端控制器 DispatcherServlet不需要程序员开发
作用接收请求、响应结果相当于转发器有了DispatcherServlet 就减少了其它组件之间的耦合度。
2处理器映射器HandlerMapping不需要程序员开发
作用根据请求的URL来查找Handler
3处理器适配器HandlerAdapter
注意在编写Handler的时候要按照HandlerAdapter要求的规则去编写这样适配器HandlerAdapter才可以正确的去执行Handler。
4处理器Handler需要程序员开发
5视图解析器 ViewResolver不需要程序员开发
作用进行视图的解析根据视图逻辑名解析成真正的视图view
6视图View需要程序员开发jsp
View是一个接口 它的实现类支持不同的视图类型jspfreemarkerpdf等等
什么是DispatcherServlet
Spring的MVC框架是围绕DispatcherServlet来设计的它用来处理所有的HTTP请求和响应。
什么是Spring MVC框架的控制器
控制器提供一个访问应用程序的行为此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层允许用户创建多种用途的控制器。
Spring MVC的控制器是不是单例模式,如果是,有什么问题,怎么解决
答是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。
工作原理
请描述Spring MVC的工作流程描述一下 DispatcherServlet 的工作流程
1用户发送请求至前端控制器DispatcherServlet
2 DispatcherServlet收到请求后调用HandlerMapping处理器映射器请求获取Handle
3处理器映射器根据请求url找到具体的处理器生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
4DispatcherServlet 调用 HandlerAdapter处理器适配器
5HandlerAdapter 经过适配调用 具体处理器(Handler也叫后端控制器)
6Handler执行完成返回ModelAndView
7HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet
8DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析
9ViewResolver解析后返回具体View
10DispatcherServlet对View进行渲染视图即将模型数据填充至视图中
11DispatcherServlet响应用户。
Springmvc完整执行流程动态资源
浏览器现将请求交给Tomcat服务器然后调用Tomcat服务器中的web.Xml文件配置把请求分派给中央调度器中央调度器判断请求能否处理能处理把请求交给映射器得到执行链对象带着执行链对象返回给中央调度器中央调度器在调用处理器适配器获取适配器对象后执行拦截器的preHandle方法判断方法返回值true/false为true请求可以被执行请求传递到处理器方法返回ModelAndView对象接着执行拦截器的postHandler方法调用processDispatchResult这个方法判断是否有异常有异常调用异常解析器处理异常然后执行视图解析器没有异常直接执行视图解析器通过视图解析器创建视图对象中央调度器调用视图的view.render()方法渲染方法
渲染的作用把模型Model中的数据填充到视图之中再结合应答对象做输出在视图渲染完成之后最后执行拦截器的afterCompletion方法视图处理完成也就是请求处理完成之后执行的方法
第一步发起请求到前端控制器(DispatcherServlet)
第二步前端控制器请求HandlerMapping查找 Handler 可以根据xml配置、注解进行查找
第三步处理器映射器HandlerMapping向前端控制器返回HandlerHandlerMapping会把请求映射为HandlerExecutionChain对象包含一个Handler处理器页面控制器对象多个HandlerInterceptor拦截器对象通过这种策略模式很容易添加新的映射策略
第四步前端控制器调用处理器适配器去执行Handler
第五步处理器适配器HandlerAdapter将会根据适配的结果去执行Handler
第六步Handler执行完成给适配器返回ModelAndView
第七步处理器适配器向前端控制器返回ModelAndView ModelAndView是springmvc框架的一个底层对象包括 Model和view
第八步前端控制器请求视图解析器去进行视图解析 根据逻辑视图名解析成真正的视图(jsp)通过这种策略很容易更换其他视图技术只需要更改视图解析器即可
第九步视图解析器向前端控制器返回View
第十步前端控制器进行视图渲染 视图渲染将模型数据(在ModelAndView对象中)填充到request域
第十一步前端控制器向用户响应结果
简析源码 dispatcherservlet继承关系
当一个请求request过来进入DispatcherServlet中里面有个方法 doDispatch方法 里面包含了核心流程 源码如下
然后往下看DispatcherServlet.java
mapperHandler是 HandlerExecutionChain 处理器调用链 类
HandlerExecutionChain 包含了 处理器对象 以及和处理器相关的 拦截器。
HandlerMapping 获取HandlerExecutionChina对象Handlermapping 定义了请求到处理器之间的映射 请求找到处理器 就需要用到HandlerMapping
这里将出现三种 情况
一、当请求的url路径不存在时没有对应的requestmapping注解方法
如果发的请求的映射是空的。返回的HandlerExecutionChain mappedHandler对象为空表示没有对应的映射 执行noHandlerFound方法
二、 当请求的路径url不存在时没有对应的requestmapping注解方法applicationcontext.xml中存在以下注解时
所以getHandler() 不会返回null因为 加上以上的配置,会调用SimpleUrlHandlerMapping 去寻找本地的静态资源,如css js 等 但是 同样的路径不存在 跳转到404页面
三、如果存在映射继续执行之后的代码:
通过Binner进行了
这个类 进行了 很多操作比如表单到实体Bean的赋值,数据的绑定。
下一步
底层调用了拦截器的PreHandle方法
继续执行DispatcherServlet.java
随后代码继续执行 调用了 拦截器的 PostHandler方法 然后调用 ProcessDispatchResult方法
继续执行
继续执行
渲染视图的render方法
为什么我们要使用字符串
继续往下找
进入render方法
由于是接口方法所以找到他的抽象类
找到renderMergedOutputModel
由于是抽象方法因此需要找到实现类
找到对应的视图解析器
进入InternalResourceView 往下找到
进入方法
获取转发器
最后
源码版本
发起请求到前端控制器(DispatcherServlet) 调用对应的 doDispath() 方法 该方法中有一个 getHandler()方法 返回一个处理器执行链对象处理器执行链中 有一个 handler对象和一个拦截器集合判断执行链对象为空 或者里面handler对象为空则调用noHandlerFound方法设置对应的HTTP状态码当请求路径不存在则返回 404如果存在映射根据处理器执行链中的handler 对象 在调用getHandlerAdapter()方法返回一个处理器适配器HandlerAdapater对象之后调用applyPreHandle方法底层也就是调用拦截器的preHandle方法返回true/fase如果返回true继续执行否则直接返回之后适配器对象调用handle()方法返回一个ModelAndView对象之后在调用applyPostHandle()方法底层也是调用拦截器的postHandle方法之后调用processDispatchResult方法这个方中有一个processHandlerException()方法返回一个ModelAndView视图对象然后继续执行有个渲染视图的render方法在这个方法中有一个视图对象利用ModelAndView对象调用getViewName()获得一个String类型视图名这个方法也规定了为什么使用String去作为key然后这个render方法中在调用视图解析器resolveViewName方法得到一个view视图对象这个视图对象在去调用render()方法这个方法是一个接口方法因此寻找对应的抽象类AbstractView重写的render方法这个方法中有一个renderMergedOutputModel()方法这个方法也是个接口方法寻找他实现类InternalResourceView这个类重写的renderMergedOutputModel这个方法中有一个exposeModelAsRequestAttributes()方法这个方法将对应的数据使用 request.setAttribute()方法放入请求域中接着使用getRequestDispatcher()方法获取一个转发器这个转发器最后利用请求转发forward()方法响应给用户。
MVC框架
MVC是什么MVC设计模式的好处有哪些
mvc是一种设计模式设计模式就是日常开发中编写代码的一种好的方法和经验的总结。模型model-视图view-控制器controller三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。
mvc设计模式的好处
1.分层设计实现了业务系统各个组件之间的解耦有利于业务系统的可扩展性可维护性。
2.有利于系统的并行开发提升开发效率。
常用注解
注解原理是什么
注解本质是一个继承了Annotation的特殊接口其具体实现类是Java运行时生成的动态代理类。我们通过反射获取注解时返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。
Spring MVC常用的注解有哪些
@RequestMapping用于处理请求 url 映射的注解可用于类或方法上。用于类上则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody注解实现接收http请求的json数据将json转换为java对象。
@ResponseBody注解实现将conreoller方法返回对象转化为json对象响应给客户。
@ModelAttribute
在方法定义上使用 @ModelAttribute 注解Spring MVC 在调用目标处理方法前会先逐个调用在方法级上标注了@ModelAttribute 的方法。
• 在方法的入参前使用 @ModelAttribute 注解
– 可以从隐含对象中获取隐含的模型数据中获取对象再将请求参数绑定到对象中再传入入参
– 将方法入参对象添加到模型中
如果是重定向到 jsp 页面则 jsp 页面不能写在 WEB-INF 目录中否则无法找到。
SpingMvc中的控制器的注解一般用哪个,有没有别的注解可以替代
答一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外一般不用别的注解代替。
@Controller注解的作用
在Spring MVC 中控制器Controller 负责处理由DispatcherServlet 分发的请求它把用户请求的数据经过业务处理层处理之后封装成一个Model 然后再把该Model 返回给对应的View 进行展示。在Spring MVC 中提供了一个非常简便的定义Controller 的方法你无需继承特定的类或实现特定的接口只需使用@Controller 标记一个类是Controller 然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象它们可以通过Controller 的方法参数灵活的获取到。
@Controller 用于标记在一个类上使用它标记的类就是一个Spring MVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类而使用**@RequestMapping 注解的方法才是真正处理请求的处理器**。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式
- 在Spring MVC 的配置文件中定义MyController 的bean 对象。
- 在Spring MVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。
@RequestMapping注解的作用
RequestMapping是一个用来处理请求地址映射的注解可用于类或方法上。用于类上表示类中的所有响应请求的方法都是以该地址作为父路径。
RequestMapping注解有六个属性下面我们把她分成三类进行说明下面有相应示例。
value method
value 指定请求的实际地址指定的地址可以是URI Template 模式后面将会说明
method 指定请求的method类型 GET、POST、PUT、DELETE等
consumesproduces
consumes 指定处理请求的提交内容类型Content-Type例如application/json, text/html;
produces: 指定返回的内容类型仅当request请求头中的(Accept)类型中包含该指定类型才返回
paramsheaders
params 指定request中必须包含某些参数值是才让该方法处理。
headers 指定request中必须包含某些指定的header值才能让该方法处理请求。
@ResponseBody注解的作用
作用 该注解用于将Controller的方法返回的对象通过适当的HttpMessageConverter转换为指定格式后写入到Response对象的body数据区。
使用时机返回的数据不是html标签的页面而是其他某种格式的数据时如json、xml等使用
@PathVariable和@RequestParam的区别
请求路径上有个id的变量值可以通过@PathVariable来获取 @RequestMapping(value = “/page/{id}”, method = RequestMethod.GET)
@RequestParam用来获得静态的URL请求入参 spring注解时action里用到。
Spring MVC怎么样设定重定向和转发的
1转发在返回值前面加"forward:“譬如"forward:user.do?name=method4”
2重定向在返回值前面加"redirect:“譬如"redirect:http://www.baidu.com”
Spring MVC怎么和AJAX相互调用的
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下
1加入Jackson.jar
2在配置文件中配置json的映射
3在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。
如何解决POST请求中文乱码问题GET的又如何处理呢
1解决post请求乱码问题
在web.xml中配置一个CharacterEncodingFilter过滤器设置成utf-8
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1234567891011121314
2get请求中文参数出现乱码解决方法有两个
①修改tomcat配置文件添加编码与工程编码一致如下
<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
1
②另外一种方法对参数进行重新编码
String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”)
ISO8859-1是tomcat默认编码需要将tomcat编码后的内容按utf-8编码。
Spring MVC的异常处理
答可以将异常抛给Spring框架由Spring框架来处理我们只需要配置简单的异常处理器在异常处理器中添视图页面即可。
如果在拦截请求中我想拦截get方式提交的方法,怎么配置
答可以在@RequestMapping注解里面加上method=RequestMethod.GET。
怎样在方法里面得到Request,或者Session
答直接在方法的形参中声明request,Spring MVC就自动把request对象传入。
如果想在拦截的方法里面得到从前台传入的参数,怎么得到
答直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。
如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象
答直接在方法中声明这个对象,Spring MVC就自动会把属性赋值到这个对象里面。
Spring MVC中函数的返回值是什么
答返回值可以有很多类型,有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的但一般用String比较好。
Spring MVC用什么对象从后台向前台传递数据的
答通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表达式拿到。
Spring MVC里面拦截器是怎么写的
有两种写法,一种是实现HandlerInterceptor接口另外一种是继承适配器类接着在接口方法当中实现处理逻辑然后在Spring MVC的配置文件中配置拦截器即可
<!-- 配置Spring MVC的拦截器 -->
<mvc:interceptors>
<!-- 配置一个拦截器的Bean就可以了 默认是对所有请求都拦截 -->
<bean id="myInterceptor" class="com.zwp.action.MyHandlerInterceptor"></bean>
<!-- 只针对部分请求拦截 -->
<mvc:interceptor>
<mvc:mapping path="/modelMap.do" />
<bean class="com.zwp.action.MyHandlerInterceptorAdapter" />
</mvc:interceptor>
</mvc:interceptors>
介绍一下 WebApplicationContext
WebApplicationContext 继承了ApplicationContext 并增加了一些WEB应用必备的特有功能它不同于一般的ApplicationContext 因为它能处理主题并找到被关联的servlet。
标准的 HTTP 请求报头
拦截器的作用以及与过滤器的区别
Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter用于对处理器进行预处理和后处理。
用户可以自己定义一些拦截器来实现特定的功能。
谈到拦截器还要向大家提一个词——拦截器链Interceptor Chain。拦截器链就是将拦截器按一定的顺
序联结成一条链。在访问被拦截的方法或字段时拦截器链中的拦截器就会按其之前定义的顺序被调用。
说到这里可能大家脑海中有了一个疑问这不是我们之前学的过滤器吗是的它和过滤器是有几分相似但
是也有区别接下来我们就来说说他们的区别
过滤器是 servlet 规范中的一部分任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了**/***之后可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法如果访问的是 jsphtml,css,image 或者 js 是不会进行拦
截的。
它也是 AOP 思想的具体应用。
我们要想自定义拦截器 要求必须实现HandlerInterceptor 接口。
区别
①拦截器是基于java的反射机制的而过滤器是基于函数的回调。
②拦截器不依赖于servlet容器而过滤器依赖于servlet容器。
③拦截器只对action请求起作用而过滤器则可以对几乎所有的请求起作用。
④拦截器可以访问action上下文、值、栈里面的对象而过滤器不可以。
⑤在action的生命周期中拦截器可以多次被调用而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean而过滤器不行这点很重要在拦截器里注入一个service可以调用业务逻辑。
拦截器与过滤器触发时机不一样
过滤器是在请求进入容器后但请求进入servlet之前进行预处理的。请求结束返回也是是在servlet处理完后返回给前端之前。
过滤器包裹servletservlet包裹住拦截器
preHandle
/**
* 如何调用
* 按拦截器定义顺序调用
* 何时调用
* 只要配置了都会调用
* 有什么用
* 如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器或者是业务处理器去
* 进行处理则返回 true。
* 如果程序员决定不需要再调用其他的组件去处理请求则返回 false。
*/
postHandle():
/**
* 如何调用
* 按拦截器定义逆序调用
* 何时调用
* 在拦截器链内所有拦截器返成功调用
* 有什么用
* 在业务处理器处理完请求后但是 DispatcherServlet 向客户端返回响应前被调用
* 在该方法中对用户请求 request 进行处理。
*/
afterCompletion():
/**
* 如何调用
* 按拦截器定义逆序调用
* 何时调用
* 只有 preHandle 返回 true 才调用
* 有什么用
* 在 DispatcherServlet 完全处理完请求后被调用
* 可以在该方法中进行一些资源清理的操作。
*/
四、使用场景
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter用于对处理器进行预处理和后处理。
1、日志记录记录请求信息的日志以便进行信息监控、信息统计、计算PVPage View等。
2、权限检查如登录检测进入处理器检测检测是否登录如果没有直接返回到登录页面
3、性能监控有时候系统在某段时间莫名其妙的慢可以通过拦截器在进入处理器之前记录开始时间在处理完后记录结束时间从而得到该请求的处理时间如果有反向代理如apache可以自动记录
4、通用行为读取cookie得到用户信息并将用户对象放入请求从而方便后续流程使用还有如提取Locale、Theme信息等只要是多个处理器都需要的即可使用拦截器实现。
5、OpenSessionInView如hibernate在进入处理器打开Session在完成后关闭Session。