【Spring】Spring MVC高级技术

简介: 前面学习了简单的Spring Web知识,接着学习更高阶的Web技术

前言


前面学习了简单的Spring Web知识,接着学习更高阶的Web技术。


高级技术



Spring MVC配置的替换方案


自定义DispatcherServlet配置

在第五章我们曾编写过如下代码。

public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

可以看到SpitterWebinitializer实现了AbstractAnnotationConfigDispatcherServletInitializer抽象类,并重写了三个必须的方法,实际上还可对更多方法进行重写,以便实现额外的配置,如对customizeRegistration方法进行重写,该方法是AbstractDispatcherServletInitializer的方法,无实际的方法体。当AbstractAnnotationConfigDispatcherServletInitializerDispatcherServlet注册到Servlet容器中后,就会调用customizeRegistration方法,并将Servlet注册后得到的Registration.Dynamic传入。可通过重写customizeRegistration方法设置MultipartConfigElement,如下所示。

@Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setMultipartConfig(
                new MultipartConfigElement("/tmp/spittr/uploads"));
    }


添加其他Servlet和Filter

AbstractAnnotationConfigDispatcherServletInitializer会创建DispatcherServletContextLoaderListener,当需要添加其他ServletFilter时,只需要创建一个新的初始化器即可,最简单的方式是实现WebApplicationInitializer接口。

import org.springframework.web.WebApplicationInitializer;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
public class MyServletInitializer implements WebApplicationInitializer {
    public void onStartup(ServletContext servletContext) throws ServletException {
        Dynamic servlet = servletContext.addServlet("myServlet", MyServlet.class);
        servlet.addMapping("/custom/**");
        FilterRegistration.Dynamic filter = servletContext.addFilter("myFilter", MyFilter.class);
        filter.addMappingForUrlPatterns(null, false, "/custom/*");
    }
}


在xml文件中声明DispatcherServlet

对基本的Spring MVC应用而言,需要配置DispatcherServletContextLoaderListenerweb.xml配置如下。

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

可以看到在web.xml中配置了DispatcherServletContextLoaderListener,并且定义了上下文,该上下文会被ContextLoaderListener加载,从中读取bean。也可指定DispatcherServlet的应用上下文并完成加载,配置web.xml如下。

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

上面使用DispatcherServletContextLoaderListener加载各自的上下文,但实际情况中,基于Java的配置更为通用,此时只需要配置DispatcherServletContextLoaderListener使用AnnotationConfigWebApplicationContext,这样它便可加载Java配置类,而非使用xml,可设置contextClassDispathcerServlet的初始化参数,如下所示。

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>ch7.RootConfig</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>ch7.WebConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>


处理multipart形式数据

处理multipart数据主要用于处理文件上传操作。需要配置multipart解析器读取multipart请求。


配置multipart解析器

DispatcherServlet并未实现任何解析multipart请求数据功能,它只是将任务委托给MultipartResolver策略接口实现,通过该实现解析multipart请求内容,Spring中内置了CommonsMultipartResolverStandardServletMultipartResolver两个解析器。

  • 使用StandardServletMultipartResolver

使用Java配置如下

@Override
protected void customizeRegistration(Dynamic registration) {
  registration.setMultipartConfig(new MultipartConfigElement("/tmp/spittr/uploads", 2 * 1024 * 1024, 4 * 1024 * 1024, 0));
}

使用xml配置如下,在servlet标签中配置multipart-config

<multipart-config>
        <location>/tmp/spittr/uploads</location>
        <max-file-size>2 * 1024 * 1024</max-file-size>
        <max-request-size>4 * 1024 * 1024</max-request-size>
      </multipart-config>
  • 使用CommonsMultipartResolver

使用Java配置如下

@Bean
    public MultipartResolver multipartResolver() throws IOException {
        CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();
        commonsMultipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));
        return commonsMultipartResolver;
    }


处理multipart请求

可在控制器的方法参数上添加@RequestPart注解,如下所示。

@RequestMapping(value="/register", method=POST)
public String processRegistration(
  @RequestPart("profilePicture") byte[] profilePicture,
  @Valid Spittr spitter,
  Errors errors) {
  profilePicture.transferTo(new File("/data/spittr" + profilePicture.getOriginalFilename()));
}


处理异常

Spring提供了多种方式将异常转换为响应

  • 特定的异常将会自动映射为指定的HTTP状态码。
  • 异常上可以添加@ResponseStatus注解,从而将其映射为某个HTTP状态码。
  • 在方法上可添加@ExceptionHandler注解,使其用来处理异常。


将异常映射为HTTP状态码

Spring异常与状态码对应关系如下。


编写异常处理方法

可在请求中直接使用try/catch处理异常,其与正常Java方法中的try/catch相同,同时,也可编写处理器来处理特定异常,当出现特定异常时,将有处理器委托方法进行处理。

@ExceptionHandler(DuplicateSpittleException.class)
public String handleDuplicateSpittle() {
  return "error/duplicate";
}


为控制器添加通知

控制器通知是任意带有@ControllerAdvice注解的类,该类包含如下类型的一个或多个方法。

  • @ExceptionHandler注解标注的方法。
  • @InitBinder注解标注的方法。
  • @ModelAttribute注解标注的方法。

上面方法会运用到整个应用程序所有控制器中带有@RequestMapping注解的方法上。

@ControllerAdvice
public class AppWideExceptionHandler {
  @ExceptionHandler(DuplicateSpittleException.class)
  public String duplicateSpittleHandler() {
    return "error/duplicate";
  }
}

经过上述配置,任意控制器方法抛出了DuplicateSpittleException异常,都会调用这个duplicateSpittleHandler方法处理异常。


跨重定向请求传递数据

对于重定向而言,若需要从发起重定向的方法传递数据给处理重定向方法中,有如下两种方法

  • 使用URL模版以路径变量和/或查询参数形式传递数据。
  • 通过flash属性发送数据。


通过URL模版进行重定向

如前面讲到的通过redirect:/spitter/{username}进行重定向,该方法会直接根据username确定url,并非十分安全的做法,可使用进行如下处理。

model.addAttribute("username", spitter.getUsername());
return "redirect:/spitter/{username}";

当需要传递参数,如id时,可进行如下处理。

model.addAttribute("username", spitter.getUsername());
model.addAttribute("spitterId", spitter.getId());
return "redirect:/spitter/{username}";

usernameleesfid123456。这样访问的url/spitter/leesf?spitterId=123456。这种方法只能传递简单的值,无法发送更为复杂的值,此时需要使用flash属性。


使用flash属性

通过RedirectAttributes设置flash属性,这样可直接传递对象。

@ReuqestMapping(value="/register", method=POST)
public String processRegistration(Spitter spitter, RedirectAttributes model) {
  spitterRepository.save(spitter);
  model.addAttribute("username", spitter.getUsername());
  model.addFlashAttribute("spitter", spitter);
  return "redirect:/spitter/{username}";
}

这样spitter对象也被传递到重定向页面中,可直接访问spitter对象。


总结


本篇博文讲解了如何配置DispatcherServletContextLoaderListener,以及如何处理异常和控制器通知,最后分析如何在重定向时传递数据。

目录
相关文章
|
3月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
366 0
|
4月前
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
382 0
|
2月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
3月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
223 1
|
3月前
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
424 1
|
3月前
|
Java 数据库连接 开发者
Spring Framework 核心技术详解
本文档旨在深入解析 Java Spring Framework 的核心技术原理与应用。与侧重于快速开发的 Spring Boot 不同,本文将聚焦于 Spring 框架本身的设计理念、核心容器、控制反转(IoC)、面向切面编程(AOP)、数据访问与事务管理等基础且强大的模块。通过理解这些核心概念,开发者能够更深刻地领悟 Spring 生态系统的设计哲学,并具备解决复杂企业级应用开发问题的能力。
256 4
|
3月前
|
前端开发 Java 开发者
MVC 架构模式技术详解与实践
本文档旨在全面解析软件工程中经典且至关重要的 MVC(Model-View-Controller) 架构模式。内容将深入探讨 MVC 的核心思想、三大组件的职责与交互关系、其优势与劣势,并重点分析其在现代 Web 开发中的具体实现,特别是以 Spring MVC 框架为例,详解其请求处理流程、核心组件及基本开发实践。通过本文档,读者将能够深刻理解 MVC 的设计哲学,并掌握基于该模式进行 Web 应用开发的能力。
556 1
|
4月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
353 2
|
3月前
|
监控 Java API
Spring WebFlux 响应式编程技术详解与实践指南
本文档全面介绍 Spring WebFlux 响应式编程框架的核心概念、架构设计和实际应用。作为 Spring 5 引入的革命性特性,WebFlux 提供了完全的响应式、非阻塞的 Web 开发栈,能够显著提升系统的并发处理能力和资源利用率。本文将深入探讨 Reactor 编程模型、响应式流规范、WebFlux 核心组件以及在实际项目中的最佳实践,帮助开发者构建高性能的响应式应用系统。
644 0
|
3月前
|
监控 Cloud Native Java
Spring Integration 企业集成模式技术详解与实践指南
本文档全面介绍 Spring Integration 框架的核心概念、架构设计和实际应用。作为 Spring 生态系统中的企业集成解决方案,Spring Integration 基于著名的 Enterprise Integration Patterns(EIP)提供了轻量级的消息驱动架构。本文将深入探讨其消息通道、端点、过滤器、转换器等核心组件,以及如何构建可靠的企业集成解决方案。
317 0

热门文章

最新文章