SpringBoot第三站:整合SpringMVC

发布于:2025-03-18 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

1. Springmvc的自动解管理

1.1 中央转发器

1.2 控制器

1.3 视图解析器自动管理

实现文件上传

1.4 静态资源访问

 

1.5 消息转换和格式化

1.6 欢迎页面的自动配置

2.springboot扩展SpringMVC

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

2.2 注册格式化器

2.3 消息转换器

2.4 拦截器注册



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

1. Springmvc的自动解管理

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

1.1 中央转发器

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:组合所有的视图解析器的;

曾经的配置文件无需再配

<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是自动被配置好的

实现文件上传

页面

<!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

@RequestMapping("/img")
public String upload(){
    return "upload";
}
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接口来扩展

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的工作

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

2.2 注册格式化器

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

在配置文件里加上:

@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

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

配置消息转换器,添加fastjson

@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);
}

在实体类上可以继续控制

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.创建拦截器

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("最终拦截");
    }
}

拦截器注册

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

        除了hello2的其他的都拦截

示例

在访问hello时