热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SpringBootWeb应用源码解析:遗失的web.xmI

SpringBootWeb应用源码解析在Spring及SpringBoot的使用过程中,应用最广泛的当属Web应用,而Web应用又往往部署在像Tomc

SpringBootWeb应用源码解析

在 Spring 及 Spring Boot 的使用过程中,应用最广泛的当属 Web 应用,而 Web 应用又往往部署在像 Tomcat 这样的 Servlet 容器中。

本章将带领大家学习 Spring Boot 中 Web 应用的整合以及在此过程中与直接使用 Spring 的差别。


遗失的web.xmI

提到 Spring 的 Web 应用,我们首先想到的可能是 Spring MVC 框架和 web.xmI 等配置文件。而 Spring MVC 又是围绕 DispatcherServlet 这个核心类来展开的。

Spring Boot 当前是基于 Spring 5.2.x 版本,和传统的 Spring 启动有所不同。以前是通过在web.xml 中 配 置 Servlet 来 完 成 Spring MVC 的 启 动 , 但 在 Spring Boot 中 是 通 过Dispatch-erServletAutoConfiguration 来完成初始化工作的。在此过程中,web.xml 遗失了。

我们先回顾一下 Servlet 3.0 之前版本的操作。当我们创建一个 web 项目时,往往会在resources/WEB-INF 目录下创建一个 web.xml 文件, 该文件内配置了 Servlet 和 Filter 等功能。当 Spring MVC 出现后,web.xml 中 便有了 DispatcherServlet 的配置。

随着 Java EE 6 的发布,Servlet 3.0 作为 Java EE 6 规范体系的一员,也被慢慢推广并被用户接受。 Servlet 3.0 在 Servlet 25 的基础. 上提供了一些简化 Web 应用的开发和部署的新特性,无 xml 配置便是其中一项。

Servlet 3.0 提供了@WebServlet、@WebFilter 等注解, 可以使用注解来声明 Servlet 和Filter,这便有了抛弃 web.xml 的基础。同时,它还提供了可以在运行时动态注册 Servlet、Filter、 Listener 等更加强大的功能。 关于动态配置 Servlet,如果翻看 Servlet 3.0 中servlet-api 包下 ServletContext 接口定义的方法,你会看到如下方法定义。

public ServletRegistration. Dynamic addServlet(String servletName, String clas sName);

public ServletRegistration . Dynamic addServlet(String servletName, Servlet s

ervlet);

public ServletRegistration . Dynamic addServlet(String servletName,Class

xtends Servlet> servletClass);public T createServlet(Class clazz)throws ServletExc

eption;

public ServletRegistration getServletRegistration(String servletName);

public Map getServletRegistrations

();

}

在 Servlet 3.0 中还新增了 ServletContainerlnitializer 接口,在容器启动时使用 JAR 服务 API来发现其实现类,并将容器 WEB-INF/ib 目录下 jar 包中的类都交由该类的 onStartup 方法来处理。而 Servlet 和 Filter 在 Web 应用启动时可借助该接口的实现类和 Java 的 SPI 机制完成加载。

在Spring中 提 供 了ServletContainerlnitializer接 口 的 实 现 类SpringServletContainerlni-tializer, 该 类 在 其 onStartup 方 法 中 会 调 用 所 有WebApplicationInitializer 实现类的 onStartup 方法,将相关组件注册到容器中。而 Servlet和 Filter 也是 通过 WebApplicationitializer 的实现类完成创建和加载的。

基于以上新特性和演变,当我们使用 Spring Boot 时,Spring Boot 已经不知不觉地开始使用这些新特性了。至此,我们从发展的角度了解了 web.xml 消失的过程,在后面的章节我会详细讲解 Spring Boot 是如何进行 Web 应用的自动配置的。

SpringBootWeb应用源码解析:遗失的web.xmI


Web应用的自动配置

在 Spring Boot 项目中引入 spring-boot-starter-web 的依赖,Spring Boot 的自动配置机制便会加载并初始化其相关组件。整个自动配置原理在前面章节已经讲过,这里针对 Web 应用再进行一-次梳理。

在上一节中我们已经提到,Servlet3.0 中新增了ServletContainerlnitializer 接 口 , 而 在 Spring 中 又 提 供 了 其 实 现 类SpringServletContainerlnitializer 来 初 始 化 Servlet 。 但 在 Spring Boot 中 , 当 引 入spring-boot-starter-web 的依赖之后,Spring Boot 并未完全遵守 Servlet 3.0 的规范,也没有使用 Spring 中提供的 SpringServletContainerlnitializer 类,而是完全选择另外一套初始化流程。下面, 我们看一下初始化流程的源码。

根据自动配置的原理,我们在 spring-boot-autoconfigure 包中的 META-INF/spring.factories配置文件中找到了针对 Servlet 自动配置的 EnableAutoConfiguration。

#自动配置

org. springframework . boot . autoconfigure . EnableAutoConfiguration=\

org. springframework. boot . autoconfigure . web. servlet . DispatcherServletAutoCon下面对 EnableAutoConfiguration 类中的自动配置项目进行逐步分析。

DispatcherServlet 自动配置

DispatcherServlet 自动配置位于 DispatcherServletAutoConfiguration 类中。下面我们通过DispatcherServletAutoConfiguration 的源码来 了解其自动配置的过程。

首先来看 DispatcherServletAutoConfiguration 上面的注解。

@Configuration(proxyBeanMethods = false)

@ConditionalOnWebApplication(type = Type . SERVLET)

@ConditionalOnClass(DispatcherServlet. class)

@AutoConfigureAfter(ServletwWebServerFactoryAutoConfiguration. class)

public class DispatcherServletAutoConfiguration {}

这些注解的基本功能在前面章节已经提到过,我们再来温习一下。


  • @AutoConfigureOrder:指定自动配置加载的顺序。
  • @Configuration:指定该类为配置类,交给 Spring 容器管理,默认指定不使用代理。
  • .@ConditionalOmWebApplication:表示只有 Web 应用才会加载此类。
  • @ConditionalOnClass:表示只有存在 DispatcherServlet 类的情况下才会加载此类。
  • . @AutoConfigureAfter : ServletWebServerFactoryAutoConfiguration 加载完成之后才会加此 类。

关于 ServletWebServerFactoryAutoConfiguration 的加载会在下一章中详细讲解。

从整体上来看,在 DispatcherServletAutoConfiguration 内部主要提供 了 4 个静态内部类。


  • :DispatcherServletConfiguration:主 要用来初始化 DispatcherServlet。
  • :DispatcherServletRegistrationConfiguration :主要用来将 DispatcherServlet 注册到系统中。
  • :DefaultDispatcherServletCondition :主要针对容器中 DispatcherServlet 进行一些逻辑判断。
  • :DispatcherServletRegistrationCondition :

主要针对注册 DispatcherServlet 进行一些逻辑判断。

针对以上概述,下面来看具体的源代码实现。首先是内部类 DispatcherServletConfiguration的源码及功能。

@Configuration(proxyBeanMethods = false)

//实例化配置类

@Conditional (DefaultDispatcherServletCondition.class) //实例化条件:通过该

@ConditionalOnClass (ServletRegistration. class)

//存在指定的 ServletRe

gistration 类//加裁 HttpProperties 和 webMvcProperties

@EnableConfigurationProperties({ HttpProperties. class, WebMvcProperties .cla

s })

protected static class DispatcherServletConfiguration {

@Bean(name = DEFAULT DISPATCHER_ SERVLET_ BEAN NAME)

public DispatcherServlet dispatcherServlet (HttpProperties httpProperties ,

WebMvcProperties webMvcProperties) {

//创建 DispatcherServlet

DispatcherServlet dispatcherServlet = new DispatcherServlet();

//初始化 DispatcherServlet 各项配置

dispatcherServlet . setDispatchOptionsRequest (webMvcProperties . isDispatch

OptionsRequest());

dispatcherServlet . setDispatchTraceRequest (webMvcProperties . isDispatch-

TraceRequest());

dispatcherServlet. setThrowExceptionI fNoHandlerFound(webMvcProperties. is

ThrowExcept ionIfNoHandlerFound();

di spatcherServlet . setPublishEvents (webMvcProperties . isPublishRequestHan

dledEvents());

dispatcherServlet . setEnableLoggingReques tDetails (httpProperties. isLog-

RequestDetails());

return dispatcherServlet;

//初始化上传文件的解析器

@Bean

@ConditionalOnBean(MultipartResolver . class)

@ConditionalOnMissingBean(name = DispatcherServlet . MULTIPART_ RESOLVER_

BEA

NAME)

public MultipartResolver multipartResolver(MultipartResolver resolver) {

//检测用户是否创建了 MultipartResolver, 但命名不正确

return resolver;

}

}

通过以上源码可以看出,当满足指定的条件后,会对 DispatcherServletConfiguration 进行实例化,而该类内部通过@Bean 注解的方法会被实例化,生成 Bean 并注入 Spring 容器中。

其中,在 DispatcherServlet 方法中完成 了 DispatcherServlet 的实例化和基本设置。这里既没有用到 SPI 机制,也没用到 Spring 提供的 SpringServletContainerlnitializer 和 Servlet3.0 的 ServletContainerlnitializer 接口,从而验证了 6.2 节提到的说法。

DispatcherServlet 方法将 DispatcherServlet 实例化的 Bean 注入 Spring 容器中,并且指定Bean 的 name 为 dispatcherServlet。该名称默认会被映射到根 URL 的/访问路径。

DispatcherServlet 作为前端控制器设计模式的实现,提供了 Spring WebMVC 的集中访问点,负责职责的分派,与 Spring loc 容器无缝集成,可以获得 Spring 的所有好处。它的主要作用包括:文件上传解析、请求映射到处理器、通过 ViewResolver 解析逻辑视图名到具体视图实现、本地化解析、渲染具体视图等。

在未使用 Spring Boot 时,通常 DispatcherServlet 类的配置需要开发人员在 web.xml 当中进行配置。这里 Spring Boot 通过自动配置完成了 DispatcherServlet 类的配置和初始化,并 在 此 过 程 中 设 置 了 一 些 初 始 化 的 参 数 。 这 些 参 数 通 过 HttpProperties 和WebMvcProperties 获得。

DispatcherServletConfiguration 中还定义了上传文件的解析器 MultipartResolver 的 Bean初始化操作,准确来说是 Bean 名称转化的操作。通过条件注解判断,当 MultipartResolver的 Bean 存在,但 Bean 的名称不为“multipartResolver”时,将其重命名为“multipartResolver'我们再回到 DispatcherServletConfiguration 的注解部分,@Conditional 指定的限定条件类为 DefaultDispatcherServletCondition,该类是 DispatcherServletAutoConfiguration 的另外一个内部类,代码如下。

@Order (Ordered. LOWEST_ PRECEDENCE- 10)

private static class DefaultDispatcherServletCondition extends SpringBootCo

ndition {

@Override

public ConditionOutcome getMatchOutcome (ConditionContext context ,

AnnotatedTypeMetadata metadata) {

ConditionMessage . Builder message = ConditionMessage

. forCondition("Default DispatcherServlet");

ConfigurablelistableBeanFactory beanFactory = context. getBeanFactory();

//获取类型为 Di spatcherServlet 的 Bean 名称列表

List dispatchServletBeans = Arrays . asList(beanFactory

. getBeanNamesForType

(DispatcherServlet.class, false, false));

//如果 Bean 名称列表中包含 dispatcherServlet,则返回不匹配

if (dispatchServletBeans. contains (DEFAULT_ DISPATCHER_ SERVLET_ BEAN_ NAM

E)) {

return ConditionOutcome . noMatch (message . found("dispatcher servlet bea

n")

. items (DEFAULT_ DISPATCHER_ SERVLET_ BEAN_ NAME));

// 如果 beanFactory 中包含名称为 Di spatcherServlet 的 Bean, 则返回不匹配

if (beanFactory. containsBean(DEFAULT_ DISPATCHER_ SERVLET_ BEAN NAME)) {

return ConditionOutcome

. noMatch(message . found("non dispatcher servlet bean")

. items (DEFAULT_ DISPATCHER_ SERVLET_ BEAN_ NAME));

//如果 Bean 名称列表为空,则返回匹配

if (dispatchServletBeans . isEmpty()) {

return ConditionOutcome

. match(message . didNotFind(”dispatcher servlet beans").atAll());

//其他情况则返回匹配

return ConditionOutcome . match(message

. found("dispatcher servlet bean", "dispat

cher servlet beans")

. items (Style . QUOTE, dispatchServletBeans)

. append("and none is named ”+ DEFAULT_ DI

SPATCHER_ SERVLET_ BEAN_

NAME));

}

}

DefaultDispatcherServletCondition 的最核心业务逻辑只做了一件事,那就是:防止重复生成DispatcherServlet。具体实现流程为:从上下文中获得 beanFactory, 然后通过 beanFactory获取类型为 DispatcherServlet 的 Bean 的 name 列表,然后分别 判断 name 列表和beanFactory 中是否包含名称为“dispatcherServlet"的字符串或 Bean,如果包含则返回不匹配(已经存在,不匹配则不会重复实例化),否则返回匹配。

DispatcherServletConfiguration 类中还有-个注解@EnableConfigurationProperties,该注解指定了两个配置类:

HttpProperties 和 WebMvcProperties。这两个配置类正是上面初始化 DispatcherServlet 时用于初始化的参数值,查看这两个类的源代码就会发现,它们分别对应加载了以“spring.http"和"spring.mvc"为前缀的配置项,可以在 application properties 文件中进行配置。

@ConfigurationProperties(prefix = "spring . http" )

public class HttpProperties {}

@ConfigurationProperties(prefix = "spring . mvc")

public class WebMvcProperties {}

SpringBootWeb应用源码解析:遗失的web.xmI

DispatcherServletRegistrationBean 自动配置

下面我们再来看用于注册的 DispatcherServletRegistrationConfiguration 类。关于该类的注解功能可以参考 DispatcherServletConfiguration 的说明,我们主要看:业务逻辑处理。

@Configuration( proxyBeanMethods = false)

@Conditional (DispatcherServletRegistrationCondition. class)

@ConditionalOnClass (ServletRegistration. class)

@EnableConfigurationProperties (WebMvcProperties .class)

@Import (DispatcherServletConfiguration.class)

protected static class DispatcherServletRegistrationConfiguration {

@Bean(name = DEFAULT_ DISPATCHER_ SERVLET_ REGISTRATION_ BEAN AME)

@ConditionalOnBean(value=

DispatcherServlet.class,

name=DEFAULT_

DISPATCHER_

SERVLET_ BEAN_ NAME)

public

DispatcherServletRegistrationBean

di

spatcherServletRegistration(DispatcherServlet dispatcherServlet,

n We

bMvcProperties webMvcProperties, objectProvider ul

tipartConfig) {

//通过 ServletRegistrat ionBean 将 dispatcherServlet 注册为 Servlet,这样 serv

Let 才会生效

Di spatcherServletRegistrationBean registration = new DispatcherServletR

egistrationBean( dispatcherServlet ,

webMvcProperties . getServlet(). getPath());

//设置名称为 di spatcherServlet

registration. setName(DEFAULT_ DISPATCHER_ SERVLET_ BEAN NAME);

// 没 置 加 载 优 先 级 , 没 置 值 默 认 为 -1 , 存 在 FwebMvcProperties 类 中 registration.

setLoadOnStartup(webMvcProperties . getServlet(). getLoadOn-Startup());

multipartConfig. ifAvailable(registration::setMultipartConfig);

return registration;

}

}

DispatcherServletRegistrationConfiguration 类的核心功能就是注册 dispatcherServlet,使其生效并设置一一些初始化的参数。

其 中 DispatcherServletRegistrationBean 继 承 自 ServletRegistrationBean , 主 要 为DispatcherServlet 提供服务。

DispatcherServletRegistrationBean 和 DispatcherServlet 都提 供了注 册 Servlet 并公开DispatcherServletPath 信息的功能。

在 dispatcherServletRegistration 方 法 中 直 接 通 过 new 来 创 建DispatcherServletRegistrationBean,第一个 参数为 DispatcherServlet,第二个参数为application 配置文件中配置的 path 值,相关代码如下。

public class DispatcherServletRegistrationBean extends ServletRegistratiomB

ean implements Di spatcherServletPath {

private final String path;

//根据指定的 DispatcherServlet 和给定的 path 创建 DispatcherServletRegistratio

nBean

public DispatcherServletRegistrationBean(DispatcherServlet servlet, Strin3 path) {

super(servlet);

Assert . notNull(path, "Path must not be null");

this.path = path;

super . addUrlMappings (getServletUrlMapping());

/重写父类的方法,但抛出异常,相当于禁用该操作

@Override

public void setUrlMappings (Collection urlMappings) {

throw new UnsupportedOperationException("URL Mapping cannot be changed

on a DispatcherServlet registration");

//重写父类的方法,但抛出异常,相当于禁用该操作

@verride

public void addUrlMappings(String... urlMappings) {

throw new UnsupportedOperationException("URL Mapping cannot be changed

on a DispatcherServlet registration");

}

}

在 DispatcherServletRegistrationBean 中实现了 setUrlMappings 和 addlUrlManninas 两种方法,但均直接抛出异常,这相当于禁用了该子类中这两项操作。而在构造方法中除了成员变 量 赋 值 之 外 , 还 调 用 了 父 类 ServletRegistrationBean 的 构 造 方 法ServletRegistrationBean(Tservlet,String...urlMappings)和addUrlMappings(String...urlMappings)方法。

关于 ServletRegistrationBean 的构造方法和 addUrlMappings 只是进行成员变量的赋值和设 置 , 我 们 重 点 看 DispatcherServletRegistrationBean 在 构 造 方 法 中 调 用 的getServletUrlMapping 方法。顾名思义,该方法的功能是获取 Servlet 的 URL 的匹配。该方法具体在 DispatcherServletRegistrationBean 实现的接口 DispatcherServletPath 中定义。

DispatcherServletPath 的 主 要 功 能 是 提 供 自 动 配 置 所 需 的 path 信 息 , 而DispatcherServletRegistrationBean 中的 path 信息正是构造方法传入的。

下面我们来看 DispatcherServletPath 中 getServletUrlMapping 方法的具体实现。

@FunctionalInterface

public interface DispatcherServletPath {

//返回一个 URL 匹配表达式,用 FServletRegistrat ionBean 映射对应的 DispatcherSe

rvlet

default String getServletUrlMapping() {

if (getPath(). equals("") || getPath(). equals("/")) {

return "/";

if (getPath(). contains("*")) {

return getPath();

if (getPath(). endsWith("/")) {

return getPath() + *";

return getPath() + "/*";

}

}

getServletUrlMapping 方法为接口的默认实现方法,返回一个用于 ServletRegistrationBean映射 DispatcherServlet 的 URL 表达式。判断逻辑比较简单:如果获得的 path 为空或“/”,则返回“/”; 如果 path 中包含“”,则直接返回 path;如果 path 以“/"结尾,则对 path 后追加“”;其他 情 况 下 , path 后 面 追 加 关 于 dispatcherServletRegistration 方 法 中 对DispatcherServletRegistrationBean 其他属性的简单赋值操作就不再赘述了。

我们再回到针对 DispatcherServletRegistrationConfiguration 的注解@Conditional 指定的限定条件类 DispatcherServletRegistrationCondition,该限定条件类主要用来判断进行dis-patcherServlet 和 dispatcherServletRegistration 是否存在等。

DispatcherServletRegistrationCondition 中判断条件及代码较多,这里只展示顶层判断方法的源代码。

@Order (Ordered. LOWEST_ PRECEDENCE - 10)

private static class DispatcherServletRegistrationCondition extends SpringBoot-Condition

{

@Override

public ConditionOutcome getMatchOutcome(ConditionContext context, Annotated-

TypeMetadata metadata) {

ConfigurableListableBeanFactory beanFactory = context . getBeanFactory();

//判断是否重复存在 dispatcherServlet

ConditionOutcome outcome = checkDefaultDispatcherName (beanFactory);

if (!outcome . isMatch()) {

return outcome ;//判断是否重复存在 dispatcherServletRegistration

return checkServletRegistration(beanFactory);

}

DispatcherServletRegistrationCondition 的 getMatchOutcome 方 法 中 分 别 判 断 了dispatcherServlet 和 dispatcherServletRegistration 是否已经存在对应的 Bean。具体判断方法基本与上节讲到的 DefaultDispatcherServletCondition 的判断方法一致。

至此,在该自动配置类中,DispatcherServlet 的创建、 简单初始化和注册已经完成。当第一次接收到网络请求时,DispatcherServlet 内部会进行一 系列的初始化操作,这些更多属于 Spring 的内容,就不再展开了。

SpringBootWeb应用源码解析:遗失的web.xmI


本文给大家讲解的内容是SpringBootWeb应用源码解析:遗失的web.xmI和Web应用的自动配置


  1. 下篇文章给大家讲解的是SpringBootWeb应用源码解析:Spring MVC 的自动配置;
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!

推荐阅读
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
  • 解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因
    本文介绍了解决java.lang.IllegalStateException: ApplicationEventMulticaster not initialized错误的方法和原因。其中包括修改包名、解决service name重复、处理jar包冲突和添加maven依赖等解决方案。同时推荐了一个人工智能学习网站,该网站内容通俗易懂,风趣幽默,值得一看。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 本文讨论了如何在codeigniter中识别来自angularjs的请求,并提供了两种方法的代码示例。作者尝试了$this->input->is_ajax_request()和自定义函数is_ajax(),但都没有成功。最后,作者展示了一个ajax请求的示例代码。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 本文讨论了在ASP中创建RazorFunctions.cshtml文件时出现的问题,即ASP.global_asax不存在于命名空间ASP中。文章提供了解决该问题的代码示例,并详细解释了代码中涉及的关键概念,如HttpContext、Request和RouteData等。通过阅读本文,读者可以了解如何解决该问题并理解相关的ASP概念。 ... [详细]
author-avatar
mobiledu2502898013
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有