SpringMVC面试题总结

  • 一、谈谈你对SpringMVC的理解?
  • a.SpringMVC有哪些优点?
  • b.Spring MVC的异常处理 ?
  • 二、SpringMVC有哪些组件?
  • a.前端控制器(DispatcherServlet)
  • b.处理器映射器(HandlerMapping)
  • c.处理器适配器(HandlerAdapter)
  • d.视图解析器(ViewResolver)
  • e.视图(View)
  • 三、SpringMVC的流程?
  • 四、SpringMVC有哪些组件?
  • 1.常用注解
  • @RequestMapping
  • @RequestBody
  • @ResponseBody
  • 2.获取请求参数
  • 五、SpringMVC中资源的跳转
  • a.三种资源跳转方式的区别:
  • 1.转发
  • 2.重定向
  • 3.定时刷新
  • a.SpringMVC中的请求转发
  • b.SpringMVC中的请求重定向
  • c.SpringMVC中的定时刷新
  • 六、SpringMVC中域的使用
  • a.request域的使用
  • b.session域的使用
  • c.ServeletContext域中的使用
  • d.@RequestAttribute
  • e.@SessionAttrribute
  • f.@ModelAttribute
  • 七、处理器方法支持的参数类型和返回值类型
  • a.支持的方法参数类型
  • b.控制器方法支持的返回值类型
  • 八、SpringMVC文件上传
  • 九、异常处理
  • 十、json处理
  • 十一、SpringMVC注解方式工作原理


一、谈谈你对SpringMVC的理解?

SpringMVC是一个WEB层、控制层框架,主要用来负责与客户端交互,业务逻辑的调用。MVC是一种模型(model)-视图(view)-控制器(controller),三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。分层设计,实现了业务系统各个组件之间的解耦,有利于系统的并行开发,提升开发效率。

a.SpringMVC有哪些优点?

1.清晰的角色划分:前端控制器(dispatcherServlet) ,请求到处理器映射(handlerMapping),处理器适配器(HandlerAdapter),视图解析器(ViewResolver),每一个角色都可以由一个专门的对象来实现。
2.Spring MVC是视图不可知的,可以支持各种视图技术。
3.SpringMVC可以和Spring框架实现无缝连接。

b.Spring MVC的异常处理 ?

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

二、SpringMVC有哪些组件?

a.前端控制器(DispatcherServlet)

本质上是一个Servlet,相当于一个中转站,所有的访问都会走到这个Servlet中,再根据配置进行中转到相应的Handler中进行处理,获取到数据和视图后,在使用相应视图做出响应。

b.处理器映射器(HandlerMapping)

本质上就是一段映射关系,将访问路径和对应的Handler存储为映射关系,在需要时供前端控制器查阅。

c.处理器适配器(HandlerAdapter)

本质上是一个适配器,可以根据要求找到对应的Handler来运行。前端控制器通过处理器映射器找到对应的Handler信息之后,将请求响应和对应的Handler信息交由处理器适配器处理,处理器适配器找到真正handler执行后,将结果即model和view返回给前端控制器

d.视图解析器(ViewResolver)

本质上也是一种映射关系,可以将视图名称映射到真正的视图地址。前端控制器调用处理器适配完成后得到model和view,将view信息传给视图解析器得到真正的view

e.视图(View)

将handler处理器中返回的model数据嵌入到视图解析器解析后得到的jsp页面中,向客户端做出响应

三、SpringMVC的流程?

java mvc 笔试 mvc面试题及答案_System

(1)用户发送请求至前端控制器DispatcherServlet;
(2)DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
(3)处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;
(5)HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑; (6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。

四、SpringMVC有哪些组件?

1.常用注解

@RequestMapping

a.基本使用
	通过注解方式实现路径到处理器方法的映射
		用在类上
			用在类上则配置的路径会作为这个类中所有处理器的路径的父路径使用
		用在方法上
			用在方法上表示将该方法变为一个处理器,且和指定路径做映射
b.注解属性
	i.String [] value() default {}; 
		指定要将当前处理器绑定到哪个访问路径上
		可以配置多个路径。路径中也可以使用*号作为通配符匹配部分路径
	ii.RequestMethod[] method() default {} ;
		指定当前处理器处理哪种提交方式提交的请求。
		不指定则接收任意请求方式的请求
	iii.String[] params() default {};
		用来限定当前请求中必须包含指定名称的请求参数才会被当前处理器处理 
		通过params属性指定只处理请求参数符合指定要求的请求
/**
 * params()
 * 限定请求参数
 *      格式1:只指定名称
 *      格式2:(!名称)
 *      格式3:(名称=值)或(名称!=值)
 */
@RequestMapping(value = "/test04.action",params = {"uname","!uage","ucity=bj","ugender!=male"})
public void test04(){
    System.out.println("my01..test04...");
}
iv.String[] headers() default {};
		用来限定当前请求中必须包含指定名称的请求头才会被当前处理器处理
/**
 * headers() default()
 * 限定请求头的要求,符合要求才能进来
 *      格式1:只指定名称
 *      格式2:(!名称)
 *      格式3:(名称=值)或(名称!=值)
 */
@RequestMapping(value = "/test05.action",headers = {"Host=localhost"})
public void test05(){
    System.out.println("my01..test05...");
}

@RequestBody

注解实现接收http请求的json数据,将json转换为java对象:

/**
 * 控制方法可以接受的参数:请求实体内容
 * @RequestBody 直接获取请求体内容
 */
@RequestMapping("/test06.action")
public void test06(@RequestBody() String body){
    System.out.println(body);
}

@ResponseBody

a.返回字符串数据
	i.通过response返回 
	ii.直接获取PrintWriter返回
	iii.通过@ResponseBody返回 
b.返回json数据 
	i.手动拼接json 
	ii.通过配置@ResponseBody利用内置的jackson将对象处理为json返回

2.获取请求参数

web开发相关的对象:request response session webrequest
	a.通过request对象获取
		在SpringMVC的注解开发中
		可以选择性的接收Request和Response对象来使用
		可以用request对象来获取请求参数
web开发相关的流对象:Reader Writer InputStream OutputStream
模型对象:Model Map ModelMap
请求参数
	直接获取请求参数
	手动映射获取请求参数 @RequestParam
	封装请求参数到bean

中文乱码解决

<!--配置SpringMVC乱码解决过滤器-->
<filter>
    <filter-name>encodingFilter</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>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

域属性
@RequestAttribute
@SessionAttribute

/**
 * 控制器方法可以接收的参数:域属性
 * @RequestAttribute 从request域中获取数据
 * @SessionAttribute 从session域中获取数据
 */
@RequestMapping("/test02_1.action")
public String test02_1(HttpServletRequest request, HttpSession session){
    request.setAttribute("k1","v1");
    request.setAttribute("k2","v2");
    session.setAttribute("k3","v3");
    session.setAttribute("k4","v4");
    return "forward:/my01/test02_2.action";
}
@RequestMapping("/test02_2.action")
public void test02_2(@RequestAttribute("k1") String k1,
	@RequestAttribute("k2") String k2,
	@SessionAttribute("k3") String k3,
	@SessionAttribute("k4") String k4){
    System.out.println(k1);
    System.out.println(k2);
    System.out.println(k3);
    System.out.println(k4);
}

其他注解
@CookieValue

/**
 * 控制器方法可以接受的参数:cookie的值
 * @CookieValue 获取指定名称cookie的值
 */
@RequestMapping("/test03.action")
public void test03(@CookieValue("JSESSIONID") String JSESSIONID){
    System.out.println(JSESSIONID);
}

@RequestHeader

/**
 * 控制器方法可以接受的参数:请求头的值
 * @RequestHeader 获取指定名称请求头的值
 */
@RequestMapping("/test04.action")
public void test04(@RequestHeader("host") String host){
    System.out.println(host);
}

@RequestBody

/**
 * 控制方法可以接受的参数:请求实体内容
 * @RequestBody 直接获取请求体内容
 */
@RequestMapping("/test06.action")
public void test06(@RequestBody() String body){
    System.out.println(body);
}

@PathVariable
通过@PathVariable可以将 URL 中占位符参数绑定到控制器处理方法的参数中

//@PathVariable可以用来映射URL中的占位符到目标方法的参数中
@RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable("id") Integer id){
        System.out.println("testPathVariable:"+id);
        return SUCCESS;
    }

五、SpringMVC中资源的跳转

a.三种资源跳转方式的区别:

1.转发

请求转发是服务器内部的跳转
		地址栏不发生变化
		只有一个请求响应
		可以通过request域传递数据

2.重定向

请求重定向是浏览器自动发起对跳转目标的请求
		地址栏会发生变化
		两次请求响应
		无法通过request域传递对象

3.定时刷新

定时刷新是浏览器自动发起对跳转目标的请求
		地址栏会发生变化
		两次请求响应
		无法通过request域传递对象
		可以在资源跳转期间提示额外信息

a.SpringMVC中的请求转发

可以通过返回forward:/xxxx.xxx格式的字符串表明要转发到指定地址

b.SpringMVC中的请求重定向

i.传统方式实现请求重定向 
	ii.SpringMVC方式实现请求重定向
		可以通过返回redirect:/xxxx.xxx格式的字符串表明要重定向到指定地址
		通过这种方式实现请求重定向时不用在路径前写应用名,SpringMVC会自动拼接应用名

c.SpringMVC中的定时刷新

SpringMVC中没有提供实现定时刷新的便捷方式,只能用传统方式实现定时刷新

六、SpringMVC中域的使用

a.request域的使用

i.传统方式向request域中写入数据
	ii.向model中写入数据,默认就是写入request域

b.session域的使用

i.传统方式向session域中写入数据
@RequestMapping("/test01.action")
public String test01(HttpServletRequest request){
    request.setAttribute("k1","v1");
    request.setAttribute("k2","v2");
    return "forward:/my01/test02.action";
}
@RequestMapping("/test02.action")
public void test02(HttpServletRequest request){
    String k1 = (String) request.getAttribute("k1");
    String k2 = (String) request.getAttribute("k2");
    System.out.println(k1);
    System.out.println(k2);
}
ii.通过model+@SessionAttributes实现将数据写入session
/**
 * SpringMVC作用域--request域--MVC方式
 * 向模型中写入的数据 本质上就是将数据写入了request域
 */
@RequestMapping("/test03.action")
public String test03(Model model){
    model.addAttribute("k1","v1");
    model.addAttribute("k2","v2");
    return "forward:/my01/test04.action";
}

@RequestMapping("/tet04.action")
public void test04(@RequestAttribute("k1") String k1,@RequestAttribute("k2") String k2){
    System.out.println(k1);
    System.out.println(k2);
}

c.ServeletContext域中的使用

只能通过传统方式写入
/**
 * SpringMVC作用域--SessionContext域--传统方式
 */
@RequestMapping("/test01.action")
public void test01(HttpServletRequest request){
    ServletContext sc = request.getServletContext();
    sc.setAttribute("sck1","scv1");
    sc.setAttribute("sck2","scv2");
}
@RequestMapping("/test02.action")
public void test02(HttpServletRequest request){
    ServletContext sc = request.getServletContext();
    String sck1 = (String) sc.getAttribute("sck1");
    String sck2 = (String) sc.getAttribute("sck2");
    System.out.println(sck1);
    System.out.println(sck2);
}

d.@RequestAttribute

用在控制器方法参数上用来从Request域中获取指定名称的属性的属性值

e.@SessionAttrribute

用在控制器方法参数上用来从Session域中获取指定名称的属性的属性值

f.@ModelAttribute

i.使用在方法上 
		则被修饰的方法将会在当前类的任意handler方法执行之前执行,
		该方法返回的返回值会自动存入model供后续使用
	ii.使用在方法参数之前 
		会从model中获取属性值赋值到被修饰的方法参数上

七、处理器方法支持的参数类型和返回值类型

a.支持的方法参数类型

HttpServletRequest 
		代表当前请求的对象
	HttpServletResponse 
		代表当前响应的对象
	HttpSession 
		代表当前会话的对象
	WebRequest 
		SpringMVC提供的对象
		相当于是request和session的合体,可以操作这两个域中的属性
	InputStream OutputStream Reader Writer 
		代表request中获取的输入流和response中获取的输出流
	通过@PathVariable @RequestParam声明的方法参数 
		@PathVariable可以将请求路径的指定部分获取赋值给指定方法参数
		@RequestParam可以将指定请求参数赋值给指定方法参数
		如果不写此注解,则默认会将同名的请求参数赋值给方法参数
	通过@RequestAttribute、@SessionAttribute和@ModelAttribute声明的方法参数 
		@RequestAttribute从request域中获取数据
		@SessionAttribute从Session域中获取数据
		@ModelAttribute从Model中获取数据
	通过@CookieValue和@RequestHeader声明的方法参数 
		@CookieValue可以将请求中的指定名称的cookie赋值给指定方法参数
		@RequestHeader可以将请求参数中的指定名称的头赋值给指定方法参数
	Model和ModelMap和java.util.Map 
		向这些Model ModelMap Map中存入属性,相当于向模型中存入数据
	Bean类 
		SpringMVC自动将请求参数封装到bean
	MultipartFile 
		实现文件上传功能时,接收上传的文件对象
	Errors  BindingResult  
		实现数据验证的参数

b.控制器方法支持的返回值类型

ModelAndView :可以返回一个ModelAndView对象,在其中封装Model和View信息
*View:可以直接返回一个代表视图的View对象
字符串类型有以下三种:
1.redirect

/**
 * 控制器方法可以返回的返回值类型:redirect:开头的字符串
 * 返回redirect:开头的字符串可以实现请求重定向
 */
@RequestMapping("/test04_1.action")
public void test04_01(HttpServletRequest request,HttpServletResponse response) throws IOException {
    response.sendRedirect(request.getContextPath()+"/index.jsp");
}

@RequestMapping("/test04_2.action")
public String test04_2(){
    return "redirect:/index.jsp";
}

2.forward

/**
 * 控制器方法可以返回的返回值类型:forward:开头的字符串
 * 返回forward:开头的字符串可以实现请求转发
 */
@RequestMapping("/test03_1.action")
public void test03_1(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/index.jsp").forward(request,response);
}
//
@RequestMapping("/test03_2.action")
public String test03_2(){
    return "forward:/index.jsp";
}

3.普通字符

/**
 * 控制方法可以返回的返回值类型:普通字符型
 * 返回的普通字符串会作为试图名称来使用
 */
@RequestMapping("/test02.action")
public String test02(Model model){
    model.addAttribute("k1","v1");
    model.addAttribute("k2","v2");
    return "my01test02";
}

void :如果返回值类型是void,则会自动返回和当前处理器路径名相同的视图名

/**
 * 控制方法返回可以返回的返回值类型:void
 * 将使用默认视图名作为视图名称来使用
 * 所谓默认视图名 = 当前控制器方法访问路径去除前后缀
 */
@RequestMapping("/test05.action")
public void test05(Model model){
    model.addAttribute("k1","v1");
    model.addAttribute("k2","v2");
}

方法被@ResponseBody修饰
当方法被@ResponseBody修饰时,默认将返回的对象转为json写入输出

/**
 * 控制器可以返回的返回值类型:@ResponseBody修饰的方法
 * 如果控制器方法被@ResponseBody修饰,则无论返回值是什么,都会作为相应发送给浏览器
 * 如果是基本数据类型、String类型,则直接发送给浏览器
 * 如果是对象类型,则转换为json格式字符串发送给浏览器
 */
@ResponseBody
@RequestMapping("/test06_2.action")
public User test06_2(){
    return new User(3,"xxx", Arrays.asList("bj","sh","gz"));
}
//直接打给浏览器
@ResponseBody
@RequestMapping("/test06_1.action")
public String test06_1(){
    return "abc";
}

除以上之外返回的任何内容都会被当做模型中的数据来处理,值为返回的数据,键为返回类型名首字母转小写,而返回的视图名等同于返回值为void的时的视图名 。

八、SpringMVC文件上传

a.准备文件上传表单 文件上传表单必须满足如下三个条件
	a.文件上传项必须有name属性
	b.表单必须是post提交
	c.表单必须是enctype=“multipart/form-date”
<!--配置文件上传工具类-->
<bean id="mltipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="utf-8"/>
</bean>
b.在配置文件中配置文件上传工具 
	必须是这个id必是这个类
<!--配置文件上传工具类-->
<bean id="mltipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="utf-8"/>
</bean>
c.在Controller中实现文件上传
/**
 * 文件上传
 */
@RequestMapping("/test01.action")
public void test01(MultipartFile fx) throws IOException {
    fx.transferTo(new File("D://"+fx.getOriginalFilename()));
}

九、异常处理

为当前Controller配置错误处理
@ExceptionHandler

public ModelAndView exceptionHandler(Exception e){
    System.out.println("出异常的代码");
    ModelAndView mav = new ModelAndView();
    mav.addObject("exception",e);
    mav.setViewName("err");
    return mav;
}

配置文件方式配置全局错误处理

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.NullPointerException">null_err</prop>
            <prop key="java.io.IOException">io_err</prop>
            <prop key="java.lang.Throwable">g_err</prop>
        </props>
    </property>
</bean>

十、json处理

发送json数据
通过配置@ResponseBody利用内置的jackson将对象处理为json返回

/**
 * 发送json数据
 * 通过配置@ResponseBody利用内置的jackson将对象处理为json返回
 */
@ResponseBody
@RequestMapping("/test01.action")
public User test01(){
    User user = new User(99,"张三丰", Arrays.asList("sg","gz","sz"));
    return user;
}

接收json数据
通过@RequestBody利用内置的jackson将json处理为对象

/**
     * 接收json数据
     * @RequestBody 直接读取json为对象
     */
    @RequestMapping("/test02.action")
    public void test02(@RequestBody User user){
        System.out.println(user);
    }
}

十一、SpringMVC注解方式工作原理

        当服务器启动时,先会加载web.xml,创建前端控制器Servlet,前端控制器加载并解析SpringMVC的配置文件。
        当解析到包扫描时,扫描指定的包,并将含有@Controller注解的类解析为处理器。
        如果配置过mvc:annotation-driven/ 就会解析Spring-MVC注解。
        解析@RequestMapping(value="/hello.action"),将指定的地址和当前方法的映射关系进行保存。
        当用户发出请求访问一个地址时,SpringMVC寻找该地址映射关系,如果存在,则找到响应处理器相应方法执行,如果找不到,则报404