# Spring MVC

# 01. 简述一下 Spring MVC 的执行流程?

参考答案

前端控制器(DispatcherServlet) 接收请求,通过映射从 IoC 容器中获取对应的 Controller 对象和 Method 方法,在方法中进行业务逻辑处理组装数据,组装完数据把数据发给视图解析器,视图解析器根据数据和页面信息生成最终的页面,然后再返回给客户端。

# 02. POJO 和 JavaBean 有什么区别?

参考答案

POJO 和 JavaBean 的区别如下:

  • POJO(Plain Ordinary Java Object)普通 Java 类,具有 getter/setter 方法的普通类都就可以称作 POJO,它是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
  • JavaBean 是 Java 语言中的一种可重用组件,JavaBean 的构造函数和行为必须符合特定的约定:这个类必须有一个公共的缺省构造函数;这个类的属性使用 getter/setter 来访问,其他方法遵从标准命名规范;这个类应是可序列化的。

简而言之,当一个 POJO 可序列化,有一个无参的构造函数,它就是一个 JavaBean。

# 03. 如何实现跨域访问?

参考答案

常见的跨域的实现方式有两种:使用 Nginx 代理或者在服务器端设置运行跨域。服务器运行跨域的代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                // 设置允许跨域的请求规则
                registry.addMapping("/api/**");
            }
        };
    }
}

# 04. 以下代码描述正确的是?

@RequestMapping(value="/list",params={"age=10"}
public String list(){
   // do something
}

A:age 参数不传递的时候,默认值是 10
B:age 参数可以为空
C:age 参数不能为空
D:以上都不对

参考答案

C

params={"age=10"} 表示必须包含 age 参数,且值必须等于 10。

# 05. @RequestMapping 注解的常用属性有哪些?

参考答案

@RequestMapping 常用属性如下:

  • value:指定 URL 请求的实际地址,用法:@RequestMapping(value="/index");

  • method:指定请求的 method 类型,如 GET/POST/PUT/DELETE 等,用法:@RequestMapping(value="/list",method=RequestMethod.POST);

  • params:指定请求参数中必须包含的参数名称,如果不存在该名称,则无法调用此方法,用法:@RequestMapping(value="/list",params={"name","age"})。

# 06. 访问以下接口不传递任何参数的情况下,执行的结果是?

@RequestMapping(value="/list")
@ResponseBody
public String list(int id){
    return "id="+id;
}

A:id=0
B:id=
C:页面报错 500
D:id=null

参考答案

C

页面报错会提示:可选的参数 id 不能转为 null,因为基本类型不能赋值 null,所以会报错。

# 07. 访问页面时显示 403 代表的含义是?

A:服务器繁忙
B:找不到该页面
C:禁止访问
D:服务器跳转中

参考答案

C

常用 HTTP 状态码及对应的含义:

HTTP 状态码 含义
400 错误请求,服务器不理解请求的语法
401 未授权,请求要求身份验证
403 禁止访问,服务器拒绝请求
500 服务器内部错误,服务器遇到错误,无法完成请求
502 错误网关,服务器作为网关或代理,从上游服务器收到无效响应
504 网关超时,服务器作为网关或代理,但是没有及时从上游服务器收到请求

# 08. forward 和 redirect 有什么区别?

参考答案

forward 和 redirect 区别如下:

  • forward 表示请求转发,请求转发是服务器的行为;redirect 表示重定向,重定向是客户端行为;

  • forward 是服务器请求资源,服务器直接访问把请求的资源转发给浏览器,浏览器根本不知道服务器的内容是从哪来的,因此它的地址栏还是原来的地址;redirect 是服务端发送一个状态码告诉浏览器重新请求新的地址,因此地址栏显示的是新的 URL;

  • forward 转发页面和转发到的页面可以共享 request 里面的数据;redirect 不能共享数据;

  • 从效率来说,forward 比 redirect 效率更高。

# 09. 访问以下接口不传递任何参数的情况下,执行的结果是?

@RequestMapping(value="/list")
@ResponseBody
public String list(Integer id){
    return "id="+id;
}

A:id=0
B:id=
C:页面报错 500
D:id=null

参考答案

D

包装类可以赋值 null,不会报错。

# 10. Spring MVC 中如何在后端代码中实现页面跳转?

参考答案

在后端代码中可以使用 forward:/index.jsp 或 redirect:/index.jsp 完成页面跳转,前者 URL 地址不会发生改变,或者 URL 地址会发生改变,完整跳转代码如下:

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

# 11. Spring MVC 的常用注解有哪些?

参考答案

Spring MVC 的常用注解如下:

常用注解 说明
@Controller 用于标记某个类为控制器
@ResponseBody 标识返回的数据不是 html 标签的页面,而是某种格式的数据,如 JSON、XML 等
@RestController 相当于 @Controller 加 @ResponseBody 的组合效果
@Component 标识为 Spring 的组件
@Configuration 用于定义配置类
@RequestMapping 用于映射请求地址的注解
@Autowired 自动装配对象
@RequestHeader 可以把 Request 请求的 header 值绑定到方法的参数上

# 12. 拦截器的使用场景有哪些?

参考答案

拦截器的典型使用场景如下:

  • 日志记录:可用于记录请求日志,便于信息监控和信息统计;

  • 权限检查:可用于用户登录状态的检查;

  • 统一安全处理:可用于统一的安全效验或参数的加密 / 解密等。

# 13. Spring MVC 如何排除拦截目录?

参考答案

在 Spring MVC 的配置文件中,添加 ,用于排除拦截目录,完整配置的示例代码如下:

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <!-- 排除拦截地址 -->
        <mvc:exclude-mapping path="/api/**" />
        <bean class="com.learning.core.MyInteceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

# 14. @Validated 和 @Valid 有什么区别 ?

参考答案

@Validated 和 @Valid 都用于参数的效验,不同的是:

  • @Valid 是 Hibernate 提供的效验机制,Java 的 JSR 303 声明了 @Valid 这个类接口,而 Hibernate-validator 对其进行了实现;@Validated 是 Spring 提供的效验机制,@Validation 是对 @Valid 进行了二次封装,提供了分组功能,可以在参数验证时,根据不同的分组采用不同的验证机制;

  • @Valid 可用在成员对象的属性字段验证上,而 @Validated 不能用在成员对象的属性字段验证上,也就是说 @Validated 无法提供嵌套验证。

# 15. Spring MVC 有几种获取 request 的方式?

参考答案

Spring MVC 获取 request 有以下三种方式:

  1. 从请求参数中获取

    示例代码:

    @RequestMapping("/index")
    @ResponseBody
    public void index(HttpServletRequest request) {
        // do something
    }
    

    该方法实现的原理是 Controller 开始处理请求时,Spring 会将 request 对象赋值到方法参数中。

  2. 通过 RequestContextHolder上下文获取 request 对象

    示例代码:

    @RequestMapping("/index")
    @ResponseBody
    public void index(){
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
       // do something
    }
    
  3. 通过自动注入的方式

    @Controller
    public class HomeController{
        @Autowired
        private HttpServletRequest request; // 自动注入 request 对象
        // do something
    }