【小家Spring】Spring MVC好用工具介绍:UrlPathHelper、WebUtils、RequestContextUtils、WebApplicationContextUtils...(下)

简介: 【小家Spring】Spring MVC好用工具介绍:UrlPathHelper、WebUtils、RequestContextUtils、WebApplicationContextUtils...(下)

WebApplicationContextUtils


当 Web 应用集成 Spring 容器后,这个工具类就可以很方便的访问出一些web组件。比如`.


  @Nullable
  public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
    return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
  }
  //Required这个方法和上面唯一的区别是:它如果返回null 就直接抛出异常了,上面是返回null
  public static WebApplicationContext getRequiredWebApplicationContext(ServletContext sc) throws IllegalStateException {
    WebApplicationContext wac = getWebApplicationContext(sc);
    if (wac == null) {
      throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
    }
    return wac;
  }
  // 我在讲解源码的时候:创建容器失败的时候,也会吧异常放进来(我们调用者一般较少使用)
  public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) { ... }
  // 这个可以说是上面的加强版。当getWebApplicationContext(sc)没找到时,还会试从ServletContext的属性中查找唯一的一个WebApplicationContext
  // 如果找到的WebApplicationContext不唯一,则抛出异常声明该情况
  public static WebApplicationContext findWebApplicationContext(ServletContext sc) { ... }
  //向WebApplicationContext使用的BeanFactory注册web有关作用域对象 :
  public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory,
      @Nullable ServletContext sc) {
    beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
    beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
    if (sc != null) {
      ServletContextScope appScope = new ServletContextScope(sc);
      beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
      // Register as ServletContext attribute, for ContextCleanupListener to detect it.
      // 此处,还吧ServletContext上下文的Scope,注册到上下文里,方便ContextCleanupListener 进行获取
      sc.setAttribute(ServletContextScope.class.getName(), appScope);
    }
    // 定义注入规则。当开发人员依赖注入ServletRequest对象时,注入的bean其实是这里的RequestObjectFactory工厂bean
    beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
    beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
    beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
    // ServletWebRequest 里面既有request,也有response
    beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
    if (jsfPresent) {
      FacesDependencyRegistrar.registerFacesDependencies(beanFactory);
    }
  }


接下来看看这个方法registerEnvironmentBeans:


  public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf,
      @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) {
    // 把servletContext和servletConfig以Bean的形式,注册到容器里面,这样我们就可以@Autowired了  如下面例子
    if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
      bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
    }
        if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
      bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
    }
    //这个特别特别重要:我们可以看到Spring在启动的时候,把ServletContext里面所有所有的InitParameter都拿出来了,存到一个Map里面
    // 最后把这个Bean注册到容器里面了,Bean名称为:contextParameters
    // 这就是为什么,后面我们可以非常非常方便拿到initParam的原因~~~
    if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
      Map<String, String> parameterMap = new HashMap<>();
      if (servletContext != null) {
        Enumeration<?> paramNameEnum = servletContext.getInitParameterNames();
        while (paramNameEnum.hasMoreElements()) {
          String paramName = (String) paramNameEnum.nextElement();
          parameterMap.put(paramName, servletContext.getInitParameter(paramName));
        }
      }
      if (servletConfig != null) {
        Enumeration<?> paramNameEnum = servletConfig.getInitParameterNames();
        while (paramNameEnum.hasMoreElements()) {
          String paramName = (String) paramNameEnum.nextElement();
          parameterMap.put(paramName, servletConfig.getInitParameter(paramName));
        }
      }
      bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
          Collections.unmodifiableMap(parameterMap));
    }
    // 原理同上,这里吧ServletContext里面的contextAttributes,都以Bean的形式放进Bean容器里了
    if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
      Map<String, Object> attributeMap = new HashMap<>();
      if (servletContext != null) {
        Enumeration<?> attrNameEnum = servletContext.getAttributeNames();
        while (attrNameEnum.hasMoreElements()) {
          String attrName = (String) attrNameEnum.nextElement();
          attributeMap.put(attrName, servletContext.getAttribute(attrName));
        }
      }
      bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
          Collections.unmodifiableMap(attributeMap));
    }
  }


因为可以看到上面已经注册了Bean,因此我们可以这么来使用,直接注入即可:


    @Autowired
    private ServletContext servletContext;
    @Autowired
    private ServletConfig servletConfig;
    @ResponseBody
    @GetMapping("/hello")
    public String helloGet() {
        System.out.println(servletContext); //org.apache.catalina.core.StandardWrapperFacade@1f3768f6
        System.out.println(servletConfig); //org.apache.catalina.core.StandardContext$NoPluggabilityServletContext@73ced3c2
        return "hello...Get";
    }
  //将 servletContext、servletConfig 添加到 propertySources
  public static void initServletPropertySources(MutablePropertySources sources,
      @Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { ... }



UrlPathHelper


这个帮助类非常的重要了,位于包org.springframework.web.util内。它帮助Spring MVC处理URL相关的各种难题,先介绍它的几个属性~~~

public class UrlPathHelper {
  // 是否总是按照全路径 默认是false(一般不改~) 
  private boolean alwaysUseFullPath = false;
  // 是否对url进行解码(默认都是需要解码的)  解码可以是request.getCharacterEncoding()。若没指定就是下面的defaultEncoding 
  private boolean urlDecode = true;
  // 设置是否应从请求URI中删除“;”(分号)
  private boolean removeSemicolonContent = true;
  // 默认编码是它:ISO-8859-1
  private String defaultEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING;
  ...
}


它的API具体如图:


image.png


简单使用Demo如下:(我的请求地址为:http://localhost:8080/demo_war_war/api/v1/hello


    @ResponseBody
    @GetMapping("/hello")
    public String helloGet(HttpServletRequest request) throws Exception {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        System.out.println(urlPathHelper.getLookupPathForRequest(request)); // /api/v1/hello
        System.out.println(urlPathHelper.getOriginatingContextPath(request)); // /demo_war_war
        System.out.println(urlPathHelper.getContextPath(request)); // /demo_war_war
        System.out.println(urlPathHelper.getServletPath(request)); // /api/v1/hello
        System.out.println(urlPathHelper.getRequestUri(request)); // /demo_war_war/api/v1/hello
        return "hello...Get";
    }



总之它就是Spring用来处理URL的工具类,若你在你的项目中有类似的需要,也可以参考使用的。同时还有:UriUtils、UriComponents、UriComponentsBuilder等等

总结


Spring-web这个jar包内提供给我们还是有几个比较好用的类的,大家知悉即可。

特别是request的包装类,还是非常好用的~

相关文章
|
27天前
|
Java Maven Spring
【Spring工具插件】lombok使用和EditStarter插件
本文第一个板块主要介绍了SpringMVC中lombok依赖的引入,和相应的使用方法,以及浅显的原理解释,第二个板块主要介绍EditStarter插件的安装与使用
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
83 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
1月前
|
设计模式 前端开发 Java
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
通过对 `DispatcherServlet`源码的深入剖析,我们了解了SpringMVC请求处理的全流程。`DispatcherServlet`作为前端控制器,负责请求的接收和分发,处理器映射和适配负责将请求分派到具体的处理器方法,视图解析器负责生成和渲染视图。理解这些核心组件及其交互原理,有助于开发者更好地使用和扩展SpringMVC框架。
51 4
|
2月前
|
前端开发 Java 开发者
Spring MVC中的请求映射:@RequestMapping注解深度解析
在Spring MVC框架中,`@RequestMapping`注解是实现请求映射的关键,它将HTTP请求映射到相应的处理器方法上。本文将深入探讨`@RequestMapping`注解的工作原理、使用方法以及最佳实践,为开发者提供一份详尽的技术干货。
190 2
|
3月前
|
JSON 前端开发 Java
SSM:SpringMVC
本文介绍了SpringMVC的依赖配置、请求参数处理、注解开发、JSON处理、拦截器、文件上传下载以及相关注意事项。首先,需要在`pom.xml`中添加必要的依赖,包括Servlet、JSTL、Spring Web MVC等。接着,在`web.xml`中配置DispatcherServlet,并设置Spring MVC的相关配置,如组件扫描、默认Servlet处理器等。然后,通过`@RequestMapping`等注解处理请求参数,使用`@ResponseBody`返回JSON数据。此外,还介绍了如何创建和配置拦截器、文件上传下载的功能,并强调了JSP文件的放置位置,避免404错误。
|
3月前
|
Java BI API
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
这篇文章介绍了如何在Spring Boot项目中整合iTextPDF库来导出PDF文件,包括写入大文本和HTML代码,并分析了几种常用的Java PDF导出工具。
816 0
spring boot 整合 itextpdf 导出 PDF,写入大文本,写入HTML代码,分析当下导出PDF的几个工具
|
4月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
3月前
|
前端开发 Java 应用服务中间件
【Spring】Spring MVC的项目准备和连接建立
【Spring】Spring MVC的项目准备和连接建立
74 2
|
3月前
|
XML 前端开发 Java
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
272 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
|
3月前
|
监控 Java 对象存储
监控与追踪:如何利用Spring Cloud Sleuth和Netflix OSS工具进行微服务调试
监控与追踪:如何利用Spring Cloud Sleuth和Netflix OSS工具进行微服务调试
64 1