SpringMVC面试题
Spring MVC 运行流程
第一步:发起请求到前端控制器(DispatcherServlet
)
第二步:前端控制器请求HandlerMapping
查找处理器Handler
( 可以根据xml配置、注解进行查找)
第三步:处理器映射器HandlerMapping
向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
(ModelAndView
是Springmvc
框架的一个底层对象,包括Model
和view
)
第八步:前端控制器请求视图解析器(ViewResolver
)去进行视图解析(根据逻辑视图名称进行查找,生成视图对象)
第九步:视图解析器向前端控制器返回视图对象View
第十步:前端控制器进行视图渲染( 视图渲染将模型数据(在ModelAndView对象中)填充到request域)
第十一步:前端控制器向用户响应结果
说说对Spring MVC的理解?
MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的Web层的开发,并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service层(处理业务)、Dao层(数据库操作)、Entity层(实体类)、Controller层(控制层,返回数据给前台页面)。
Springmvc的优点
- 可以支持各种视图技术,而不仅仅局限于JSP;
- 与Spring框架集成(如
IoC
容器、AOP
等); - 清晰的角色分配:前端控制器(
dispatcherServlet
) , 请求到处理器映射(handlerMapping
), 处理器适配器(HandlerAdapter
), 视图解析器(ViewResolver
)。 - 支持各种请求资源的映射策略。
什么是MVC模式?
MVC的全名是Model View Controller
,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。
V 即View视图,是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操纵的方式。
M 即model模型,是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
C 即controller控制器,是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。
Spring MVC的主要组件?
- 前端控制器
DispatcherServlet
:其作用是接收用户请求,然后给用户反馈结果。它的作用相当于一个转发器或中央处理器,控制整个流程的执行,对各个组件进行统一调度,以降低组件之间的耦合性,有利于组件之间的拓展。 - 处理器映射器
HandlerMapping
:其作用是根据请求的URL路径,通过注解或者XML配置,寻找匹配的处理器信息。 - 处理器适配器
HandlerAdapter
:其作用是根据映射器处理器找到的处理器信息,按照特定规则执行相关的处理器(Handler)。 - 处理器
Handler
:其作用是执行相关的请求处理逻辑,并返回相应的数据和视图信息,将其封装至ModelAndView对象中。 - 视图解析器
ViewResolver
:其作用是进行解析操作,通过ModelAndView对象中的View信息将逻辑视图名解析成真正的视图View(如通过一个JSP路径返回一个真正的JSP页面)。 - 视图**
View
:View**是一个接口,实现类支持不同的View类型(JSP、FreeMarker、Excel等)。
Servlet原理?
过滤器跟拦截器的区别?
过滤器:
Servlet中的过滤器Filter是实现了javax.servlet.Filter
接口的服务器端程序,主要的用途是过滤字符编码、做一些业务逻辑判断等。其工作原理是,只要你在web.xml文件配置好要拦截的客户端请求,它都会帮你拦截到请求,此时你就可以对请求或响应(Request、Response)统一设置编码,简化操作;同时还可以进行逻辑判断,如用户是否已经登录、有没有权限访问该页面等等工作,它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关的请求,只有当你的web应用停止或重新部署的时候才能销毁。
拦截器:
拦截器是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
拦截器不是在web.xml配置的,比如struts在struts.xml配置,而springMVC在Spring与springMVC整合的配置文件中配置。在springmvc中,定义拦截器要实现HandlerInterceptor接口,并实现该接口中提供的三个方法。
拦截器是基于Java的反射机制的,而过滤器是基于函数回调
过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
拦截器可以访问action上下文、值栈里的对象,而过滤器不能
在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
Filter需要在web.xml中配置,依赖于Servlet
Interceptor需要在SpringMVC中配置,依赖于框架
Filter的执行顺序在Interceptor之前。Filter包裹servlet,servlet包裹Interceptor
Springmvc 中如何解决 GET | POST请求中文乱码问题?
GET方式:
在服务器端配置URL编码格式:修改tomcat的配置文件server.xml:
只需增加 URIEncoding=“UTF-8” 这一句,然后重启tomcat即可。
<ConnectorURIEncoding="UTF-8"
port="8080" maxHttpHeaderSize="8192" maxThreads="150"
minSpareThreads="25" maxSpareThreads="75"connectionTimeout="20000"
disableUploadTimeout="true" URIEncoding="UTF-8"/>
POST方式:
SpringMVC默认提供一个解决post请求乱码的过滤器,在web.xml中配置即可(要注意的是它的位置一定要是第一个执行的过滤器):
<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>
该过滤器要做的其实就是强制为所有请求和响应设置编码格式:
request.setCharacterEncoding(“utf-8”);
response.setCharacterEncoding(“utf-8”);
Springmvc 如何做异常处理 ?
可以将异常抛给Spring框架,由Spring框架来处理;自定义实现spring的全局异常解析器HandlerExceptionResolver
,在异常处理器中添视图页面即可。
若与SpringBoot搭配使用,建议使用SpringBoot提供的全局异常处理:@ControllerAdvise
SpringMVC 常用注解都有哪些?
@requestMapping
:用于请求 url 映射。
@RequestBody
: 注解实现接收 http 请求的 json 数据,将 json 数据转换为 java 对象。
@ResponseBody
:注解实现将 controller 方法返回对象转化为 json 响应给客户。
@Conntroller
:控制器的注解,表示是表现层,不能用用别的注解代替。
@Valid
:标志参数被Hibernate-Validator校验框架
校验。
@PathVariable
:用于接收uri地址传过来的参数,Url中可以通过一个或多个{Xxx}占位符映射,通过@PathVariable可以绑定占位符参数到方法参数中,在RestFul接口风格中经常使用。 例如:请求URL:http://localhost/user/21/张三/query (Long类型可以根据需求改变为String或int,SpringMVC会自动做转换)
@RequestMapping("/user/{userId}/{userName}/query")
public User query(@PathVariable("userId") Long userId, @PathVariable("userName") String userName){
...
}
@RequestParam
:用于将请求参数映射到控制器方法的形参上,有如下三个属性
- value:参数名。
- required:是否必需,默认为true,表示请求参数中必须包含该参数,如果不包含抛出异常。
- defaultValue:默认参数值,如果设置了该值自动将required设置为false,如果参数中没有包含该参数则使用默认值。 示例:
@RequestParam(value = "pageNum”, required = false, defaultValue = "1")
如何开启注解处理器和适配器?
在配置文件中(一般命名为springmvc.xml )通过开启 <mvc:annotation-driven>
来实现注解处理器和适配器的开启。
Springmvc 的控制器是不是单例模式,如果是,有什么问题,怎么解决?
是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段;或者使用ThreadLocal
。
Springmvc 和struts2的区别有哪些?
Springmvc的入口是一个servlet,即前端控制器(DispatchServlet
),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter
)。
Springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
Springmvc 中对于文件的上传有哪些需要注意
- 在页面form中提交enctype="multipart/form-data"的数据时,需要springmvc对multipart类型的数据进行解析。
- 在springmvc.xml中配置multipart类型解析器。
- 方法中使用:MultipartFile attach (单个文件上传) 或者 MultipartFile[] attachs (多个文件上传)
Springmvc 中拦截器如何使用?
定义拦截器
实现HandlerInterceptor
接口。接口中提供三个方法:
preHandle()
:进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行postHandle()
:进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图afterCompletion()
:执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理
拦截器配置:
- 针对HandlerMapping配置(不推荐):springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。(一般不推荐使用)
- 类似全局的拦截器:springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。
<!-- 写法参考 -->
<mvc:interceptors>
<!-- 可配置多个。下面的例子只针对部分请求拦截。 -->
<mvc:interceptor>
<mvc:mapping path="/modelMap.do" />
<bean class="com.et.action.MyHandlerInterceptorAdapter"/>
</mvc:interceptor>
<mvc:interceptors>
- 0很棒
- 0不错
- 0一般
- 0???