SpringBoot第三站:整合SpringMVC

目录

[1. Springmvc的自动解管理](#1. Springmvc的自动解管理)

[1.1 中央转发器](#1.1 中央转发器)

[1.2 控制器](#1.2 控制器)

[1.3 视图解析器自动管理](#1.3 视图解析器自动管理)

实现文件上传

[1.4 静态资源访问](#1.4 静态资源访问)

[1.5 消息转换和格式化](#1.5 消息转换和格式化)

[1.6 欢迎页面的自动配置](#1.6 欢迎页面的自动配置)

2.springboot扩展SpringMVC

[2.1 在容器中注册视图控制器(请求转发)](#2.1 在容器中注册视图控制器(请求转发))

[2.2 注册格式化器](#2.2 注册格式化器)

[2.3 消息转换器](#2.3 消息转换器)

[2.4 拦截器注册](#2.4 拦截器注册)


学习springmvc和springboot的自动配置我们必须对springmvc的组件足够了解,起码知道怎么用。Springmvc的组件基本都被springboot来做了自动的配置。

1. Springmvc的自动解管理

  • 中央转发器(DispatcherServlet)
  • 控制器
  • 视图解析器
  • 静态资源访问
  • 消息转换器
  • 格式化
  • 静态资源管理

1.1 中央转发器

Xml无需配置

XML 复制代码
<servlet>    
    <servlet-name>chapter2</servlet-name>    
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>    
    <servlet-name>chapter2</servlet-name>    
    <url-pattern>/</url-pattern>
</servlet-mapping>

中央转发器被springboot自动接管,不再需要我们在web.xml中配置,我们现在的项目也不是web项目,也不存在web.xml,

org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\

(双击shift键即可查找)

1.2 控制器

控制器Controller在springboot的注解扫描范围内自动管理。

1.3 视图解析器自动管理

Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

ContentNegotiatingViewResolver:组合所有的视图解析器的;

曾经的配置文件无需再配

XML 复制代码
<bean id="de" class="org.springframework.web.servlet.view.InternalResourceViewResolver">    
    <property name="prefix" value="/WEB-INF/jsp/"></property>    
    <property name="suffix" value="*.jsp"></property>
</bean>

源码:

当我们做文件上传的时候我们也会发现multipartResolver是自动被配置好的

实现文件上传

页面

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input name="pic" type="file">
    <input type="submit">
</form>
</body>
</html>

Controller

java 复制代码
@RequestMapping("/img")
public String upload(){
    return "upload";
}
java 复制代码
package com.qcby.controller;

import org.junit.platform.commons.logging.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.util.logging.*;

import javax.servlet.http.HttpServletRequest;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
import org.slf4j.LoggerFactory;

@Controller
public class UploadController {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UploadController.class);

    @RequestMapping("/upload")
    public String upload(@RequestParam("pic") MultipartFile file, HttpServletRequest request) {
        if (file.isEmpty()) {
            logger.error("上传的文件为空");
            return "upload";
        }
        String contentType = file.getContentType();
        String originalFileName = file.getOriginalFilename();
        logger.info("fileName--> {}", originalFileName);
        logger.info("getContentType--> {}", contentType);

        // 生成唯一文件名,避免文件覆盖
        String uniqueFileName = generateUniqueFileName(originalFileName);
        // 使用 Path 处理文件路径,提高兼容性
        Path filePath = Paths.get("D:", "imgup");

        try {
            uploadFile(file.getBytes(), filePath, uniqueFileName);
        } catch (IOException e) {
            logger.error("文件上传失败", e);
        }

        return "success";
    }

    private static void uploadFile(byte[] file, Path filePath, String fileName) throws IOException {
        File targetDir = filePath.toFile();
        if (!targetDir.exists()) {
            Files.createDirectories(filePath);
        }
        Path targetPath = filePath.resolve(fileName);
        // 使用 try-with-resources 管理资源
        try (FileOutputStream out = new FileOutputStream(targetPath.toFile())) {
            out.write(file);
        }
    }

    private static String generateUniqueFileName(String originalFileName) {
        String extension = "";
        int dotIndex = originalFileName.lastIndexOf('.');
        if (dotIndex > 0) {
            extension = originalFileName.substring(dotIndex);
        }
        return UUID.randomUUID().toString() + extension;
    }
}

文件上传大小可以通过配置来修改

打开application.properties, 默认限制是10MB,我们可以任意修改

1.4 静态资源访问

1.5 消息转换和格式化

Springboot自动配置了消息转换器

格式化转换器的自动注册

时间类型我们可以在这里修改

在配置文件中指定好时间的模式我们就可以输入了

1.6 欢迎页面的自动配置

Springboot自动指定resources下的index.html

在resources下写一个index.html页面,在访问的时候只输入/访问的是index.html


2.springboot扩展SpringMVC

在实际开发中springboot并非完全自动化,很多跟业务相关我们需要自己扩展,springboot给我提供了接口。

我们可以来通过实现WebMvcConfigurer接口来扩展

java 复制代码
public interface WebMvcConfigurer {
    default void configurePathMatch(PathMatchConfigurer configurer) {
    }

    default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }

    default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }

    default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }

    default void addFormatters(FormatterRegistry registry) {
    }

    default void addInterceptors(InterceptorRegistry registry) {
    }

    default void addResourceHandlers(ResourceHandlerRegistry registry) {
    }

    default void addCorsMappings(CorsRegistry registry) {
    }

    default void addViewControllers(ViewControllerRegistry registry) {
    }

    default void configureViewResolvers(ViewResolverRegistry registry) {
    }

    default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
    }

    default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
    }

    default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }

    default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    }

    @Nullable
    default Validator getValidator() {
        return null;
    }

    @Nullable
    default MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
}

2.1 在容器中注册视图控制器(请求转发)

创建一个MyMVCConfig实现WebMvcConfigurer接口,实现一下addViewControllers方法,我们完成通过/ha访问,转发到success.html的工作

java 复制代码
@Configuration
public class MyMVCConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/ha").setViewName("success");
    }

2.2 注册格式化器

用来可以对请求过来的日期格式化的字符串来做定制化。当然通过application.properties配置也可以办到。

在配置文件里加上:

java 复制代码
@Configuration
public class MyMVCConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/ha").setViewName("success");
    }
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new Formatter<Date>() {
            @Override
            public String print(Date date, Locale locale) {
                return null;
            }
            @Override
            public Date parse(String s, Locale locale) throws ParseException {
                return new SimpleDateFormat("yyyy-MM-dd").parse(s);
            }
        });

2.3 消息转换器

作用

在 Spring MVC 应用中,当客户端发送请求到服务器时,请求体可能包含各种格式的数据(如 JSON、XML 等),消息转换器可以将这些数据转换为 Java 对象供控制器方法使用;当服务器处理完请求后,需要将 Java 对象转换为特定格式的数据(如 JSON、XML 等)返回给客户端,这也依赖于消息转换器。

在pom.xml中引入fastjson

XML 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

配置消息转换器,添加fastjson

java 复制代码
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonHttpMessageConverter fc = new FastJsonHttpMessageConverter();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
    fc.setFastJsonConfig(fastJsonConfig);
    converters.add(fc);
}

在实体类上可以继续控制

java 复制代码
package com.qcby.entity;

import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
public class User {
    private  String username;

    private  String password;

    private int age;

    private int score;

    private int gender;

    @JSONField(format = "yyyy-MM-dd")
    private Date date;
}

2.4 拦截器注册

1.创建拦截器

java 复制代码
package com.qcby.Interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置拦截");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置拦截");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("最终拦截");
    }
}

拦截器注册

java 复制代码
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MyInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/hello2");
}

除了hello2的其他的都拦截

示例

在访问hello时

相关推荐
无问81744 分钟前
SpringBoot配置文件
java·spring boot·后端
爱吃喵的鲤鱼1 小时前
MySQL——数据类型
java·数据库·mysql
子非衣1 小时前
Java解析多层嵌套JSON数组并将数据存入数据库示例
java·数据库·json
无眠_1 小时前
Spring Boot 核心知识点精讲:助你快速上手与深度理解
运维·spring boot·后端
幼安2291 小时前
日志统计(C++,模拟,双指针)
开发语言·c++·spring
bamboolm1 小时前
java 动态赋值写入word模板
java·word
阿梦Anmory1 小时前
【spring boot 实现图片验证码 前后端】
java·spring boot·后端
爱的叹息1 小时前
java使用(Preference、Properties、XML、JSON)实现处理(读写)配置信息或者用户首选项的方式的代码示例和表格对比
xml·java·json
幸好我会魔法1 小时前
常见限流算法及实现
java·开发语言·算法
K哥11251 小时前
【多线程】线程不安全问题
java·volatile·可重入锁·线程锁·线程安全问题·wait和notify