5.SpringMVC面试题

  • 1.请说一下SpringMVC 的执行流程
  • 2.SpringMVC常用的注解有哪些?
  • 3.如何解决get请求、post请求、返回字符串中文乱码问题?
  • 4.SpringMVC用什么对象从后台向前台传递数据的?
  • 5.怎样把Map,Model,ModelMap,ModelAndView里面的数据放到session中。
  • 6.SpringMvc中后台如何获取前台提交请求的数据?
  • 7.什么是MVC模式?
  • 8.SpringMvc中有个类把视图和数据都合并的一起的,叫什么?
  • 9. Springmvc 中拦截器如何使用?
  • 10.Spring MVC拦截器的三个方法的执行时机是什么?
  • 11.过滤器和拦截器的区别
  • 12.SpringMvc的异常处理
  • 13.什么是ContextLoaderListener,它的作用是什么?
  • 14.什么是restful架构风格?

1.请说一下SpringMVC 的执行流程

1.向服务器发送HTTP请求,请求被前端控制器DispatchServlet捕获
2.DispatcherServlet调用处理器映射器HandlerMapping
3.HandlerMapping根据请求url找到具体的处理器handler,最后以处理器执行链HandlerExecutionChain(生成处理器拦截器+处理器对象)的形式返回给DispatcherServlet
4.DispatcherServlet 根据获得的Handler,选择一个合适的 HandlerAdapter(鼠标接口有圆形的,USB的,typeC的)。
5.处理器适配器调用处理器的方法,执行完成后会向DispatcherServlet返回一个ModelAndView对象
6.根据返回的ModelAndView,选择一个合适的视图解析器ViewResolver(必须是已经注册到Spring容器的viewResolver)
7.viewResolver解析后将具体的view对象返回给DispatcherServlet
8.DispatcherServlet对view对象进行渲染视图,就是将数据模型填充到视图中形成响应对象返回给客户

2.SpringMVC常用的注解有哪些?

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

@RequestBody:作用在形参上,用于将前台发送过来的json或者xml格式的数据封装为对应的javabean对象。需要注意的是必须是post请求,而且json字符串的key必须要跟对象的属性名一致。

@ResponseBody:作用在方法上,通常controller方法的返回值会解析为跳转路径,但是加上@ResponseBody后会将返回对象转换成json格式响应给客户。(直接写入HTTP reponse body中)

@RequestParam:作用在形参上,获取请求中特定的请求参数值并赋值给形参
 

3.如何解决get请求、post请求、返回字符串中文乱码问题?

(1)post请求和get请求的传值乱码,在web.xml中配置字符编码过滤器

<!-- characterEncodingFilter字符编码过滤器 -->
<filter>
	<filter-name>characterEncodingFilter</filter-name>
	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
	<init-param>
		<!--要使用的字符集,一般我们使用UTF-8(保险起见UTF-8最好)-->
		<param-name>encoding</param-name>
		<param-value>UTF-8</param-value>
	</init-param>
	<init-param>
		<!--是否强制设置request的编码为encoding,默认false,不建议更改-->
		<param-name>forceRequestEncoding</param-name>
		<param-value>false</param-value>
	</init-param>
	<init-param>
		<!--是否强制设置response的编码为encoding,建议设置为true,下面有关于这个参数的解释-->
		<param-name>forceResponseEncoding</param-name>
		<param-value>true</param-value>
	</init-param>
</filter>
<filter-mapping>
	<filter-name>characterEncodingFilter</filter-name>
	<!--这里不能留空或者直接写 ' / ' ,否者不起作用-->
	<url-pattern>/*</url-pattern>
</filter-mapping>

(2)使用@ResponseBody出现乱码
@ResponseBody出现乱码原因:当一个请求到来时,首先会经过过滤器CharacterEncodingFilter,过滤器设置好编码之后进入springmvc,被DispatcherServlet捕获。当我们配置<mvc:annotation-driven>后会默认给容器中注入HttpMessageConverter

HttpMessageConverter有一系列实现类去处理@ResponseBody注解的返回值,如返回list或其它则使用 MappingJacksonHttpMessageConverter,如果是string,则使用 StringHttpMessageConverter,而StringHttpMessageConverter使用的是字符集默认是ISO-8859-1,而且是final的。所以在当返回json中有中文时会出现乱码。源码如下

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
    public static final Charset DEFAULT_CHARSET;
    static {
        DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
    }
}

解决方法一:单个请求的@ResponseBody后面加上produces=“text/html;charset=UTF-8;”(此方法只针对单个调用方法起作用),如下

@RestController
public class ProductController {
    @RequestMapping(value = "test.do",produces = "text/html;charset=utf-8")
    public String test(){
        return "SpringMVC test 成功";
    }
}

解决方法二:统一配置,在配置文件中的mvc:annotation-driven中添加以下代码

<!--响应ajax请求返回JSON-->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>*/*;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

4.SpringMVC用什么对象从后台向前台传递数据的?

使用Map、Model和ModelMap的方式,这种方式存储的数据是在request域中

@GetMapping("model.do")
public String testModel(Map map, Model model, ModelMap modelMap){
    map.put("map","map传递数据");
    model.addAttribute("model","model传递数据");
    modelMap.addAttribute("modelMap","modelMap传递数据");
    return "success";
}

使用request的方式

@GetMapping("requestpass.do")
public String requestPass(HttpServletRequest request, HttpServletResponse response){
    request.setAttribute("request","request传递数据");
    response.setHeader("username","zccheng");
    HttpSession session = request.getSession();
    session.setAttribute("session","session数据");
    return "success";
}

使用ModelAndView,也是把数据放到request域中。

@GetMapping("modelAndView.do")
public ModelAndView modelAndViewPass(ModelAndView mav){
    mav.addObject("mav","modelAndView数据");
    mav.setViewName("success");
    return mav;
}

5.怎样把Map,Model,ModelMap,ModelAndView里面的数据放到session中。

在类上添加@SessionAttributes注解将指定的Model数据存储到session中。

@SessionAttributes参数
names:这是一个字符串数组。里面应写需要存储到session中数据的名称。
types:根据指定参数的类型,将模型中对应类型的参数存储到session中。
value:其实和上面的names是一样的。
@SessionAttributes(value={"names"},types={Integer.class})
@Controller
public class session{
    @RequestMapping("/session")
    public String session(Model model){
        model.addAttributes("names", Arrays.asList("caoyc","zhh","cjx"));
        model.addAttributes("age", 22);
        return "/session";
    }
}

在上面代码中,在类上添加@SessionAttributes注解,并指定将names名称的Model数据存储到session域中,以及将Integer类型的Model数据存储到session域中。

6.SpringMvc中后台如何获取前台提交请求的数据?

(1)获取请求参数
(2)获取Cookie
(3)获取header

@RequestMapping(value = "test2.do",produces = "text/html;charset=utf-8")
public String test2(@RequestParam("username") String username,
                    @CookieValue("JSESSIONID")String jssionid,
                    @RequestHeader("User-Agent")String userAgent){
    return username+"======>"+jssionid+"==========>"+userAgent;
}

也可以在形参中传入HttpServletRequest,获取cookie和header

(4)获取对象

<form action="$ru">
    姓名:<input type="text" name="name"><br/>
    年龄:<input type="text" name="age"><br/>
    性别:<input type="text" name="gender"><br/>
    省份:<input type="text" name="address.province"><br/>
    城市:<input type="text" name="address.city"><br/>
    城镇:<input type="text" name="address.town"><br/>
    <input type="submit" value="提交">
</form>
@Controller
public class RequestController {
    @RequestMapping("/ru")
    public String getRequestUser(User user){
        System.out.println(user);
        return "success";
    }
}

7.什么是MVC模式?

MVC 的全称为model-view-controller(模型-视图-控制器)。MVC 是一种开发应用程序的模式。MVC模式将应用程序分成三个核心组件:模型、视图、控制器。它们各自处理自己的任务。最典型的MVC就是 JSP+servlet+javabean的模式;
Model:常用javabean去实现,通过各种类对数据库的数据进行获取,并封装在对象当中。
View: 视图是将模型包含的数据可视化,就是指用户看到交换的界面。比如html,jsp页面。
Controller:控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

8.SpringMvc中有个类把视图和数据都合并的一起的,叫什么?

ModelAndView。
Controller处理器调用模型层处理完用户请求后,把结果数据存储在该类的model属性中,把要返回的视图信息存储在该类的view属性中,然后把 ModelAndView返回给前端控制器。前端控制器通过调用配置文件中定义的视图解析器,对该对象进行解析,最后把结果数据显示在指定的页面上。

ModelAndVew可以使用addObject()方法设置需要返回的值。通过setViewName()方法跳转到指定的页面。

public class ModelAndView {
    @Nullable
    private Object view;
    @Nullable
    private ModelMap model;
}

9. Springmvc 中拦截器如何使用?

定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle方法执行");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    	//设置响应头
        response.setHeader("postHandle","postHandle");
        //postHandle方法可以修改跳转的页面
        modelAndView.setViewName("interceptor");
        System.out.println("postHandle方法执行");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    	//虽然设置了响应头但是不会生效
        response.setHeader("afterCompletion","afterCompletion");
        System.out.println("afterCompletion方法执行");
    }
}

在springmvc的配置文件中添加此拦截器

<mvc:interceptors>
	<mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.zcc.interceptor.MyInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

注意SSM项目中添加拦截器不能使用创建WebMvcConfigurer实现类的形式。这种方法是SpringBoot项目中使用的。
 

10.Spring MVC拦截器的三个方法的执行时机是什么?

preHandle(request,response, Object handler)
该方法在处理器方法执行之前执行。其返回值为 boolean ,若为 true 则紧接着会执行处理器方法

postHandle(request,response, Object handler,modelAndView)
该方法在处理器方法执行之后执行。处理器方法若最终未被执行,则该方法不会执行。由于该方法是在处理器方法执行完后执行,且该方法 参数中包含 ModelAndView ,所以该方法可以修改处理器方法的处理结果数据,还可以修改跳转的路径。

afterCompletion(request,response, Object handler, Exception ex)
等到对请求进行响应的所有工作完成之后才执行该方法。即该方法是在中央调度器渲染(数据填充)了响应页面之后执行的 ,此时对 ModelAndView 再操作也对响应无济于事。

当两个拦截器都实现放行操作时,顺序为preHandle1、preHandle2、处理器方法、postHandle2、postHandle1、afterCompletion2、afterCompletion1;

11.过滤器和拦截器的区别

(1)实现原理不同
过滤器是基于函数回调的,拦截器是基于java反射机制实现的
(2)是否依赖容器
过滤器实现的是java.servlet.Filter接口,该接口给是在Servlet规范中定义的,所以过滤器的使用要依赖于Tomcat等容器;

package javax.servlet;
import java.io.IOException;

public interface Filter {
    void init(FilterConfig var1) throws ServletException;
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    void destroy();
}

而拦截器它是spring的组件,由spring容器管理,并不依赖Tomcat容器,可以单独使用
(3)触发时机不同
过滤器是在请求进入Servlet之前进行预处理,在Servlet处理完以后结束
拦截器是在请求进入Servlet后,执行处理器方法之前进行预处理的,渲染了视图之后结束。

(4)拦截的范围不同
拦截器只对controller中的请求或访问static目录下资源起作用。而filter对所有进入容器的请求起作用
(5)是否能获取容器中的bean
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

过滤器处理中
filter=====>>>>>testService = null
preHandle方法执行
handler方法执行完毕
interceptor====>>>>>testService = com.zcc.service.TestServiceImpl@6b0ff65a
打印出a方法
postHandle方法执行
afterCompletion方法执行

(6)控制执行顺序不同
过滤器用@Order注解控制执行顺序,通过@Order控制过滤器的级别,值越小级别越高越先执行。

@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class MyFilter2 implements Filter {

拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
    registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").order(3);
}

参考文章

12.SpringMvc的异常处理

(1)在Controller中使用@ExceptionHandler注解。

@ExceptionHandler(CalculateException.class)
public String handleCalculateException(Exception exception, Model model){
    model.addAttribute("msg",exception.getMessage());
    return "error407";
}

 
error407.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>407错误:${requestScope.msg}</h1>
</body>
</html>

@ExceptionHandler是Controller级别的,不是整个应用程序全局有效。给每个controller添加对应的@ExceptionHandler方法会很繁琐。所以我们可以定义全局异常处理类

(2)使用@ControllerAdvice定义全局异常处理类(该类需要定义在ComponentScan扫描包下)

//@RestControllerAdvice 如果不想跳转页面,直接返回错误信息可以用此注解
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(CalculateException.class)
    @ResponseBody  //加了@ResponseBody就不再跳转页面了,直接将字符串返回
    public String handleCalculateException(Exception exception, Model model){
        model.addAttribute("msg",exception.getMessage());
        return "error407";
    }

    //处理其它异常
    @ExceptionHandler
    public String handleException(Exception exception, Model model){
        model.addAttribute("msg",exception.getMessage());
        return "error";
    }
}

13.什么是ContextLoaderListener,它的作用是什么?

ContextLoaderListener就是一个监听器,它的作用就是启动Web容器时,读取在contextConfigLocation中定义的xml文件,自动装配ApplicationContext的配置信息,并产生WebApplicationContext对象,然后将这个对象放置在ServletContext的属性里,这样我们只要得到Servlet就可以得到WebApplicationContext对象,并利用这个对象访问spring容器管理的bean。
简单来说,就是下面这段配置为web项目提供了spring支持,初始化了Ioc容器。

public interface WebApplicationContext extends ApplicationContext {
    @Nullable
    ServletContext getServletContext();
}
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
</context-param>

14.什么是restful架构风格?

restful架构风格就是必须通过某种手段让服务器的状态发生转化,而这种转化是建立在表现层上的,所以就叫做表现层状态转化。
对应到HTTP协议中来说,表现层代表的资源就是URI,手段就是使用不同请求方法,例如GET代表获取资源,POST代表添加资源,PUT代表修改资源,DELETE代表删除资源。

更多推荐

5.SpringMVC面试题