Spring MVC 的执行流程如下:
Spring MVC 的核心组件如下列表所示:
自动类型转换指的是,Spring MVC 可以将表单中的字段,自动映射到实体类的对应属性上。
JSP 页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<form action="add">
名称:<input type="input" name="name"><br>
年龄:<input type="input" name="age"><br>
<input type="submit" value=" 提交 ">
form>
body>
html>
编写实体类
public class PersonDTO {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
编写控制器
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PersonController {
@RequestMapping(value = "/add", produces = "text/plain;charset=utf-8")
public String add(PersonVO person) {
return person.getName() + ":" + person.getAge();
}
}
业务的操作过程中可能会出现中文乱码的情况,以下是处理中文乱码的解决方案。
第一步,在 web.xml 添加编码过滤器,配置如下:
<filter>
<filter-name>encodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
filter>
<filter-mapping>
<filter-name>encodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
第二步,设置 RequestMapping 的 produces 属性,指定返回值类型和编码,如下所示:
@RequestMapping(value = "/add", produces = "text/plain;charset=utf-8")
在 Spring MVC 中可以通过配置和实现 HandlerInterceptor 接口,来实现自己的拦截器。
配置全局拦截器
在 Spring MVC 的配置文件中,添加如下配置:
<mvc:interceptors>
<bean class="com.learning.core.MyInteceptor">bean>
mvc:interceptors>
添加拦截器实现代码
拦截器的实现代码如下:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 拦截器
**/
public class MyInteceptor implements HandlerInterceptor {
// 在业务处理器处理请求之前被调用
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
// 在业务处理器处理请求完成之后,生成视图之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
// 在 DispatcherServlet 完全处理完请求之后被调用
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
pom.xml 添加验证依赖包
配置如下:
<dependency>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.17.Finalversion>
dependency>
开启注解验证
在 Spring MVC 的配置文件中,添加如下配置信息:
<mvc:annotation-driven />
编写控制器
代码如下:
import com.google.gson.JsonObject;
import com.learning.pojo.PersonDTO;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class PersonController {
@RequestMapping(value = "/check", produces = "text/plain;charset=utf-8")
public String check(@Validated PersonDTO person, BindingResult bindResult) {
// 需要 import com.google.gson.Gson
JsonObject result = new JsonObject();
StringBuilder errmsg = new StringBuilder();
if (bindResult.hasErrors()) {
List<ObjectError> errors = bindResult.getAllErrors();
for (ObjectError error : errors) {
errmsg.append(error.getDefaultMessage());
}
result.addProperty("status", -1);
} else {
result.addProperty("status", 1);
}
result.addProperty("errmsg", errmsg.toString());
return result.toString();
}
}
编写实体类
代码如下:
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class PersonDTO {
@NotNull(message = "姓名不能为空")
private String name;
@Min(value = 18,message = "年龄不能低于18岁")
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
更多验证注解,如下所示:
注解 | 运行时检查 |
---|---|
@AssertFalse | 被注解的元素必须为 false |
@AssertTrue | 被注解的元素必须为 true |
@DecimalMax(value) | 被注解的元素必须为一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(Value) | 被注解的元素必须为一个数字,其值必须大于等于指定的最小值 |
@Digits(integer=, fraction=) | 被注解的元素必须为一个数字,其值必须在可接受的范围内 |
@Future | 被注解的元素必须是日期,检查给定的日期是否比现在晚 |
@Max(value) | 被注解的元素必须为一个数字,其值必须小于等于指定的最大值 |
@Min(value) | 被注解的元素必须为一个数字,其值必须大于等于指定的最小值 |
@NotNull | 被注解的元素必须不为 null |
@Null | 被注解的元素必须为 null |
@Past(java.util.Date/Calendar) | 被注解的元素必须过去的日期,检查标注对象中的值表示的日期比当前早 |
@Pattern(regex=, flag=) | 被注解的元素必须符合正则表达式,检查该字符串是否能够在 match 指定的情况下被 regex定义的正则表达式匹配 |
@Size(min=, max=) | 被注解的元素必须在制定的范围(数据类型:String、Collection、Map、Array) |
@Valid | 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个 map,则对其中的值部分进行校验 |
@CreditCardNumber | 对信用卡号进行一个大致的验证 |
被注释的元素必须是电子邮箱地址 | |
@Length(min=, max=) | 被注解的对象必须是字符串的大小必须在制定的范围内 |
@NotBlank | 被注解的对象必须为字符串,不能为空,检查时会将空格忽略 |
@NotEmpty | 被注释的对象必须不为空(数据:String、Collection、Map、Array) |
@Range(min=, max=) | 被注释的元素必须在合适的范围内(数据:BigDecimal、BigInteger、String、byte、short、int、long 和原始类型的包装类) |
@URL(protocol=, host=, port=, regexp=, flags=) | 被注解的对象必须是字符串,检查是否是一个有效的URL,如果提供了 protocol、host 等,则该 URL 还需满足提供的条件 |
答:
答:POJO 和 JavaBean 的区别如下:
getter/setter
方法的普通类都就可以称作 POJO,它是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。简而言之,当一个 POJO 可序列化,有一个无参的构造函数,它就是一个 JavaBean。
答:常见的跨域的实现方式有两种:使用 JSONP 或者在服务器端设置运行跨域。服务器运行跨域的代码如下:
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/**");
}
};
}
}
@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。
答:@RequestMapping 常用属性如下:
@RequestMapping(value="/index")
;@RequestMapping(value="/list",method=RequestMethod.POST)
;@RequestMapping(value="/list",params={"name","age"})
。@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,所以会报错。
A:服务器繁忙
B:找不到该页面
C:禁止访问
D:服务器跳转中
答:C
题目解析:常用 HTTP 状态码及对应的含义:
答:forward 和 redirect 区别如下:
@RequestMapping(value="/list")
@ResponseBody
public String list(Integer id){
return "id="+id;
}
A:id=0
B:id=
C:页面报错 500
D:id=null
答:D
题目解析:包装类可以赋值 null,不会报错。
答:在后端代码中可以使用 forward:/index.jsp
或 redirect:/index.jsp
完成页面跳转,前者 URL 地址不会发生改变,或者 URL 地址会发生改变,完整跳转代码如下:
@RequestMapping("/redirect")
public String redirectTest(){
return "redirect:/index.jsp";
}
答: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>
答:@Validated 和 @Valid 都用于参数的效验,不同的是:
答:Spring MVC 获取 request 有以下三种方式:
从请求参数中获取
示例代码:
@RequestMapping("/index")
@ResponseBody
public void index(HttpServletRequest request){
// do something
}
该方法实现的原理是 Controller 开始处理请求时,Spring 会将 request 对象赋值到方法参数中。
通过 RequestContextHolder上下文获取 request 对象
示例代码:
@RequestMapping("/index")
@ResponseBody
public void index(){
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
// do something
}
通过自动注入的方式
@Controller
public class HomeController{
@Autowired
private HttpServletRequest request; // 自动注入 request 对象
// do something
}