TARGET DECK: SpringMVC

1 概述

1.1 MVC 概念和好处

MVC 是一种 Web 开发的设计模式。这种模式将 Web 开发分为模型(model)、视图(view)、控制器(controller)共三层架构。这样可以将前端页面的展现与后端业务数据处理进行分离。
好处:分层设计,有利于业务系统各个组件解耦合,提高系统的可扩展性;有利于系统的并行开发,提高开发效率。

1.2 SpringMVC 概念

SpringMVC 是一个基于 Java 的实现了 MVC 设计模式的轻量级 Web 框架,通过把模型-视图-控制器分离,将 web 层的职责解耦,把复杂的 web 应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

1.3 SpringMVC 优点

(1)可以支持各种视图技术, 而不仅仅局限于 JSP;
(2)与 Spring 框架集成(如 IoC 容器、AOP 等);
(3)清晰的角色分配:前端控制器 (dispatcherServlet) , 请求处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。
(4)支持各种请求资源的映射策略。

1.4 SpringMVC 的主要组件

DispatcherServlet:中央调度器,也称前端控制器,在 MVC 架构中相当于 C,即控制层,它是整个流程的控制中心,接收请求、响应结果,相当于转发器。中央调度器的存在降低了组件之间的耦合性,系统扩展性提高,由框架实现。
HandlerMapping:处理器映射器,负责根据用户请求 url 找到要执行的 Handler,springmvc 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。由框架实现。
Handler(需要程序员开发具体的 Controller):处理器,Handler 是继 DispatcherServlet 前端控制器的后端控制器,在 DispatcherServlet 的控制下对具体的用户请求进行处理。由于 Handler 涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发。
HandlerAdapter:处理器适配器,通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。由框架实现。
ViewResolver:视图解析器,View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。由框架实现。
View(需要程序员开发 jsp 等页面):视图,springmvc 框架提供了很多的 View 视图类型的支持,包括:jsp、jstlView、freemarkerView、pdfView 等。一般需要我们根据业务需求开发具体的页面。

1.5 SpringMVC 的工作流程

(DispatcherServlet 的工作流程)

Spring MVC 执行流程

  1. 用户在浏览器提交请求会到前端控制器 DispatcherServlet 进行处理。
  2. 前端控制器 DispatcherServlet 收到请求后,将请求转给处理器映射器 HandlerMapping。
  3. 处理器映射器 HandlerMapping 根据 request 请求的 URL 等信息查找能够进行处理的 Handler,以及相关拦截器 interceptor,并构造 HandlerExecutionChain 执行链,然后将构造好的 HandlerExecutionChain 执行链对象返回给前端控制器 DispatcherServlet,执行链包含一个处理器对象和一或多个拦截器。
  4. 前端控制器 DispatcherServlet 根据处理器执行链的处理器,能够找到其对应的处理器适配器 HandlerAdapter;
  5. 处理器适配器 HandlerAdapter 调用相应的处理器 Handler,即让我们写的具体的 Controller 方法执行。
  6. Controller 处理完后返回 ModelAndView 给 HandlerAdapter(ModelAndView 表示 SpringMVC 的封装对象,将 model 和 view 封装在一起)。
  7. 处理器适配器 HandlerAdapter 将 Controller 执行结果 ModelAndView 返回给前端控制器 DispatcherServlet。
  8. 前端控制器 DispatcherServlet 调用视图解析器 ViewReslover 处理 ModelAndView。
  9. 视图解析器 ViewReslover 解析后根据逻辑视图名解析成物理视图名即具体的页面地址,生成并返回具体对象 View(springmvc 封装对象,是一个接口)。
  10. 前端控制器 DispatcherServlet 根据对象 View 进行视图渲染(即将模型数据 model 填充至视图中)。
  11. 最后前端控制器 DispatcherServlet 向用户返回响应,至此就全部完成了。

1.6 SpringMVC 的控制器是不是单例模式, 如果是, 有什么问题, 怎么解决?

答:是单例模式, 所以在多线程访问的时候有线程安全问题, 不要用同步, 会影响性能的, 解决方案是在控制器里面不能写字段。

2 常用注解

2.1 注解原理是什么

注解本质是一个继承了 Annotation 的特殊接口,其具体实现类是 Java 运行时生成的动态代理类。我们通过反射获取注解时,返回的是 Java 运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用 AnnotationInvocationHandler 的 invoke 方法。该方法会从 memberValues 这个 Map 中索引出对应的值。而 memberValues 的来源是 Java 常量池。

2.2 SpringMVC 常用的注解有哪些?

@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收 http 请求的 json 数据,将 json 转换为 java 对象。
@ResponseBody:注解实现将 conreoller 方法返回对象转化为 json 对象响应给客户。
@Controller:标志控制器
@RestController:@ResponseBody + @Controller
@GetMapping…

2.3 @Controller 注解的作用

在 SpringMVC 中,控制器 Controller 负责处理由 DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个 Model ,然后再把该 Model 返回给对应的 View 进行展示。在 SpringMVC 中提供了一个非常简便的定义 Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是 Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义 URL 请求和 Controller 方法之间的映射,这样的 Controller 就能被外界访问到。此外 Controller 不会直接依赖于 HttpServletRequest 和 HttpServletResponse 等 HttpServlet 对象,它们可以通过 Controller 的方法参数灵活的获取到。

@Controller 用于标记在一个类上,使用它标记的类就是一个 SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是 SpringMVC 的一个控制器类,因为这个时候 Spring 还不认识它。那么要如何做 Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给 Spring 来管理。有两种方式:

  • 在 SpringMVC 的配置文件中定义 MyController 的 bean 对象。
  • 在 SpringMVC 的配置文件中告诉 Spring 该到哪里去找标记为@Controller 的 Controller 控制器。

2.4 @RequestMapping 注解的作用

RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

Value: 指定请求的实际地址,指定的地址可以是 URI Template 模式;
Method: 指定请求的 method 类型, GET、POST、PUT、DELETE 等;
Consumes: 指定处理请求的提交内容类型(Content-Type),例如 application/json, text/html;
Produces: 指定返回的内容类型,仅当 request 请求头中的 (Accept) 类型中包含该指定类型才返回;
Params: 指定 request 中必须包含某些参数值是,才让该方法处理。
Headers: 指定 request 中必须包含某些指定的 header 值,才能让该方法处理请求。

2.5 @ResponseBody 注解的作用

作用: 该注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。
使用时机:返回的数据不是 html 标签的页面,而是其他某种格式的数据时(如 json、xml 等)使用;

2.6 @PathVariable 和 @RequestParam 的区别

@PathVariable 从 URI 中获取参数。请求路径上有个 id 的变量值,可以通过@PathVariable 来获取 @RequestMapping (value = “/page/{id}”, method = RequestMethod. GET)

@RequestParam 从请求携带的参数中获取。

3 进阶

3.1 SpringMVC 怎么样设定重定向和转发的?

(1)转发:在返回值前面加”forward:“,譬如”forward:user.do?name=method4”
(2)重定向:在返回值前面加”redirect:“,譬如”redirect :http: //www.baidu.com

3.2 SpringMVC 返回 Json 怎么设置?

可以使用@ResponseBody 注解,或者使用包含(@ResponseBody 注解的@Restcontroller 注解。当然,还是需要配合相应的支持 JSON 格式化的 HttpMessageConverter 实现类。例如,Spring MVC 默认使用 MappingJackson2HttpMessageConverter。

3.3 SpringMVC 怎么和 AJAX 相互调用的?

通过 Jackson 框架就可以把 Java 里面的对象直接转化成 Js 可以识别的 Json 对象。具体步骤如下 :
(1)加入 Jackson.jar
(2)在配置文件中配置 json 的映射
(3)在接受 Ajax 方法里面可以直接返回 Object, List 等, 但方法前面要加上@ResponseBody 注解。

3.4 POST、GET 请求中文乱码问题

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>
  • 方案二:SprintBoot 在 application.yml 中配置:
server:
  servlet:
    encoding:
      charset: UTF-8

get 请求中文参数出现乱码

  • 修改 tomcat 配置文件添加编码与工程编码一致,如下:
 <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
  • 另外一种方法对参数进行重新编码:
String userName = new String (request. GetParamter ("userName"). GetBytes ("ISO8859-1"),"utf-8")

ISO8859-1 是 tomcat 默认编码,需要将 tomcat 编码后的内容按 utf-8 编码。

3.5 SpringMVC 的异常处理?

答:可以将异常抛给 Spring 框架,由 Spring 框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。

3.6 如果在拦截请求中,我想拦截 get 方式提交的方法,怎么配置

答:可以在@RequestMapping 注解里面加上 method=RequestMethod.GET。

3.7 怎样在方法里面得到 Request,或者 Session?

答:直接在方法的形参中声明 request,SpringMVC 就自动把 request 对象传入。

3.8 拦截方法获得前台传入数据,怎么处理?

答:直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。

3.9 函数有多个参数传入 & 属于一个对象的,怎么处理?

答:直接在方法中声明这个对象,SpringMVC 就自动会把属性赋值到这个对象里面。

3.10 函数的返回值是什么?

答:返回值可以有很多类型,有 String, ModelAndView。ModelAndView 类把视图和数据都合并的一起的,但一般用 String 比较好。

3.11 从后台向前台传递数据的,怎么做?

答:通过 ModelMap 对象,可以在这个对象里面调用 put 方法,把对象加到里面,前台就可以通过 el 表达式拿到。

3.12 怎么样把 ModelMap 里面的数据放入 Session 里面?

答:可以在类上面加上 @SessionAttributes 注解,里面包含的字符串就是要放入 session 里面的 key。

3.13 拦截器的实现

SpringMVC 拦截器

拦截器必须实现 org.springframework.web.servlet 包的 HandlerInterceptor。此接口定义了三种方法:

  • preHandle:在执行实际处理程序之前调用。
  • postHandle:在执行完实际程序之后调用。
  • afterCompletion:在完成请求后调用。

拦截器的实现包含两种,一种是实现 HandlerInterceptor 接口,即实现上述三个方法;另一种是继承拦截适配器类,只需修改所需方法。

之后,在 SpringMVC 的配置文件中配置拦截器即可。

image

3.14 介绍一下 WebApplicationContext

WebApplicationContext 继承了 ApplicationContext 并增加了一些 WEB 应用必备的特有功能,它不同于一般的 ApplicationContext ,因为它能处理主题,并找到被关联的 servlet。

3.15 SpringMVC 与 Struts2 区别

相同点
都是基于 mvc 的表现层框架,都用于 web 项目的开发。

不同点

  1. 前端控制器不一样。SpringMVC 的前端控制器是 servlet:DispatcherServlet。Struts2 的前端控制器是 filter:StrutsPreparedAndExcutorFilter。

  2. 请求参数的接收方式不一样。SpringMVC 是使用方法的形参接收请求的参数,基于方法的开发,线程安全,可以设计为单例或者多例的开发,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。Struts2 是通过类的成员变量接收请求的参数,是基于类的开发,线程不安全,只能设计为多例的开发。

  3. Struts 采用值栈存储请求和响应的数据,通过 OGNL 存取数据,SpringMVC 通过参数解析器是将 request 请求内容解析,并给方法形参赋值,将数据和视图封装成 ModelAndView 对象,最后又将 ModelAndView 中的模型数据通过 reques 域传输到页面。Jsp 视图解析器默认使用 jstl。

  4. 与 spring 整合不一样。SpringMVC 是 spring 框架的一部分,不需要整合。在企业项目中,SpringMVC 使用更多一些。

4 REST

4.1 REST 代表什么

REST 代表着抽象状态转移,它是根据 HTTP 协议从客户端发送数据到服务端。

4.2 什么是安全的 REST 操作

REST 接口是通过 HTTP 方法完成操作

  • 一些 HTTP 操作是安全的,如 GET 和 HEAD,它不能在服务端修改资源
  • 换句话说,PUT、POST 和 DELETE 是不安全的,因为他们能修改服务端的资源

所以,是否安全的界限,在于是否修改服务端的资源

4.3 REST API 是无状态的吗

是的,REST API 应该是无状态的,因为它是基于 HTTP 的,它也是无状态的。

REST API 中的请求应该包含处理它所需的所有细节。它不应该依赖于以前或下一个请求或服务器端维护的一些数据,例如会话。

REST 规范为使其无状态设置了一个约束,在设计 REST API 时,你应该记住这一点。

4.4 REST 是安全的吗,能做什么来保护它

安全是一个宽泛的术语。它可能意味着消息的安全性,这是通过认证和授权提供的加密或访问限制提供的。
REST 通常不是安全的,需要开发人员自己实现安全机制。