一、Spring MVC 核心概念
Spring MVC 的核心组件有哪些?
DispatcherServlet:前端控制器,接收所有请求并协调处理流程。
HandlerMapping:映射请求到对应的 Controller 或方法。
Controller:处理业务逻辑,返回 Model 和视图名称。
ViewResolver:解析视图名称到具体视图(如 JSP、Thymeleaf)。
ModelAndView:封装模型数据和视图信息。
Spring MVC 处理请求的完整流程?
用户发送请求 → DispatcherServlet 接收请求。
DispatcherServlet 通过 HandlerMapping 找到对应的 Handler(Controller 方法)。
调用 HandlerAdapter 执行 Handler,处理业务逻辑。
Handler 返回 ModelAndView(或直接返回数据,如 @ResponseBody)。
ViewResolver 解析视图名称,渲染视图(如 JSP)并返回响应。
二、注解与配置
@Controller 和 @RestController 的区别?
@Controller:返回视图名称,需配合视图解析器(如 JSP)。
@RestController:等价于 @Controller + @ResponseBody,直接返回 JSON/XML 数据,适用于 RESTful API。
@RequestMapping 和 @GetMapping/@PostMapping 的区别?
@RequestMapping 支持所有 HTTP 方法(需指定 method 参数)。
@GetMapping 是 @RequestMapping(method = RequestMethod.GET) 的简写。
如何获取请求参数?
URL 参数:@RequestParam(“name”) String name。
路径变量:@PathVariable(“id”) int id。
请求体(JSON):@RequestBody User user。
请求头:@RequestHeader(“User-Agent”) String userAgent。
如何实现文件上传?
配置 MultipartResolver(如 CommonsMultipartResolver)。
使用 @RequestParam(“file”) MultipartFile file 接收文件:
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
if (!file.isEmpty()) {
file.transferTo(new File("/path/to/save/" + file.getOriginalFilename()));
}
return "redirect:/success";
}
配置Multipart解析器
对于Spring Boot应用,通常不需要手动配置Multipart解析器,因为Spring Boot已经自动配置好了。但是,如果你需要自定义设置(例如文件大小限制),你可以通过在application.properties或application.yml中配置:
# application.properties
spring.servlet.multipart.max-file-size=2MB
spring.servlet.multipart.max-request-size=2MB
创建文件上传的Controller
在你的Controller中,你可以使用@RequestParam注解来接收上传的文件。例如
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
public class FileUploadController {
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// 这里可以保存文件到服务器或进行其他处理
// 例如保存到文件系统:Files.write(Paths.get("path/to/file"), bytes);
redirectAttributes.addFlashAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + '!');
} catch (IOException e) {
e.printStackTrace();
}
} else {
redirectAttributes.addFlashAttribute("message", "Failed to upload " + file.getOriginalFilename() + " => " + file.getSize() + " bytes");
}
return "redirect:/uploadStatus"; // 重定向到上传状态页面
}
}
三、数据绑定与验证
如何将表单数据绑定到对象?
直接使用对象作为参数,字段名与表单 name 属性一致:
@PostMapping("/submit")
public String submitForm(User user) {
// user 自动填充表单数据
return "result";
}
如何实现数据校验(Validation)?
使用 @Valid 注解结合 JSR-303 规范(如 Hibernate Validator):
@PostMapping("/create")
public String createUser(@Valid @ModelAttribute User user, BindingResult result) {
if (result.hasErrors()) {
return "error-page";
}
// 处理逻辑
return "success";
}
四、拦截器与异常处理
如何自定义拦截器(Interceptor)?
实现 HandlerInterceptor 接口,重写 preHandle、postHandle、afterCompletion。
注册拦截器:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/admin/**");
}
}
WebMvcConfigurer参考:https://blog.youkuaiyun.com/weixin_45433031/article/details/121846207
如何全局处理异常?
使用 @ControllerAdvice 和 @ExceptionHandler:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception e) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("message", e.getMessage());
return mav;
}
}
五、RESTful 支持与跨域
如何设计 RESTful API?
使用 HTTP 方法对应操作:
GET 查询 → @GetMapping
POST 新增 → @PostMapping
PUT 更新 → @PutMapping
DELETE 删除 → @DeleteMapping
URL 路径使用复数名词(如 /api/users)
如何解决跨域问题(CORS)?
使用 @CrossOrigin 注解:
@RestController
@CrossOrigin(origins = "http://example.com")
public class UserController { ... }
全局配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://example.com")
.allowedMethods("GET", "POST");
}
}
六、整合与高级特性
Spring MVC 如何整合 Spring Security?
引入 spring-boot-starter-security 依赖。
配置安全规则:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().permitAll();
}
}
Spring Security: https://blog.youkuaiyun.com/As_Yua/article/details/140829880
如何实现异步请求处理?
使用 Callable 或 DeferredResult:
搭建注意事项
- 启动项目访问浏览器报错
后台报错
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [SpringMvc.xml]; nested exception is java.io.FileNotFoundException: class path resource [SpringMvc.xml] cannot be opened because it does not exist
将web.xml中
<param-value>classpath:SpringMvc.xml</param-value>
改为
<param-value>classpath*:SpringMvc.xml</param-value>
为什么修改下面有讲解,改错误为找不到SpringMvc.xml文件
改完继续报错
最后检查一通是project Structure 中的Artifacts中的war包有问题,重新加载了一个war包
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
此时web.xml中的 <param-value>classpath :SpringMvc.xml</param-value>
但是继续访问请求如图
后台报错:
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [SpringMvc.xml]; nested exception is java.io.FileNotFoundException: class path resource [SpringMvc.xml] cannot be opened because it does not exist
原因,多模块中,我的项目为<packaging>pom</packaging>,在pom
下打包resourse下资源不会进入target中
解决办法:
1.将pom修改成jar/war后打包(使用maven工具先将target 清除掉 maven clean 如何 package一下就ok),后面可以在改把<packaging>pom</packaging>
改回来
2.
将Output path修改到resourses目录下
如果1此时web.xml中的 <param-value>classpath* :SpringMvc.xml</param-value>
访问请求如图
后台不报错 后台不报错的原因为
classpath: 到你的class路径中查找文件,在target中找
classpath*:不仅包含class的路径,还包括jar文件中(class路径)进行查找
解决办法和上面一样
-
报错java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet
这类问题归结于下面:Intellij idea使用Maven搭建web项目启动报找不到类,而maven的pom.xml都已引用,问题就是在于没在WEB-INF下新建lib文件夹
解决办法:
在IDEA中点击File > Project Structure > Artifacts > 在右侧Output Layout右击项目名,选择Put into Output Root,执行后,在WEB-INF在增加了lib目录,里面是项目引用的jar包,点击OK。
重新启动tomcat就行了。 -
在web.xml中设置分发器
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
对于<url-pattern>/</url-pattern>
方式一:带后缀,比如*.action *.do .aaa
该种方式比较精确、方便,在以前和现在企业中都有很大的使用比例 方式二:/ 不会拦截 .jsp,但是会拦截.html等静态资源(静态资源:除了 servlet和jsp之外的js、css、png等)
为什么配置为/ 会拦截静态资源???
因为tomcat容器中有一个web.xml(父),你的项目中也有一个web.xml(子),是一个继承关系
父web.xml中有一个DefaultServlet, url-pattern 是一个 /
此时我们自己的web.xml中也配置了一个 / ,覆写了父web.xml的配置
为什么不拦截.jsp呢?
因为父web.xml中有一个JspServlet,这个servlet拦截.jsp文件,而我们并没有覆写这个配置,
所以springmvc此时不拦截jsp,jsp的处理交给了tomcat
如何解决/拦截静态资源这件事? 方式三:/ 拦截所有,包括.jsp
这里的/必须为/ ,为/*会页面访问不了
如果为/*
启动服务器(注意)