导航:首页 > 源码编译 > springboot启动类源码

springboot启动类源码

发布时间:2022-09-07 15:47:32

‘壹’ spring boot启动不扫描创建bean怎么回事

说明你的spring boot启动时的application类不在io.github.gefangshuai.app及其子包下。

‘贰’ 怎么学习spring boot 源码

可以根据官网的示例来学习。

‘叁’ Feign源码解析二

本文会基于Feign源码,看看Feign到底是怎么实现远程调用

上文中,我们的 user-service 服务需要调用远程的 order-service 服务完成一定的业务逻辑,而基本实现是order-service提供一个spi的jar包给user-service依赖,并且在user-service的启动类上添加了一个注解

这个注解就是@EnableFeignClients,接下来我们就从这个注解入手,一步一步解开Feign的神秘面纱

该注解类上的注释大概的意思就是:
扫描那些被声明为 Feign Clients (只要有 org.springframework.cloud.openfeign.FeignClient 注解修饰的接口都是Feign Clients接口)的接口

下面我们继续追踪源码,看看到底什么地方用到了这个注解
利用IDEA的查找调用链快捷键,可以发现在.class类型的文件中只有一个文件用到了这个注解

OK,下面主要就是看这个类做了什么

通过UML图我们发现该类分别实现了 ImportBeanDefinitionRegistrar , ResourceLoaderAware 以及 EnvironmentAware 接口
这三个接口均是spring-framework框架的spring-context模块下的接口,都是和spring上下文相关,具体作用下文会分析

总结下来就是利用这两个重要属性,一个获取应用配置属性,一个可以加载classpath下的文件,那么FeignClientsRegistrar持有这两个东西之后要做什么呢?

上面将bean配置类包装成 FeignClientSpecification ,注入到容器。该对象非常重要,包含FeignClient需要的 重试策略 , 超时策略 , 日志 等配置,如果某个FeignClient服务没有设置独立的配置类,则读取默认的配置,可以将这里注册的bean理解为整个应用中所有feign的默认配置

由于 FeignClientsRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,这里简单提下这个接口的作用
我们知道在spring框架中,我们如果想注册一个bean的话主要由两种方式:自动注册/手动注册

知道了 ImportBeanDefinitionRegistrar 接口的作用,下面就来看下 FeignClientsRegistrar 类是何时被加载实例化的

通过IDEA工具搜索引用链,发现该类是在注解@EnableFeignClients上被import进来的,文章开始的图片中有

这里提下@Import注解的作用

该注解仅有一个属性value,使用该注解表明导入一个或者多个@Configuration类,其作用和.xml文件中的<import>等效,其允许导入@Configuration类,ImportSelector接口/ImportBeanDefinitionRegistrar接口的实现,也同样可以导入一个普通的组件类

注意,如果是XML或非@Configuration的bean定义资源需要被导入的话,需要使用@ImportResource注解代替

这里我们导入的FeignClientsRegistrar类正是一个ImportBeanDefinitionRegistrar接口的实现

FeignClientsRegistrar重写了该接口的 registerBeanDefinitions 方法,该方法有两个参数注解元数据 metadata 和bean定义注册表 registry

该方法会由spring负责调用,继而注册所有标注为@FeignClient注解的bean定义

下面看registerBeanDefinitions方法中的第二个方法,在该方法中完成了所有@FeignClient注解接口的扫描工作,以及注册到spring中,注意这里注册bean的类型为 FeignClientFactoryBean ,下面细说

总结一下该方法,就是扫描@EnableFeignClients注解上指定的basePackage或clients值,获取所有@FeignClient注解标识的接口,然后将这些接口一一调用以下 两个重要方法 完成 注册configuration配置bean 和注册 FeignClient bean

断点位置相当重要

BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);

这里是利用了spring的代理工厂来生成代理类,即这里将所有的 feignClient的描述信息 BeanDefinition 设定为 FeignClientFactoryBean 类型,该类继承自FactoryBean,因此这是一个代理类,FactoryBean是一个工厂bean,用作创建代理bean,所以得出结论,feign将所有的 feignClient bean定义的类型包装成 FeignClientFactoryBean

最终其实就是存入了BeanFactory的beanDefinitionMap中

那么代理类什么时候会触发生成呢? 在spring 刷新容器时 ,会根据beanDefinition去实例化bean,如果beanDefinition的beanClass类型为代理bean,则会调用其 T getObject() throws Exception; 方法生成代理bean,而我们实际利用注入进来的FeignClient接口就是这些一个个代理类

这里有一个需要注意的点,也是开发中会遇到的一个 启动报错点
如果我们同时定义了两个不同名称的接口 (同一个包下/或依赖方指定全部扫描我们提供的 @FeignClient ),且这两个 @FeignClient 接口注解的 value/name/serviceId 值一样的话,依赖方拿到我们的提供的spi依赖,启动类上 @EnableFeignClients 注解扫描能同时扫描到这两个接口,就会 启动报错

原因就是Feign会为每个@FeignClient注解标识的接口都注册一个以serviceId/name/value为key,FeignClientSpecification类型的bean定义为value去spring注册bean定义,又默认不允许覆盖bean定义,所以报错

官方提示给出的解决方法要么改个@FeignClient注解的serviceId,name,value属性值,要么就开启spring允许bean定义覆写

至此我们知道利用在springboot的启动类上添加的@EnableFeignClients注解,该注解中import进来了一个手动注册bean的 FeignClientsRegistrar注册器 ,该注册器会由spring加载其 registerBeanDefinitions方法 ,由此来扫描所有@EnableFeignClients注解定义的basePackages包路径下的所有标注为@FeignClient注解的接口,并将其注册到spring的bean定义Map中,并实例化bean

下一篇博文中,我会分析为什么我们在调用(@Resource)这些由@FeignClient注解的bean的方法时会发起 远程调用

‘肆’ 学习java的同学都是怎么读源码的

刚参加工作那会,没想过去读源码,更没想过去改框架的源码;总想着别人的框架应该是完美的、万能的,应该不需要改;另外即使我改了源码,怎么样让我的改动生效了?项目中引用的不还是没改的jar包吗。回想起来觉得那时候的想法确实挺??

工作了一年多之后准备跳槽了,开始了一轮的面试,其中有几个面试官就问到了相关的源码问题:ArrayList、HashMap的底层实现,spring、mybatis的相关源码。问源码的面试一般就是回去等消息,然后就没然后了。

那时候开始意识到,源码这东西在之前的工作的中感受不到,但是在面试中好像面的还挺频繁的,从此有意识的开始了jdk部分源码的阅读(主要是集合)。一开始看源码,看的特别糙,知道个大概,知道ArrayList的底层实现是数组,HashMap的底层是散列表(数组+链表);更深入一点的扩容、hash碰撞等等就不知道了。

读spring源码起于工作中遇到了一个问题(spring jdbcTemplate事务,各种诡异,包你醍醐灌顶!),排查一段时间最终是解决了,但过程让我非常难受,各种上网查资料、各种尝试,感觉就像大海捞针一样,遥遥无期。我下定决心,我要看一看spring的源码,于是我买了一本《spring源码深度解析》,结合着这本书、打开着eclipse,开始了spring的源码阅读之旅。至此,读源码成了习惯,源码已经进入了我的心里。

后来,springboot的火热,让我也想蹭上一蹭,于是有了springboot的启动源码系列,虽然还在进行中,但是我相信我能将其完成;工作中用到了shiro,我又结合着《跟我学shiro》将shiro的源码看了个大概,有了shiro源码系列博文,还差一篇认证与授权(应该很快就能面世),shiro源码系列就封笔了。最近在搭建自己的后台管理系统,用到了quartz,集成的过程也遇到了一些问题,因此有了quartz的两篇文章。

慢慢的,从一味的网上找资料变成了很多时候会从源码中找答案。不求能读太多的源码,但愿自己接触的技术都能读上一读,路漫漫其修远兮,吾将上下而求索!

大家为什么要读源码?

很多人一定和我一样的感受:源码在工作中有用吗?用处大吗?很长一段时间内我也有这样的疑问,认为哪些有事没事扯源码的人就是在装,只是为了提高他们的逼格而已。

那为什么我还要读源码呢?一刚开始为了面试,后来为了解决工作中的问题,再后来就是个人喜好了。说的好听点是有匠人精神;说的委婉点是好奇(底层是怎么实现的);说的不自信点是对黑盒的东西我用的没底,怕用错;说的简单直白点是提升自我价值,为了更高的薪资待遇(这里对真正的技术迷说声抱歉)。

源码中我们可以学到很多东西,学习别人高效的代码书写、学习别人对设计模式的熟练使用、学习别人对整个架构的布局,等等。如果你还能找出其中的不足,那么恭喜你,你要飞升了!会使用固然重要,但知道为什么这么使用同样重要。从模仿中学习,从模仿中创新。

读源码不像围城(外面的人想进来,里面的人想出去),它是外面的人不想进来,里面的人不想出去;当我们跨进城内,你会发现(还是城外好,皮!)城内风光无限,源码的海洋任我们遨游!

首先我们要对我们的目标有所了解,知道她有什么特点,有些什么功能。对对方都还不了解,就想着进入别人的内心世界,那不是臭不要脸嘛,我们要做一个有着流氓心的绅士;对她有个大致的了解了,就可以发起攻势,一举拿下。

那么怎么样了解了,方式有很多,我这里提供几种,仅供参考

最好的方式就是官方参考指南,亲生父母往往对孩子是最了解的,对孩子的描述也是最详细的;比如Spring Boot Reference Guide就是对springboot最详细的描述,怎么样使用springboot、springboot特性等等,通过此指南,springboot在你面前一览无遗;

但是,springboot毕竟是外国人的孩子,如果英语不好,估计读起来有点头疼了,不过我们有google翻译呀,咬咬牙也是能看的。源码世界的丈母娘、老岳丈是非常慷慨的!

其次是书籍,国外优秀的有很多,国内也不乏好书,比较推荐此方式,自成体系,让我们掌握的知识点不至于太散。这就是好比是源码的闺蜜,对源码非常了解,重点是挺大方,会尽全力帮助我们了解源码。

再次就是博客,虽然可能觉得知识点比较散,但是针对某个知识点却特别的细,对彻底掌握非常有帮助,园子内就有很多技术大牛,写的博客自然也是非常棒,非常具有学习价值。当然还有社区、论坛、github、码云等等。这就是源码的朋友圈,我们从中也能获取到非常多关于源码的信息。

设计模式的了解

优秀的框架、技术从不乏设计模式;jdk源码中就应用了很多设计模式,比如IO流中的适配器模式与装饰模式、GUI的观察者模式、集合中的迭代器模式等等;spring源码中也是用到了大量的设计模式。设计模式有什么优点、各适用于什么场景,不是本文的内容,需要我们大家自行去了解。

我们只需要对一些常用的设计模式有个大致了解,再去读源码是比较好的;不需要将23种设计模式都通读,也不需要将常用设计模式完全理解透;对于全部通读,我们时间有限,另外有些模式确实不太好理解、用的少,性价比不高,没必要全部都读。

推荐书籍:《Head First Design Patterns》(中文版:《Head First 设计模式》)、《Java与模式》;

另外我比较推荐的一种学习设计模式的方式是读别人博客:java_my_life,刘伟技术博客,chenssy的设计模式;

设计模式之于源码,就好比逛街购物之于女人,想顺利勾搭源码,我们需要好好掌握设计模式这个套路。

配合ide进行断点追踪

我们通过源码的圈子对源码的了解终究只是停在表面,终究还是没有走进她的内心,接下来我就和大家分享下,我是如何走进她的内心的!

相信看过我的源码博客的小伙伴都知道,我非常喜欢通过idea断点来进行源码追踪,断点追踪源码是我非常推荐的一种方式。断点不仅可以用来调试我们的代码,也可以用来调试我们用到的框架源码。

面对未知的、茫茫多的源码,我们往往没有足够的时间、经历和耐心去通读所有源码,我们只需要去读我们关注的部分即可(有人可能会说我都不关心,这?)。那为什么要用断掉调试的方式来跟源码,而不是直接从源代码入手去跟我们关注的部分呢?

尝试过的小伙伴应该知道,如果我们对源码不熟悉,直接通过源码的方式去跟,一方面很容易迷路(多态,会有很多子类实现),不知道接下来跟哪一个,另一方面也很容易跟丢,当我们跟入的很深的时候,很有可能就忘记上一步跟到哪了。所以读源码的重要性浅显易懂了。

‘伍’ 如何构建spring boot

Spring Boot充分利用了JavaConfig的配置模式以及“约定优于配置”的理念,能够极大的简化基于Spring
MVC的Web应用和REST服务开发。

Spring
4倡导微服务的架构,针对这一理念,近来在微博上也有一些有价值的讨论,如这里和这里。微服务架构倡导将功能拆分到离散的服务中,独立地进行部署,Spring
Boot能够很方便地将应用打包成独立可运行的JAR包,因此在开发模式上很契合这一理念。目前,Spring
Boot依然是0.5.0的里程碑版本,因此相关的文档尚不完善,本文将会以一个简单的样例来介绍基于这个项目的开发过程。

要Spring
Boot进行功能开发,需要使用Gradle或者Maven作为构建工具。在本例中,我们会使用Eclipse和Maven插件进行开发。要使用Spring
Boot,首先创建一个Maven工程,并修改Maven主要的配置文件pom.xml,如下所示:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.M7</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
</dependency>
</dependencies>

<properties>
<start-class>com.levin.Application</start-class>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>spring-milestone</id>
<url>http://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>spring-milestone</id>
<url>http://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

在上面的配置中,需要将工程的parent设置为spring-boot-starter-parent,并添加对spring-boot-starter-web的依赖,这样我们就无需设置各个依赖项及其版本信息了。并且在构建中要声明使用spring-boot-maven-plugin这个插件,它会对Maven打包形成的JAR进行二次修改,最终产生符合我们要求的内容结构。

在我们的应用中将要发布一个REST服务,显示一个基本的用户信息,首先定义一个简单的模型类:

package com.levin;

public class Person {
private String name;
private String email;

public Person(String name, String email) {
this.name = name;
this.email = email;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}

}

接下来,我们需要声明一个Spring MVC的Controller,响应对实体的请求:
@Controller
public class ShowPersonController {
@RequestMapping("/showPerson")
public @ResponseBody Person showPerson() {
return new Person("levinzhang","[email protected]");
}
}

这个类与我们在使用Spring MVC定义Controller时并无任何差别。接下来,我们需要声明一个主类启动这个应用程序:
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

这个类的main方法中使用了SpringApplication帮助类,并以Application这个类作为配置来启动Spring的应用上下文。在这个类中使用了ComponentScan以及EnableAutoConfiguration注解,其中ComponentScan注解会告知Spring扫描指定的包来初始化Spring
Bean,这能够确保我们声明的Bean能够被发现。EnableAutoConfiguration将会启动自动配置模式,在我们的配置中会将对Tomcat的依赖级联进来,因此在应用启动时将会自动启动一个嵌入式的Tomcat,因为在样例中使用了Spring
MVC,所以也会自动注册所需的DispatcherServlet,这都不需要类似web.xml这样的配置。

在Eclipse中要运行这个应用的话,可以直接以Java
Application的形式来运行这个main函数,此时会启动应用,我们在浏览器中可以看到如下的运行效果,这就是我们想要的REST服务:

在开发调试完成之后,可以将应用打成JAR包的形式,在Eclipse中可以直接使用Maven插件的package命令,最终会形成一个可运行的JAR包。我们使用java
–jar命令就可以运行这个JAR包了。所呈现出的效果与在调试期是一样的。现在看一下这个JAR包解压后的目录结构:

这个JAR包与传统JAR包的不同之处在于里面有一个名为lib的目录,在这个目录中包含了这个简单应用所依赖的其他JAR包,其中也包含内置的嵌入式Tomcat,正是使用它,才能发布服务和访问Web资源。除了我们编写的源码所编译形成的CLASS以外,在org目录下还有许多Spring所提供的CLASS,正是依赖这些CLASS,才能够加载位于lib目录下JAR中的类。这样的加载机制与在OSGi
bundle中声明Bundle-Classpath很类似,不过在OSGi中会由容器来负责加载指定路径下的类。这大致阐述了这样一个JAR包能够发布服务的原因。

如果我们想要使用HTML、JSP等Web资源的话,在Controller中直接返回对应的视图就可以了。

如果我们想要将这个JAR包转换成可以在Servlet容器中部署的WAR的话,就不能依赖于Application的main函数了,而是要以类似于web.xml文件配置的方式来启动Spring应用上下文,此时我们需要声明这样一个类:
public class HelloWebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}

}

这个类的作用与在web.xml中配置负责初始化Spring应用上下文的监听器作用类似,只不过在这里不需要编写额外的XML文件了。

如果要将最终的打包形式改为WAR的话,还需要对pom.xml文件进行修改,除了需要将packaging的值修改为war以外,还需要对依赖进行适当的配置(这一部分在Spring
Boot的样例和文档中均未提及,提醒大家注意):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

在这里需要移除对嵌入式Tomcat的依赖,这样打出的WAR包中,在lib目录下才不会包含Tomcat相关的JAR包,否则将会出现启动错误。另外,在移除对Tomcat的依赖后,为了保证编译正确,还需要添加对servlet-api的依赖,因此添加如下的配置:

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>7.0.42</version>
<scope>provided</scope>
</dependency>

在这里将scope属性设置为provided,这样在最终形成的WAR中不会包含这个JAR包,因为Tomcat或Jetty等服务器在运行时将会提供相关的API类。此时,执行mvn
package命令就会得到一个WAR文件,我们可以直接将其放到Tomcat下运行(需要7.0.42版本以上)。

以上介绍了基于Spring Boot开发应用的过程,目前它的文档尚不完善,但是在GitHub上有不少的样例,包括与Spring
Data集成访问数据库(关系型以及非关系型)、安全、WebSocket等,读者感兴趣可以下载运行,需要注意的是有些样例中使用的是0.5.0.M6版本,这个版本有问题,运行时会出错,建议手动修改为0.5.0.M7或快照版本。

基于以上的介绍,希望读者能够对Spring
Boot这个新项目有所了解。它简化了JAR包管理和相关基础设施环境的配置,能够帮助我们快速开发Web应用或构建REST服务,希望它能够尽快完善成熟,更多地用于实践,提升开发效率。

‘陆’ 在哪里可下spring boot admin ui源码

创建PageController,编码如下:
package org.springboot.sample.controller;

import java.util.Date;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class PageController {

// 从 application.properties 中读取配置,如取不到默认值为Hello Shanhy
@Value("${application.hell:Hello Shanhy}")
private String hello = "Hello Shanhy";

/**
* 默认页<br/>
* @RequestMapping("/") 和 @RequestMapping 是有区别的
* 如果不写参数,则为全局默认页,加入输入404页面,也会自动访问到这个页面。
* 如果加了参数“/”,则只认为是根页面。
*
* @return
* @author SHANHY
* @create 2016年1月5日
*/
@RequestMapping(value = {"/","/index"})
public String index(Map<String, Object> model){
// 直接返回字符串,框架默认会去 spring.view.prefix 目录下的 (index拼接spring.view.suffix)页面
// 本例为 /WEB-INF/jsp/index.jsp
model.put("time", new Date());
model.put("message", this.hello);
return "index";
}

/**
* 响应到JSP页面page1
*
* @return
* @author SHANHY
* @create 2016年1月5日
*/
@RequestMapping("/page1")
public ModelAndView page1(){
// 页面位置 /WEB-INF/jsp/page/page.jsp
ModelAndView mav = new ModelAndView("page/page1");
mav.addObject("content", hello);
return mav;
}

/**
* 响应到JSP页面page1(可以直接使用Model封装内容,直接返回页面字符串)
*
* @return
* @author SHANHY
* @create 2016年1月5日
*/
@RequestMapping("/page2")
public String page2(Model model){
// 页面位置 /WEB-INF/jsp/page/page.jsp
model.addAttribute("content", hello + "(第二种)");
return "page/page1";
}
}

pom.xml添加依赖:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>123456789

上面说了spring-boot 不推荐JSP,想使用JSP需要配置application.properties。
添加src/main/resources/application.properties内容:
# 页面默认前缀目录
spring.mvc.view.prefix=/WEB-INF/jsp/
# 响应页面默认后缀
spring.mvc.view.suffix=.jsp
# 自定义属性,可以在Controller中读取
application.hello=Hello Shanhy123456

在 src/main 下面创建 webapp/WEB-INF/jsp 目录用来存放我们的jsp页面。
index.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Spring Boot Sample</title>
</head>

<body>
Time: ${time}
<br>
Message: ${message}
</body>
</html>12345678910111213

page1.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Spring Boot Sample</title>
</head>

<body>
<h1>${content }</h1>
</body>
</html>1234567891011

要想让spring-boot支持JSP,需要将项目打成war包。
我们做最后一点修改,修改pom.xml文件,将 jar 中的 jar 修改为 war
然后启动spring-boot服务。

‘柒’ springBoot @RequestBody 写在方法上与写在参数上的区别

1. @Controller
控制层组件,定义一个springMVC的控制器类,往往需要和@RequestMapping配合使用。
2. @RestController
相当于@ResponseBody+@Controller合在一起的作用。
3. @Service
服务层组件,用于标注业务层组件,表示定义一个bean,自动根据bean的类名实例化一个首写字母为小写的bean,也可以指定bean的名称:@Service(“beanName”)。
4. @Repository
持久层组件,用于标注数据访问组件,即DAO组件。
5. @Component
把普通pojo实例化到spring容器中,相当于配置文件中的 <bean id="" class=""/>。
6. @RequestMapping
用于配置控制层的访问URL,可以用在控制器类上和控制器方法上,如果用在控制器类上,则访问类中的方法是要加上类上的路径,例如:
@Controller
@RequestMapping("/personal/linkInfo")
public class LinkInfoController {
@RequestMapping(value = "/addLinkInfo")
public String addLinkInfo(LinkInfoReq linkInfoReq) {
linkInfoService.addLinkInfo(linkInfoReq);
return "redirect:/personal/linkInfo/toLinkInfo";
}
}
上述代码的访问路径就是XXX/personal/linkInfo/addLinkInfo。
@RequestMapping源代码如下图:
a) value:设置访问的URL,数组,可以将多个请求映射到一个方法上去。支持通配符配置
代码示例:
@RequestMapping(value = {"/page","/page*"})
public void getInfo() {
}
上述代码访问路径可以是:XXX/page,XXX/pageadc等满足value条件的路径。
b) method:设置访问的方法,数组,可是设置多个访问方法映射到同一个方法上,默认为GET方法
代码示例:
@RequestMapping(value = "/page", method = RequestMethod.POST)
public void getInfo() {
}
上述代码 /page路径就只能用POST方法才能请求。
method的可选值有GET,HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE。
c) params:指定request中必须包含某些参数值是,才让该方法处理。数组。
@RequestMapping(value = "/page", params = {"type=1"})
public void getInfo() {
}
上述代码/page路径只有请求参数中包含type且值等于1时才能访问该方法。
d) headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。数组。
示例代码:
@RequestMapping(value = "/page", headers = {" content-type=text/plain " })
public void getInfo() {
}
上述代码/page路径只有headers中content-type=text/plain才能访问该方法。
e) consumes:指定处理请求的提交内容类型(Content-Type),例如application/json, text/html。
f) proces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
7. @ResponseBody
通常使用在controller方法上,作用是将方法的返回值通过合适的HttpMessageConverter转换成特定格式写入到response的body区域,然后返回给客户端,如果没有使用@RequestBody注解,方法返回值将会封装到ModelAndView并解析返回视图。
8. @RequestParam
接受的参数来自requestHeader,即请求头,用来接收GET和POST请求参数并将参数赋值到被@RequestParam注解的变量上,同样可以使用requet.getParameter(“name”)获取,默认的参数接受方式,如果controller方法的参数未使用@RequestParam,则默认也是使用@RequestParam接受参数。用来处理Content-Type: 为 application/x-www-form-urlencoded编码的内容。
@RequestParam有三个配置参数:
a) required:是否必须,默认true,必须。
b) defaultValue:默认值,请求的参数为空时使用默认值。
c) value:请求的参数名。
9. @RequestBody
接受的参数来自requestBody,即请求体,一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。
10. @Autowired
它可以对类成员变量,方法及构造函数进行标注,完成自动装配工作,可以消除set,get方法。
11. @Resource
其作用和@Autowired相似。
不同点:
@Resource是Java自己的注解,@Resource有两个属性重要属性,分是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。
@Autowired是spring的注解,是spring2.5版本引入的,@Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier注解一起来修饰。
@Resource装配顺序
a) 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
b) 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
c) 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
d) 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
推荐使用@Resource,不用谢set方法,并且这个注解属于java自己的,减少了与spring的耦合度。
12. @Value
该注解有两种使用方式:
a) @Value(“${}”)
这种使用方式注入的是配置文件里的参数
这样配置文件中的com.title就能配置到LinkInfoController的title属性中
b) @Value(“#{}”)
该方式表示SpEl表达式通常用来获取bean的属性,或者调用bean的某个方法。
这样就可以把User对象的name配置到LinkInfoController的name属性中。
13. @Transactional
用于配置spring事务管理。属性信息如下:
事物的传播行为如下:
14. @SpringBootApplication
该注解其实是一个组合注解,源码如下图:
比较重要的注解有三个:
a) @SpringBootConfiguration
从源代码可以看到@SpringBootConfiguration继承自@Configuration,这两个注解的功能也是一样的。
b) @EnableAutoConfiguration
此注释自动载入应用程序所需的所有Bean。
c) @ComponentScan
该注解会扫描指定路径下的的类,并将其加入到IoC容器中。在springboot中,@ComponentScan默认扫描@SpringBootApplication所在类的同级目录以及它的子目录。
15. @Configuration
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被或类进行扫描,并用于构建bean定义,初始化Spring容器。
16. @Bean
该注解主要用在@Configuration注解的类里,也可以用在@Component注解的类里。添加的bean的id为方法名。相当于配置文件里的<bean></bean>。
@Configuration
public class RedisConfig extends CachingConfigurerSupport{
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);
return redisCacheManager;
}
}
如上代码就相当于在xml文件里配置:
<beans>
<bean id=" cacheManager " class=" com.mypage.config. RedisCacheManager "/>
</beans>
17. @MapperScan
指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类添加位置:是在Springboot启动类上面添加:
18. @EnableCaching
该注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了。
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
/**
* 采用RedisCacheManager作为缓存管理器
* @param connectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);
return redisCacheManager;
}
}
19. @EnableRedisHttpSession
用来设置springboot使用redis存储session,该注解会创建一个名字叫springSessionRepositoryFilter的Spring Bean,其实就是一个Filter,这个Filter负责用Spring Session来替换原先的默认HttpSession实现。
示例代码如下:
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 60*30)
public class HttpSessionConfig {
}
其中属性maxInactiveIntervalInSeconds是设置session的有效时间,单位毫秒,默认1800ms。
但其实这样还是不够的,还要在配置文件中设置redis存储session:
spring.session.store-type=redis
这样就可以了。

阅读全文

与springboot启动类源码相关的资料

热点内容
卡尔曼滤波算法书籍 浏览:769
安卓手机怎么用爱思助手传文件进苹果手机上 浏览:844
安卓怎么下载60秒生存 浏览:803
外向式文件夹 浏览:240
dospdf 浏览:431
怎么修改腾讯云服务器ip 浏览:392
pdftoeps 浏览:496
为什么鸿蒙那么像安卓 浏览:736
安卓手机怎么拍自媒体视频 浏览:186
单片机各个中断的初始化 浏览:724
python怎么集合元素 浏览:481
python逐条解读 浏览:833
基于单片机的湿度控制 浏览:499
ios如何使用安卓的帐号 浏览:883
程序员公园采访 浏览:812
程序员实战教程要多长时间 浏览:979
企业数据加密技巧 浏览:135
租云服务器开发 浏览:814
程序员告白妈妈不同意 浏览:336
攻城掠地怎么查看服务器 浏览:601