springMVC面经

1. 什么是MVC?

springMVC面经_第1张图片

用户的请求会到达 Servlet,然后根据请求调用相应的 Java Bean,并把所有的显示结果交给 JSP 去完成,这样的模式我们就称为 MVC 模式。

MVC是一种设计模式,在这种模式下软件被分为三层,即Model(模型)、View(视图)、Controller(控制器)。Model代表的是数据,View代表的是用户界面,Controller代表的是数据的处理逻辑,它是Model和View这两层的桥梁。将软件分层的好处是,可以将对象之间的耦合度降低,便于代码的维护。
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分

M:Model,模型层,指工程中的JavaBean,作用是处理数据 dao,bean

JavaBean分为两类:

一类称为实体类Bean:专门存储业务数据的,如 Student、User 等
一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。

V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据

C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器

MVC的工作流程:

用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器

1.1 什么是SpringMVC

Spring MVC 是一个基于 Java 的实现了 MVC 设计模式的请求驱动类型的轻量级 Web 框架,通过把 Model,View,Controller 分离,将 web 层进行职责解耦,把复杂的 web 应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合

SpringMVC是Spring的一个后续产品,是Spring的一个子项目

SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。

注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet

1.2 SpringMVC的特点

  • Spring 家族原生产品,与 IOC 容器等基础设施无缝对接
  • 基于原生的Servlet,通过了功能强大的前端控制器DispatcherServlet,对请求和响应进行统一处理
  • 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案
  • 代码清新简洁,大幅度提升开发效率
  • 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可
  • 性能卓著,尤其适合现代大型、超大型互联网项目要求

2. DAO层是做什么的?

DAO是Data Access Object的缩写,即数据访问对象,在项目中它通常作为独立的一层,专门用于访问数据库。这一层的具体实现技术有很多,常用的有Spring JDBC、Hibernate、JPA、MyBatis等,在Spring框架下无论采用哪一种技术访问数据库,它的编程模式都是统一的。

3. 介绍一下Spring MVC的执行流程

  • 整个过程开始于客户端发出的一个HTTP请求,Web应用服务器接收到这个请求。如果匹配DispatcherServlet的请求映射路径,则Web容器将该请求转交给DispatcherServlet处理。

  • DispatcherServlet接收到这个请求后,将根据请求的信息(包括URL、HTTP方法、请求报文头、请求参数、Cookie等)及HandlerMapping的配置找到处理请求的处理器(Handler)。可将HandlerMapping看做路由控制器,将Handler看做目标主机。值得注意的是,在Spring MVC中并没有定义一个Handler接口,实际上任何一个Object都可以成为请求处理器。

  • 当DispatcherServlet根据HandlerMapping得到对应当前请求的Handler后,通过HandlerAdapter对Handler进行封装,再以统一的适配器接口调用Handler。HandlerAdapter是Spring MVC框架级接口,顾名思义,HandlerAdapter是一个适配器,它用统一的接口对各种Handler方法进行调用。

  • 处理器完成业务逻 辑的处理后,将返回一个ModelAndView给DispatcherServlet,ModelAndView包含了视图逻辑名和模型数据信息。

  • ModelAndView中包含的是“逻辑视图名”而非真正的视图对象,DispatcherServlet借由ViewResolver完成逻辑视图名到真实视图对象的解析工作。

  • 当得到真实的视图对象View后,DispatcherServlet就使用这个View对象对ModelAndView中的模型数据进行视图渲染。

  • 最终客户端得到的响应消息可能是一个普通的HTML页面,也可能是一个XML或JSON串,甚至是一张图片或一个PDF文档等不同的媒体形式。

4. 说一说你知道的Spring MVC注解

  • @RequestMapping:

    作用:该注解的作用就是用来处理请求地址映射的,也就是说将其中的处理器方法映射到url路径上。

    属性:

    method:是让你指定请求的method的类型,比如常用的有get和post。

    value:是指请求的实际地址,如果是多个地址就用{}来指定就可以啦。

    produces:指定返回的内容类型,当request请求头中的Accept类型中包含指定的类型才可以返回的。

    consumes:指定处理请求的提交内容类型,比如一些json、html、text等的类型。

    headers:指定request中必须包含那些的headed值时,它才会用该方法处理请求的。

    params:指定request中一定要有的参数值,它才会使用该方法处理请求。

  • @RequestParam:

    作用:是将请求参数绑定到你的控制器的方法参数上,是Spring MVC中的接收普通参数的注解。

    属性:

    value是请求参数中的名称。

    required是请求参数是否必须提供参数,它的默认是true,意思是表示必须提供。

  • @RequestBody:

    作用:如果作用在方法上,就表示该方法的返回结果是直接按写入的Http responsebody中(一般在异步获取数据时使用的注解)。

    属性:required,是否必须有请求体。它的默认值是true,在使用该注解时,值得注意的当为true时get的请求方式是报错的,如果你取值为false的话,get的请求是null。

  • @PathVaribale:

    作用:该注解是用于绑定url中的占位符,但是注意,spring3.0以后,url才开始支持占位符的,它是Spring MVC支持的rest风格url的一个重要的标志。

5. 介绍一下Spring MVC的拦截器

拦截器会对处理器进行拦截,这样通过拦截器就可以增强处理器的功能。Spring MVC中,所有的拦截器都需要实现HandlerInterceptor接口,该接口包含如下三个方法:preHandle()、postHandle()、afterCompletion()。

这些方法的执行流程如下图:
springMVC面经_第2张图片

  • 通过上图可以看出,Spring MVC拦截器的执行流程如下:

    执行preHandle方法,它会返回一个布尔值。如果为false,则结束所有流程,如果为true,则执行下一步。

    执行处理器逻辑,它包含控制器的功能。

    执行postHandle方法。

    执行视图解析和视图渲染。

    执行afterCompletion方法。

  • Spring MVC拦截器的开发步骤如下:

    开发拦截器:

      实现handlerInterceptor接口,从三个方法中选择合适的方法,实现拦截时要执行的具体业务逻辑。
    

    注册拦截器:

      定义配置类,并让它实现WebMvcConfigurer接口,在接口的addInterceptors方法中,
      注册拦截器,并定义该拦截器匹配哪些请求路径。
    

6. 怎么去做请求拦截?

参考答案

如果是对Controller记性拦截,则可以使用Spring MVC的拦截器。

如果是对所有的请求(如访问静态资源的请求)进行拦截,则可以使用Filter。

如果是对除了Controller之外的其他Bean的请求进行拦截,则可以使用Spring AOP。

补充

1、转发和重定向的区别

转发和重定向的区别及使用方法(全)

SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户

SpringMVC视图的种类很多,默认有转发视图重定向视图

  • 转发是一次请求,第一次是浏览器法发送(第二次是发生在服务器内部),我们说的一次是浏览器发送的一次请求。(因为第二次是发生在服务器内部,所以转发的地址栏还是第一次请求的地址栏)

  • 重定向是两次请求,第一次是访问servlet,第二次是访问重定向的地址。(最终的地址栏地址是重定向的地址)

  • 转发可以获取请求域中的数据,重定向不可以,因为转发是一次请求,用到的request是同一个。
    重定向浏览器发两次请求,两次请求就是两个request对象

  • 转发可以访问web-inf里的对象,重定向不行,因为web-inf有安全性,只能通过服务器访问,不能通过浏览器访问

  • 转发不能跨域,重定向可以。跨域也就是说 转发发生在服务器内部,只能访问服务器内部的资源。重定向可以访问外部资源,比如重定向到百度

1.1、ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转

1.2、转发视图(用的很少)-- 前缀"forward:"

SpringMVC中默认的转发视图是InternalResourceView

SpringMVC中创建转发视图的情况:

当控制器方法中所设置的视图名称以"forward:"为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转

例如"forward:/",“forward:/employee”

<a th:href="@{/testForward}">测试InternalResourceViewa><br>
@RequestMapping("/testForward")
    public String testForward(){
        return "forward:/testThymeleafView";
    }

1.3、重定向视图(用的多)-- 前缀"redirect:"

SpringMVC中默认的重定向视图是RedirectView

当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转

例如"redirect:/",重定向到首页
“redirect:/employee”

<a th:href="@{/testRedirect}">测试RedirectViewa><br>
 @RequestMapping("/testRedirect")
    public String testRedirect(){
        return "redirect:/testThymeleafView";
    }

2、RESTful(一种软件架构的风格,也就是格式)

用也行,不用也行
RESTFul从入门到精通超全解析(全)

1、RESTful简介
REST:Representational State Transfer,表现层资源状态转移。

2、RESTful的实现
具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。

它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。

REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。
springMVC面经_第3张图片

3、HiddenHttpMethodFilter

由于浏览器只支持发送get和post方式的请求,那么该如何发送put和delete请求呢?

SpringMVC 提供了 HiddenHttpMethodFilter 帮助我们将 POST 请求转换为 DELETE 或 PUT 请求

HiddenHttpMethodFilter 处理put和delete请求的条件:

a>当前请求的请求方式必须为post

b>当前请求必须传输请求参数_method

满足以上条件,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数_method的值,因此请求参数_method的值才是最终的请求方式

<form th:action="@{/user}" method="post">  
    <input type="hidden" name="_method" value="PUT">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="修改"><br>
form>
@RequestMapping(value = "/user", method = RequestMethod.PUT)
    public String updateUser(String username, String password){
        System.out.println("修改用户信息:"+username+","+password);
        return "success";
    }

4、HttpMessageConverter

HttpMessageConverter,报文信息转换器,将请求报文转换为Java对象,或将Java对象转换为响应报文

HttpMessageConverter提供了两个注解和两个类型:@RequestBody,@ResponseBody,RequestEntity,ResponseEntity

HttpMessageConverter提供了两个注解和两个类型:

@RequestBody,RequestEntity
@ResponseBody,ResponseEntity

@ResponseBody(用的多)用于标识控制器方法
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体响应到浏览器

<a th:href="@{/testResponseBody}">通过@ResponseBody响应浏览器数据a><br>
@RequestMapping("/testResponseBody")
@ResponseBody
public String testResponseBody(){
    return "success"; //响应给浏览器的数据,也就是响应到浏览器的响应体

结果:浏览器页面显示success,不再跳转到success.html页面了

4.1 问题提出:@ResponseBody直接响应浏览器User对象报错

因为不是字符串数据,浏览器接受服务器的响应数据必须是字符串格式

4.2、SpringMVC处理json(解决 4.1 问题)

注意:实体类、map转换为json是json对象,list转换为json是json数组

@ResponseBody处理json的步骤:

a>导入jackson的依赖

b>在SpringMVC的核心配置文件中开启mvc的注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器:MappingJackson2HttpMessageConverter,可以将响应到浏览器的Java对象转换为Json格式的字符串

c>在处理器方法上使用@ResponseBody注解进行标识

d>将Java对象直接作为控制器方法的返回值返回,就会自动转换为Json格式的字符串

@RequestMapping("/testResponseUser")
@ResponseBody
public User testResponseUser(){
    return new User(1001,"admin","123456",23,"男");
}

浏览器的页面中展示的结果:

{“id”:1001,“username”:“admin”,“password”:“123456”,“age”:23,“sex”:“男”}

4.3、SpringMVC处理ajax

ajax是页面不发生跳转的情况下与服务器交互

4.4、@RestController注解

@RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解

4.5、ResponseEntity(用的多)

ResponseEntity用于控制器方法的返回值类型,该控制器方法的返回值就是响应到浏览器的响应报文

5、拦截器

简介
控制器controller(也叫处理器),控制器方法被调用之后返回的是统一的ModelandView对象。

拦截器是拦截控制器方法的,拦截器的三个抽象方法一个在控制器方法执行之前、一个在控制器方法执行之后、一个在渲染视图完毕之后。

5.1、拦截器的配置

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现HandlerInterceptor接口

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

注意:一个bean就是ioc容器中的一个组件,一个对象。

5.2、拦截器的三个抽象方法

SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法

postHandle:控制器方法执行之后执行postHandle()

afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation()

5.3、 若每个拦截器的preHandle()都返回true

此时多个拦截器的执行顺序和拦截器在SpringMVC的配置文件的配置顺序有关:

preHandle()会按照配置的顺序执行,
而postHandle()和afterComplation()会按照配置的反序执行

5.4、 若某个拦截器的preHandle()返回了false

preHandle()返回false和它之前的拦截器的preHandle()都会执行,
postHandle()都不执行,
返回false的拦截器之前的拦截器的afterComplation()会执行

假如有5个拦截器,现在第3个preHandle()设置了false,那么1,2,3拦截器的preHandle()都会执行;postHandle()都不执行;拦截器2的afterComplation()会执行

6、异常处理器

6.1、基于配置的异常处理

SpringMVC提供了一个处理控制器方法执行过程中所出现的异常的接口:HandlerExceptionResolver

HandlerExceptionResolver接口的实现类有:DefaultHandlerExceptionResolver和SimpleMappingExceptionResolver

SpringMVC提供了自定义的异常处理器SimpleMappingExceptionResolver,

6.2、基于注解的异常处理

@ControllerAdvice将当前类标识为异常处理的组件,@ControllerAdvice这个和@component都是差不多标识组件的意思

@ExceptionHandler用于设置所标识方法处理的异常

ex表示当前请求处理中出现的异常对象

//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {

    //@ExceptionHandler用于设置所标识方法处理的异常
    @ExceptionHandler(ArithmeticException.class)
    //ex表示当前请求处理中出现的异常对象
    public String handleArithmeticException(Exception ex, Model model){
        model.addAttribute("ex", ex);
        return "error";
    }

}

7、SpringMVC的执行流程

springMVC面经_第4张图片

简洁版流程

1、 用户发送请求至前端控制器DispatcherServlet。

2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。

3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器

拦截器(如果有则生成)一并返回给DispatcherServlet。

4、 DispatcherServlet调用HandlerAdapter处理器适配器。

5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。

6、 Controller执行完成返回ModelAndView。

7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

9、 ViewReslover解析后返回具体View。

10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

11、 DispatcherServlet响应用户。

8、SpringMVC常用组件

  • DispatcherServlet:前端控制器,不需要工程师开发,由框架提供

作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求

  • HandlerMapping:处理器映射器,不需要工程师开发,由框架提供

作用:根据请求的url、method等信息查找Handler,即控制器方法

  • Handler:处理器,需要工程师开发

作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理

  • HandlerAdapter:处理器适配器,不需要工程师开发,由框架提供

作用:通过HandlerAdapter对处理器(控制器方法)进行执行

  • ViewResolver:视图解析器,不需要工程师开发,由框架提供

作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、RedirectView

  • View:视图

作用:将模型数据通过页面展示给用户

9、DispatcherServlet初始化过程

DispatcherServlet 本质上是一个 Servlet,所以天然的遵循 Servlet 的生命周期。所以宏观上是 Servlet 生命周期来进行调度。

a>初始化WebApplicationContext
b>创建WebApplicationContext
c>DispatcherServlet初始化策略

FrameworkServlet创建WebApplicationContext后,刷新容器,调用onRefresh(wac),此方法在DispatcherServlet中进行了重写,调用了initStrategies(context)方法,初始化策略,即初始化DispatcherServlet的各个组件

10、Spring MVC 十一个处理流程的详细解释?

  1. 浏览器发送请求,请求具体发到谁呢?先发到前端控制器,也就是说所有的请求都给发到前端控制器,前端控制器是所有请求的入口,但前端控制器不能处理业务请求,它只是一个请求的转发
  2. 谁来处理业务请求呢?Handler 处理器来真正处理业务请求,那么问题来了,前端控制器如何来找到这个 Handler 处理器呢?处理器映射器记录的就是请求的 url 和处理的方法之间的映射关系,这个映射关系是怎么建立起来的呢?就是通过 @RequestMapping 这个注解来建立起来的,这个映射关系就相当于一个 Map(key-value 这种形式),key 就是请求的 url,value 就是处理的 Handler。现在,前端控制器拿到这个请求之后,要找到对应的 Handler,怎么找呢?就要找处理器映射器,问它请求谁来处理?
  3. 处理器映射器会根据你请求的 url 来找对应的处理器,找不到就会报错,如果找到之后,这时,它就会返回一个处理器执行链,这个处理器执行链里面除了有 Handler 之外,还有拦截器(这儿我们可以开发自己的拦截器),然后返回给前端控制器
  4. 前端控制器依然不能处理这个业务请求,它这时做的还有另外一件事情,因为返回 Handler,它也不知道这个 Handler 是什么类型,因为在 springmvc 中 Handler 除了可以是注解形式的之外,其实还可以是非注解形式的(非注解形式我们一般不用),前端控制器并不知道这个 Handler 到底是什么类型的,那就没办法执行它,那总得找个东西执行,这时它就会把这个事交给另外一个组件来处理,这个组件就叫处理器适配器,这个处理器适配器就是来适配不同类型的 Handler。它就会根据你不同类型的 Handler 来选择不同类型的适配器来执行它
  5. 假如当前 Handler 是注解形式的,那么它就会选择注解形式的处理器适配器来执行这个 Handler。Handler 就执行了,也就是说我们 Controller 类中的那个方法就执行了,方法执行之后,里面的业务就处理了
  6. 业务处理之后,最后返回一个 ModelAndView。处理器适配器拿到这个结果是没有用的,它的作用就是执行这个 Handler,把这个 Handler 执行完之后,它的事就做完了
  7. 做完之后,拿到这个返回结果,那么它会原封不动地把这个返回结果扔给前端控制器,这时处理器适配器的事就做完了
  8. 前端控制器拿到这个 ModelAndView,它还是没有办法处理,它还是不能返回 html,这时它要找到相应的 jsp,因为 ModelAndView 即包含模型又包含视图,这个视图指定我们要用谁来渲染这个数据。我们要渲染数据,这时它就要找一个视图解析器来解析这个视图,由于这个视图也有很多种(我们最常见的视图是 jsp,除了 jsp,其实还有其他的,比如说还可以是报表,还可以是 pdf,还可以是 freemaker 等),它会找不同的视图解析器来处理。因为现在我们最常用的视图是 jsp,所以它就找到 jsp 对应的视图解析器
  9. 找到这个视图解析器,它来把这个视图解析,解析完了之后它会返回一个 View 对象
  10. 最后我们再调用这个视图解析器的渲染视图这个过程,渲染视图这个过程其实就是对于我们的 jsp 来说,就是把这个数据渲染成 html
  11. 最终渲染成 html 之后,就响应给用户

11、 Spring MVC 的控制器是不是单例模式?存在什么问题?怎么解决?

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

12、 Spring MVC 常用的注解?

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

13 、如何在拦截请求中拦截 get 方式提交的方法?

在 @RequestMapping 注解里面加上 method=RequestMethod.GET

14、 如何在方法中得到 Request 或 Session?

直接在方法的形参中声明 request,Spring MVC 就自动把 request 对象传入

15、 如何在拦截的方法里得到从前台传入的参数?

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

16、 如果前台有很多个参数传入,并且这些参数都是一个对象的,如何得到这个对象?

直接在方法中声明这个对象即可,Spring MVC 就自动会把属性赋值到这个对象里面

17、 Spring MVC 中函数的返回值是什么?

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

18 、Spring MVC 如何实现一个拦截器?

一是实现 HandlerInterceptor 接口,一是继承适配器类

你可能感兴趣的:(面经,servlet,java,mvc,springMVC,面经)