各位帅哥美女,编辑不易,动动发财小手,来个三连加关注,后续会有更加优秀的推文推出~
万字博客,实属用心去一行一行去敲,希望可以点赞收藏+关注,算是给我的一些鼓励和支持吧!
目录
8.4.2 使用 messages.properties 文件
12.1 Spring MVC 与 Spring Boot 整合
12.2 Spring MVC 与 Hibernate 整合
第一部分:Spring MVC 简介
1.1 什么是 Spring MVC?
Spring MVC 是 Spring 框架的一部分,是一个基于 Java 的、用于构建 Web 应用程序的 MVC 框架。它采用经典的 Model-View-Controller 设计模式,旨在简化开发流程、提高代码的可维护性。
1.2 Spring MVC 的核心组件
-
DispatcherServlet: 充当前端控制器,负责接收请求、委派请求给处理器(Controller),并协调视图的渲染。
-
HandlerMapping: 用于将请求映射到处理器(Controller)。
-
Controller: 处理器,负责处理具体的业务逻辑。
-
ViewResolver: 将逻辑视图名映射为具体的视图。
-
View: 负责渲染页面。
-
Model: 用于在 Controller 和 View 之间传递数据。
第二部分:Spring MVC 的配置
2.1 配置文件
Spring MVC 的配置文件通常是一个 XML 文件,用于配置 DispatcherServlet、HandlerMapping、ViewResolver 等核心组件。
<!-- 示例代码:Spring MVC 配置文件 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.2 注解配置
除了 XML 配置外,Spring MVC 还支持通过注解进行配置,这种方式更为简洁和方便。
// 示例代码:使用注解配置的 Controller
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/profile")
public String userProfile(Model model) {
// 处理业务逻辑
return "user/profile";
}
}
第三部分:请求处理流程
Spring MVC 的请求处理流程是整个框架的核心,理解这一流程对于开发者来说至关重要。
3.1 请求的分发
-
前端控制器 DispatcherServlet 接收请求。
-
HandlerMapping 根据请求映射找到对应的 Controller。
-
Controller 处理请求,返回一个 ModelAndView 对象。
3.2 模型和视图的处理
-
ModelAndView 包含了视图名和模型数据。
-
ViewResolver 将逻辑视图名映射为具体的视图。
-
View 负责渲染页面,将模型数据填充到页面中。
3.3 视图的渲染
-
InternalResourceViewResolver: 渲染 JSP 页面。
-
FreeMarkerViewResolver: 渲染 FreeMarker 页面。
-
其他视图解析器: 根据需要选择合适的视图解析器。
第四部分:控制器(Controller)
4.1 Controller 类的定义
Controller 负责处理具体的业务逻辑,通过注解 @Controller
声明一个类为 Controller。
// 示例代码:定义一个简单的 Controller
@Controller
@RequestMapping("/hello")
public class HelloController {
@GetMapping("/greet")
public String greet(Model model) {
model.addAttribute("message", "Hello, Spring MVC!");
return "greet";
}
}
4.2 请求映射和参数处理
@RequestMapping
注解: 映射请求路径。
// 示例代码:RequestMapping 的使用
@RequestMapping("/welcome")
public String welcome() {
return "welcome";
}
4.3 请求体处理
@RequestBody
注解: 处理请求体。
// 示例代码:RequestBody 的使用
@PostMapping("/addUser")
public String addUser(@RequestBody User user, Model model) {
userService.addUser(user);
model.addAttribute("message", "User added successfully!");
return "success";
}
第五部分:数据绑定与验证
5.1 数据绑定
基本数据绑定: 自动将请求参数绑定到方法的参数上。
// 示例代码:基本数据绑定
@GetMapping("/show")
public String showDetails(@RequestParam String username, @RequestParam int age, Model model) {
// 处理业务逻辑
return "details";
}
对象数据绑定: 将请求参数绑定到对象的属性上。
// 示例代码:对象数据绑定
@PostMapping("/update")
public String updateProfile(User user) {
// 处理业务逻辑
return "profile";
}
5.2 数据验证
@Valid
注解: 配合 javax.validation
包进行数据验证。
// 示例代码:数据验证
@PostMapping("/addUser")
public String addUser(@Valid @RequestBody User user, BindingResult result, Model model) {
if (result.hasErrors()) {
// 处理验证错误
return "error";
}
userService.addUser(user);
model.addAttribute("message", "User added successfully!");
return "success";
}
第六部分:拦截器与过滤器
6.1 拦截器
拦截器可以对请求进行预处理和后处理,通过实现 HandlerInterceptor
接口来自定义拦截器。
// 示例代码:自定义拦截器
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 在请求处理之前进行预处理
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在请求处理之后进行后处理
}
}
6.2 过滤器
过滤器是 Java Web 开发中的一种常见组件,用于对请求进行过滤处理。在 Spring MVC 中,我们可以通过配置 FilterRegistrationBean
来注册过滤器。
// 示例代码:过滤器的配置
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/api/*");
return registrationBean;
}
第七部分:异常处理
Spring MVC 提供了强大的异常处理机制,通过 @ExceptionHandler
注解和 HandlerExceptionResolver
接口来实现异常处理。
7.1 全局异常处理
通过 @ControllerAdvice
注解和 @ExceptionHandler
注解,可以实现全局异常处理。
// 示例代码:全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public String handleException(Exception e, Model model) {
model.addAttribute("error", e.getMessage());
return "error";
}
}
7.2 自定义异常
通过自定义异常类,并在业务逻辑中抛出异常,可以实现更细粒度的异常处理。
// 示例代码:自定义异常
public class MyException extends RuntimeException {
public MyException(String message) {
super(message);
}
}
第八部分:RESTful API 设计
8.1 基本概念
在设计 RESTful API 时,我们需要理解以下基本概念:
8.1.1 资源(Resource)
在 REST 中,每个 URI 代表一个资源。资源可以是具体的实体(例如用户、商品)或是一组相关的操作(例如获取所有用户、搜索商品)。资源通过 URI 进行唯一标识。
@RestController
@RequestMapping("/api/users")
public class UserController {
// ...
}
上述代码中,/api/users
就代表了用户资源的基础 URI。
8.1.2 表现层(Representation)
资源的表现形式即为资源的数据格式,通常是 JSON 或 XML。客户端通过请求资源的 URI 来获取资源的表现层,服务端则通过相应的表现层来向客户端返回资源。
8.1.3 状态转移(Stateless)
RESTful API 是无状态的,每次请求都包含足够的信息,服务器不需要保存客户端的状态。客户端的每个请求都应该包含足够的信息,以便服务器能够理解并处理请求。
8.2 注解与请求方法
在 Spring MVC 中,我们可以使用 @RestController
注解和 @RequestMapping
注解来实现 RESTful API。
@RestController
@RequestMapping("/api/users")
public class UserController {
// ...
}
上述代码中,@RestController
表示这是一个 RESTful API 的控制器,@RequestMapping
指定了基础 URI。
8.2.1 GET 请求
GET 请求用于获取资源,对应于 CRUD 操作中的读取(Retrieve)操作。
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
// 处理业务逻辑
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
上述代码中,@GetMapping("/{id}")
指定了处理 GET 请求的 URI,@PathVariable
用于获取 URI 中的参数。
8.2.2 POST 请求
POST 请求用于创建资源,对应于 CRUD 操作中的创建(Create)操作。
@PostMapping
public ResponseEntity<Void> addUser(@RequestBody User user) {
// 处理业务逻辑
userService.addUser(user);
URI location = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(user.getId())
.toUri();
return ResponseEntity.created(location).build();
}
上述代码中,@PostMapping
指定了处理 POST 请求的 URI,@RequestBody
用于获取请求体中的数据。
8.2.3 PUT 请求
PUT 请求用于更新资源,对应于 CRUD 操作中的更新(Update)操作。
@PutMapping("/{id}")
public ResponseEntity<Void> updateUser(@PathVariable Long id, @RequestBody User user) {
// 处理业务逻辑
userService.updateUser(id, user);
return ResponseEntity.noContent().build();
}
上述代码中,@PutMapping("/{id}")
指定了处理 PUT 请求的 URI,@RequestBody
用于获取请求体中的数据。
8.2.4 DELETE 请求
DELETE 请求用于删除资源,对应于 CRUD 操作中的删除(Delete)操作。
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// 处理业务逻辑
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
上述代码中,@DeleteMapping("/{id}")
指定了处理 DELETE 请求的 URI。
8.3 文件上传与下载
在实际应用中,可能会涉及到文件上传和下载的场景。以下是 RESTful API 中处理文件上传和下载的示例代码。
8.3.1 文件上传
@PostMapping("/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
return "redirect:/uploadStatus";
}
// 处理文件上传逻辑
return "redirect:/uploadStatus";
}
上述代码中,@RequestParam("file") MultipartFile file
用于接收上传的文件,RedirectAttributes
用于重定向时携带消息。
8.3.2 文件下载
@GetMapping("/download")
public ResponseEntity<Resource> handleFileDownload() {
// 处理文件下载逻辑
Resource resource = fileStorageService.loadFileAsResource("filename.txt");
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
上述代码中,Resource
用于封装文件资源,HttpHeaders.CONTENT_DISPOSITION
用于指定文件下载时的文件名。
8.4 国际化与本地化
为了支持多语言环境,我们可以在 RESTful API 中实现国际化与本地化。
8.4.1 配置 LocaleResolver
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
上述代码中,SessionLocaleResolver
用于将用户的语言信息存储在会话中,Locale.US
指定默认语言为英语。
8.4.2 使用 messages.properties 文件
# messages.properties 文件
greet.message=Hello, {0}!
@GetMapping("/greet")
public String greet(@RequestParam String name, Model model, Locale locale) {
String message = messageSource.getMessage("greet.message", new Object[]{name}, locale);
model.addAttribute("message", message);
return "greet";
}
上述代码中,messageSource.getMessage
方法用于获取 messages.properties 文件中的消息。
8.5 Spring MVC 测试
Spring MVC 提供了强大的测试支持,我们可以使用 MockMvc 对控制器进行测试。
8.5.1 基本测试
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetUserById() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username", is("testUser")));
}
}
上述代码中,@WebMvcTest(UserController.class)
表示仅测试 UserController
,mockMvc.perform(get("/api/users/1"))
模拟了 GET 请求。
8.5.2 集成测试
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@LocalServerPort
private int port;
@Test
public void testGetUserById() {
ResponseEntity<User> response = restTemplate.getForEntity("/api/users/1", User.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().getUsername()).isEqualTo("testUser");
}
}
上述代码中,@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
表示使用随机端口进行集成测试,restTemplate.getForEntity("/api/users/1", User.class)
发送 GET 请求。
8.6 安全性与 CSRF 防护
在设计 RESTful API 时,考虑到安全性是非常重要的一点。Spring Security 提供了一套完整的安全框架,可以轻松集成到 Spring MVC 中。
8.6.1 安全性配置
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
上述代码中,@EnableWebSecurity
表示启用 Web 安全性,configure(HttpSecurity http)
方法用于配置安全规则。
8.6.2 CSRF 防护
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders
第九部分:Spring MVC 测试
Spring MVC 提供了强大的测试支持,通过 MockMvc 可以模拟 HTTP 请求,验证控制器的行为。
9.1 基本测试
// 示例代码:基本测试
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testGetUserById() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username", is("testUser")));
}
}
9.2 集成测试
// 示例代码:集成测试
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@LocalServerPort
private int port;
@Test
public void testGetUserById() {
ResponseEntity<User> response = restTemplate.getForEntity("/api/users/1", User.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody().getUsername()).isEqualTo("testUser");
}
}
第十部分:安全性与 CSRF 防护
10.1 安全性配置
// 示例代码:安全性配置
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
10.2 CSRF 防护
// 示例代码:CSRF 防护配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false)
.maxAge(3600);
}
}
第十一部分:Spring MVC 进阶
11.1 异步支持
// 示例代码:异步支持
@GetMapping("/async")
public @ResponseBody Callable<String> handleAsyncRequest() {
return () -> {
// 处理业务逻辑
return "result";
};
}
11.2 WebFlux 支持
// 示例代码:WebFlux 支持
@RestController
public class ReactiveController {
@GetMapping("/flux")
public Flux<String> getFluxData() {
// 处理响应逻辑
return Flux.just("data1", "data2", "data3");
}
}
第十二部分:Spring MVC 与其他技术整合
12.1 Spring MVC 与 Spring Boot 整合
// 示例代码:Spring Boot 整合 Spring MVC
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
12.2 Spring MVC 与 Hibernate 整合
// 示例代码:Spring MVC 整合 Hibernate
@Repository
public class UserDao {
@Autowired
private SessionFactory sessionFactory;
public User getUserById(Long id) {
// 使用 Hibernate 查询用户信息
return sessionFactory.getCurrentSession().get(User.class, id);
}
}
第十三部分:Spring MVC 最佳实践
13.1 RESTful API 最佳实践
-
合理使用 HTTP 方法: GET 用于获取资源,POST 用于创建资源,PUT 用于更新资源,DELETE 用于删除资源。
-
良好的资源命名: 使用复数名词,遵循 RESTful 风格。
// 示例代码:资源命名
@RequestMapping("/api/users")
public class UserController {
// ...
}
- 使用响应状态码: 200 表示成功,201 表示资源创建成功,204 表示删除成功,400 表示客户端错误,404 表示资源未找到,500 表示服务器错误。
13.2 异常处理最佳实践
-
全局异常处理: 使用
@ControllerAdvice
注解进行全局异常处理,处理系统中未捕获的异常。 -
自定义异常: 根据业务需求自定义异常类,继承自 RuntimeException。
-
异常信息国际化: 将异常信息放入
messages.properties
文件中,实现多语言支持。
结语
本文详细介绍了 Spring MVC 框架的各个方面,包括配置、请求处理流程、控制器、数据绑定与验证、拦截器与过滤器、异常处理、RESTful API 设计、文件上传与下载、国际化与本地化、测试、安全性与 CSRF 防护、异步支持、WebFlux 支持、与其他技术的整合以及最佳实践等内容。希望通过本文的学习,读者能够深入了解 Spring MVC,并能够在实际项目中灵活运用这些知识。