Java探索之Feign入门使用详解

一,简介

Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于Retrofit、JAXRS-2.0和WebSocket。Feign最初是为了降低统一绑定Denominator到HTTP API的复杂度,不区分是否支持Restful。Feign旨在通过最少的资源和代码来实现和HTTP API的连接。通过可定制的解码器和错误处理,可以编写任意的HTTP API。

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-core -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-core</artifactId>
  <version>8.18.0</version>
  <scope>runtime</scope>
</dependency>

二,为什么选择Feign而不是其他

你可以使用 Jersey 和 CXF 这些来写一个 Rest 或 SOAP 服务的java客服端。你也可以直接使用 Apache HttpClient 来实现。但是 Feign 的目的是尽量的减少资源和代码来实现和 HTTP API 的连接。通过自定义的编码解码器以及错误处理,你可以编写任何基于文本的 HTTP API。

Feign工作机制

Feign通过注解注入一个模板化请求进行工作。只需在发送之前关闭它,参数就可以被直接的运用到模板中。然而这也限制了Feign,只支持文本形式的API,它在响应请求等方面极大的简化了系统。同时,它也是十分容易进行单元测试的。

三,Feign使用简介

3.1,基本用法

基本的使用如下所示,一个对于canonical Retrofit sample的适配。

interface GitHub {
 // RequestLine注解声明请求方法和请求地址,可以允许有查询参数
 @RequestLine("GET /repos/{owner}/{repo}/contributors")
 List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
}
static class Contributor {
 String login;
 int contributions;
}
public static void main(String... args) {
 GitHub github = Feign.builder()
            .decoder(new GsonDecoder())
            .target(GitHub.class, "https://api.github.com");
 // Fetch and print a list of the contributors to this library.
 List<Contributor> contributors = github.contributors("OpenFeign", "feign");
 for (Contributor contributor : contributors) {
  System.out.println(contributor.login + " (" + contributor.contributions + ")");
 }
}

3.2,自定义

Feign 有许多可以自定义的方面。举个简单的例子,你可以使用 Feign.builder() 来构造一个拥有你自己组件的API接口。如下:

interface Bank {
 @RequestLine("POST /account/{id}")
 Account getAccountInfo(@Param("id") String id);
}
...
// AccountDecoder() 是自己实现的一个Decoder
Bank bank = Feign.builder().decoder(new AccountDecoder()).target(Bank.class, https://api.examplebank.com);

3.3,多种接口

Feign可以提供多种API接口,这些接口都被定义为 Target<T> (默认的实现是 HardCodedTarget<T>), 它允许在执行请求前动态发现和装饰该请求。

举个例子,下面的这个模式允许使用当前url和身份验证token来装饰每个发往身份验证中心服务的请求。
CloudDNS cloudDNS = Feign.builder().target(new CloudIdentityTarget<CloudDNS>(user, apiKey));

示例

Feign 包含了 GitHub 和 Wikipedia 客户端的实现样例.相似的项目也同样在实践中运用了Feign。尤其是它的示例后台程序。

四,Feign集成模块

Feign 可以和其他的开源工具集成工作。你可以将这些开源工具集成到 Feign 中来。目前已经有的一些模块如下:

4.1,Gson

Gson 包含了一个编码器和一个解码器,这个可以被用于JSON格式的API。

添加 GsonEncoder 以及 GsonDecoder 到你的 Feign.Builder 中, 如下:

GsonCodec codec = new GsonCodec();
GitHub github = Feign.builder()
           .encoder(new GsonEncoder())
           .decoder(new GsonDecoder())
           .target(GitHub.class, https://api.github.com);

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-gson</artifactId>
  <version>8.18.0</version>
</dependency>

4.2,Jackson

Jackson 包含了一个编码器和一个解码器,这个可以被用于JSON格式的API。

添加 JacksonEncoder 以及 JacksonDecoder 到你的 Feign.Builder 中, 如下:

GitHub github = Feign.builder()
           .encoder(new JacksonEncoder())
           .decoder(new JacksonDecoder())
           .target(GitHub.class, https://api.github.com);

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-jackson</artifactId>
  <version>8.18.0</version>
</dependency>

4.3,Sax

SaxDecoder 用于解析XML,并兼容普通JVM和Android。下面是一个配置sax来解析响应的例子:

api = Feign.builder()
.decoder(SAXDecoder.builder()
.registerContentHandler(UserIdHandler.class)
.build())
.target(Api.class, https://apihost);

Maven依赖:

<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-sax</artifactId>
  <version>8.18.0</version>
</dependency>

4.4,JAXB

JAXB 包含了一个编码器和一个解码器,这个可以被用于XML格式的API。

添加 JAXBEncoder 以及 JAXBDecoder 到你的 Feign.Builder 中, 如下:

api = Feign.builder()
      .encoder(new JAXBEncoder())
      .decoder(new JAXBDecoder())
      .target(Api.class, https://apihost);

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-jaxb</artifactId>
  <version>8.18.0</version>
</dependency>

4.5,JAX-RS

JAXRSContract 使用 JAX-RS 规范重写覆盖了默认的注解处理。下面是一个使用 JAX-RS 的例子:

interface GitHub {
 @GET @Path("/repos/{owner}/{repo}/contributors")
 List<Contributor> contributors(@PathParam("owner") String owner, @PathParam("repo") String repo);
}
// contract 方法配置注解处理器,注解处理器定义了哪些注解和值是可以作用于接口的
GitHub github = Feign.builder()
           .contract(new JAXRSContract())
           .target(GitHub.class, https://api.github.com);

Maven依赖:

<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-jaxrs</artifactId>
  <version>8.18.0</version>
</dependency>

4.5,OkHttp

OkHttpClient 使用 OkHttp 来发送 Feign 的请求,OkHttp 支持 SPDY (SPDY是Google开发的基于TCP的传输层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验),并有更好的控制http请求。

要让 Feign 使用 OkHttp ,你需要将 OkHttp 加入到你的环境变量中区,然后配置 Feign 使用 OkHttpClient,如下:

GitHub github = Feign.builder()
           .client(new OkHttpClient())
           .target(GitHub.class, "https://api.github.com");
Maven依赖:
<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-okhttp</artifactId>
  <version>8.18.0</version>
</dependency>

4.6,Ribbon

RibbonClient 重写了 Feign 客户端的对URL的处理,其添加了 智能路由以及一些其他由Ribbon提供的弹性功能。
集成Ribbon需要你将ribbon的客户端名称当做url的host部分来传递,如下:

// myAppProd是你的ribbon client name
MyService api = Feign.builder().client(RibbonClient.create()).target(MyService.class, "https://myAppProd");
Maven依赖:
<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-ribbon</artifactId>
  <version>8.18.0</version>
</dependency>

4.7,Hystrix

HystrixFeign 配置了 Hystrix 提供的熔断机制。

要在 Feign 中使用 Hystrix ,你需要添加Hystrix模块到你的环境变量,然后使用 HystrixFeign 来构造你的API:

MyService api = HystrixFeign.builder().target(MyService.class, "https://myAppProd");
Maven依赖:
<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-hystrix</artifactId>
  <version>8.18.0</version>
</dependency>

4.8,SLF4J

SLF4JModule 允许你使用 SLF4J 作为 Feign 的日志记录模块,这样你就可以轻松的使用 Logback, Log4J , 等 来记录你的日志.

要在 Feign 中使用 SLF4J ,你需要添加SLF4J模块和对应的日志记录实现模块(比如Log4J)到你的环境变量,然后配置 Feign使用Slf4jLogger :

GitHub github = Feign.builder()
           .logger(new Slf4jLogger())
           .target(GitHub.class, "https://api.github.com");
Maven依赖:
<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-gson -->
<dependency>
  <groupId>com.netflix.feign</groupId>
  <artifactId>feign-slf4j</artifactId>
  <version>8.18.0</version>
</dependency>

五,Feign 组成

5.1,Decoders

Feign.builder() 允许你自定义一些额外的配置,比如说如何解码一个响应。假如有接口方法返回的消息不是 Response, String, byte[] 或者 void 类型的,那么你需要配置一个非默认的解码器。

下面是一个配置使用JSON解码器(使用的是feign-gson扩展)的例子:

GitHub github = Feign.builder()
           .decoder(new GsonDecoder())
           .target(GitHub.class, https://api.github.com);

假如你想在将响应传递给解码器处理前做一些额外的处理,那么你可以使用mapAndDecode方法。一个用例就是使用jsonp服务的时候:

// 貌似1.8.0版本中沒有mapAndDecode这个方法。。。
JsonpApi jsonpApi = Feign.builder()
             .mapAndDecode((response, type) -> jsopUnwrap(response, type), new GsonDecoder())
             .target(JsonpApi.class, https://some-jsonp-api.com);

5.2,Encoders

发送一个Post请求最简单的方法就是传递一个 String 或者 byte[] 类型的参数了。你也许还需添加一个Content-Type请求头,如下:

interface LoginClient {
 @RequestLine("POST /")
 @Headers("Content-Type: application/json")
 void login(String content);
}
...
client.login("{\"user_name\": \"denominator\", \"password\": \"secret\"}");

通过配置一个解码器,你可以发送一个安全类型的请求体,如下是一个使用 feign-gson 扩展的例子:

static class Credentials {
 final String user_name;
 final String password;
 Credentials(String user_name, String password) {
  this.user_name = user_name;
  this.password = password;
 }
}
interface LoginClient {
 @RequestLine("POST /")
 void login(Credentials creds);
}
...
LoginClient client = Feign.builder()
             .encoder(new GsonEncoder())
             .target(LoginClient.class, "https://foo.com");
client.login(new Credentials("denominator", "secret"));

5.3,@Body templates

@Body注解申明一个请求体模板,模板中可以带有参数,与方法中 @Param 注解申明的参数相匹配,使用方法如下:

interface LoginClient {
 @RequestLine("POST /")
 @Headers("Content-Type: application/xml")
 @Body("<login \"user_name\"=\"{user_name}\" \"password\"=\"{password}\"/>")
 void xml(@Param("user_name") String user, @Param("password") String password);
 @RequestLine("POST /")
 @Headers("Content-Type: application/json")
 // json curly braces must be escaped!
 // 这里JSON格式需要的花括号居然需要转码,有点蛋疼了。
 @Body("%7B\"user_name\": \"{user_name}\", \"password\": \"{password}\"%7D")
 void json(@Param("user_name") String user, @Param("password") String password);
}
...
client.xml("denominator", "secret"); // <login "user_name"="denominator" "password"="secret"/>
client.json("denominator", "secret"); // {"user_name": "denominator", "password": "secret"}

5.4,Headers

Feign 支持给请求的api设置或者请求的客户端设置请求头,如下:

给API设置请求头

使用 @Headers 设置静态请求头

// 给BaseApi中的所有方法设置Accept请求头
@Headers("Accept: application/json")
interface BaseApi<V> {
 // 单独给put方法设置Content-Type请求头
 @Headers("Content-Type: application/json")
 @RequestLine("PUT /api/{key}")
 void put(@Param("key") String, V value);
}

设置动态值的请求头

@RequestLine("POST /")
@Headers("X-Ping: {token}")
void post(@Param("token") String token);

设置key和value都是动态的请求头

有些API需要根据调用时动态确定使用不同的请求头(e.g. custom metadata header fields such as “x-amz-meta-“ or “x-goog-meta-“),

这时候可以使用 @HeaderMap 注解,如下:

// @HeaderMap 注解设置的请求头优先于其他方式设置的
@RequestLine("POST /")
void post(@HeaderMap Map<String, Object> headerMap);

给Target设置请求头

有时我们需要在一个API实现中根据不同的endpoint来传入不同的Header,这个时候我们可以使用自定义的RequestInterceptor 或 Target来实现.

通过自定义的 RequestInterceptor 来实现请查看 Request Interceptors 章节.

下面是一个通过自定义Target来实现给每个Target设置安全校验信息Header的例子:

static class DynamicAuthTokenTarget<T> implements Target<T> {
 public DynamicAuthTokenTarget(Class<T> clazz,
                UrlAndTokenProvider provider,
                ThreadLocal<String> requestIdProvider);
 ...
 @Override
 public Request apply(RequestTemplate input) {
  TokenIdAndPublicURL urlAndToken = provider.get();
  if (input.url().indexOf("http") != 0) {
   input.insert(0, urlAndToken.publicURL);
  }
  input.header("X-Auth-Token", urlAndToken.tokenId);
  input.header("X-Request-ID", requestIdProvider.get());
  return input.request();
 }
}
...
Bank bank = Feign.builder()
    .target(new DynamicAuthTokenTarget(Bank.class, provider, requestIdProvider));

这种方法的实现依赖于给Feign 客户端设置的自定义的RequestInterceptor 或 Target。可以被用来给一个客户端的所有api请求设置请求头。比如说可是被用来在header中设置身份校验信息。这些方法是在线程执行api请求的时候才会执行,所以是允许在运行时根据上下文来动态设置header的。

比如说可以根据线程本地存储(thread-local storage)来为不同的线程设置不同的请求头。

六,高级用法

6.1,Base APIS

有些请求中的一些方法是通用的,但是可能会有不同的参数类型或者返回类型,这个时候可以这么用:

// 通用API
interface BaseAPI {
 @RequestLine("GET /health")
 String health();
 @RequestLine("GET /all")
 List<Entity> all();
}
// 继承通用API
interface CustomAPI extends BaseAPI {
 @RequestLine("GET /custom")
 String custom();
}
// 各种类型有相同的表现形式,定义一个统一的API
@Headers("Accept: application/json")
interface BaseApi<V> {
 @RequestLine("GET /api/{key}")
 V get(@Param("key") String key);
 @RequestLine("GET /api")
 List<V> list();
 @Headers("Content-Type: application/json")
 @RequestLine("PUT /api/{key}")
 void put(@Param("key") String key, V value);
}
// 根据不同的类型来继承
interface FooApi extends BaseApi<Foo> { }
interface BarApi extends BaseApi<Bar> { }

6.2,Logging

你可以通过设置一个 Logger 来记录http消息,如下:

GitHub github = Feign.builder()
           .decoder(new GsonDecoder())
           .logger(new Logger.JavaLogger().appendToFile("logs/http.log"))
           .logLevel(Logger.Level.FULL)
           .target(GitHub.class, https://api.github.com);

也可以参考上面的 SLF4J 章节的说明

6.3,Request Interceptors

当你希望修改所有的的请求的时候,你可以使用Request Interceptors。比如说,你作为一个中介,你可能需要为每个请求设置 X-Forwarded-For

static class ForwardedForInterceptor implements RequestInterceptor {
 @Override public void apply(RequestTemplate template) {
  template.header("X-Forwarded-For", "origin.host.com");
 }
}
...
Bank bank = Feign.builder()
         .decoder(accountDecoder)
         .requestInterceptor(new ForwardedForInterceptor())
         .target(Bank.class, https://api.examplebank.com);

或者,你可能需要实现Basic Auth,这里有一个内置的基础校验拦截器

BasicAuthRequestInterceptor
Bank bank = Feign.builder()
         .decoder(accountDecoder)
         .requestInterceptor(new BasicAuthRequestInterceptor(username, password))
         .target(Bank.class, https://api.examplebank.com);

6.4,Custom @Param Expansion

在使用 @Param 注解给模板中的参数设值的时候,默认的是使用的对象的 toString() 方法的值,通过声明 自定义的Param.Expander,用户可以控制其行为,比如说格式化 Date 类型的值:

// 通过设置 @Param 的 expander 为 DateToMillis.class 可以定义Date类型的值
@RequestLine("GET /?since={date}")
Result list(@Param(value = "date", expander = DateToMillis.class) Date date);

6.5,Dynamic Query Parameters

动态查询参数支持,通过使用 @QueryMap 可以允许动态传入请求参数,如下:

@RequestLine("GET /find")
V find(@QueryMap Map<String, Object> queryMap);

6.6,Static and Default Methods

如果你使用的是JDK 1.8+ 的话,那么你可以给接口设置统一的默认方法和静态方法,这个事JDK8的新特性,如下:

interface GitHub {
 @RequestLine("GET /repos/{owner}/{repo}/contributors")
 List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
 @RequestLine("GET /users/{username}/repos?sort={sort}")
 List<Repo> repos(@Param("username") String owner, @Param("sort") String sort);
 default List<Repo> repos(String owner) {
  return repos(owner, "full_name");
 }
 /**
  * Lists all contributors for all repos owned by a user.
  */
 default List<Contributor> contributors(String user) {
  MergingContributorList contributors = new MergingContributorList();
  for(Repo repo : this.repos(owner)) {
   contributors.addAll(this.contributors(user, repo.getName()));
  }
  return contributors.mergeResult();
 }
 static GitHub connect() {
  return Feign.builder()
        .decoder(new GsonDecoder())
        .target(GitHub.class, "https://api.github.com");
 }
}

总结

以上就是本文关于Java探索之Feign入门使用详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:Java编程几个循环实例代码分享、Java面向对象编程(封装/继承/多态)实例解析等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • Java运用SWT插件编写桌面记事本应用程序

    本文实例介绍了Java基于SWT编写记事本的详细过程,分享给大家供大家参考,具体内容如下 可实现windows系统桌面记事本基本功能,傻瓜式教学,一步一步手把手操作.小白也可自己编写出完整的应用程序. 需要工具:Eclipse(带SWT插件) 成品如下: 应用程序功能介绍: 功能分析: 1.文件(F) 2.编辑(E) 3.格式(O) 4.查看(V) 5.帮助(H) 其中文件菜单中包括 1.1.新建(N) Ctrl+N 1.2打开(O) Ctrl+O 1.3保存(S) Ctrl+S 1.4另存为(

  • JavaWeb项目FullCalendar日历插件使用的示例代码

    本文介绍了JavaWeb项目FullCalendar日历插件使用的示例代码,分享给大家,具体如下: 使用FullCalendar需要引用的文件 1.css文件 2.js文件 <link href="${base}/assets/global/plugins/fullcalendar/fullcalendar.min.css" rel="external nofollow" rel="stylesheet" type="text/c

  • Java简单实现SpringMVC+MyBatis分页插件

    1.封装分页Page类 package com.framework.common.page.impl; import java.io.Serializable; import com.framework.common.page.IPage; /** * * * */ public abstract class BasePage implements IPage, Serializable { /** * */ private static final long serialVersionUID

  • Ajax分页插件Pagination从前台jQuery到后端java总结

    困惑了我一段时间的网页分页,今天特地整理了一下我完成不久的项目.下面我要分享下我这个项目的分页代码,前后端通吃.希望前辈多多指教. 一.效果图 下面我先上网页前台和管理端的部分分页效果图,他们用的是一套代码. 二.上代码前的一些知识点 此jQuery插件为Ajax分页插件,一次性加载,故分页切换时无刷新与延迟,如果数据量较大不建议用此方法,因为加载会比较慢. 三.前台代码部分 var pageSize =6; //每页显示多少条记录 var total; //总共多少记录 $(function(

  • Java中使用WebUploader插件上传大文件单文件和多文件的方法小结

    一.使用webuploader插件的原因说明 被现在做的项目坑了. 先说一下我的项目架构spring+struts2+mybatis+MySQL 然后呢.之前说好的按照2G上传就可以了,于是乎,用了ajaxFileUpload插件,因为之前用图片上传也是用这个,所以上传附件的时候就直接拿来用了 各种码代码,测试也测过了,2G文件上传没问题,坑来了,项目上线后,客户又要求上传4G文件,甚至还有20G以上的..纳尼,你不早说哦... 在IE11下用ajaxFileUpload.js插件上传超过4G的

  • Java探索之Feign入门使用详解

    一,简介 Feign使得 Java HTTP 客户端编写更方便.Feign 灵感来源于Retrofit.JAXRS-2.0和WebSocket.Feign最初是为了降低统一绑定Denominator到HTTP API的复杂度,不区分是否支持Restful.Feign旨在通过最少的资源和代码来实现和HTTP API的连接.通过可定制的解码器和错误处理,可以编写任意的HTTP API. Maven依赖: <!-- https://mvnrepository.com/artifact/com.netf

  • Java数据结构与算法入门实例详解

    第一部分:Java数据结构 要理解Java数据结构,必须能清楚何为数据结构? 数据结构: Data_Structure,它是储存数据的一种结构体,在此结构中储存一些数据,而这些数据之间有一定的关系. 而各数据元素之间的相互关系,又包括三个组成成分,数据的逻辑结构,数据的存储结构和数据运算结构. 而一个数据结构的设计过程分成抽象层.数据结构层和实现层. 数据结构在Java的语言体系中按逻辑结构可以分为两大类:线性数据结构和非线性数据结构. 一.Java数据结构之:线性数据结构 线性数据结构:常见的

  • Java远程调用组件Feign技术使用详解

    目录 一. 概要 二. Feign简介 1. 概念 2. 功能 三. 服务提供者 1. 添加依赖 2. 配置文件 3. 启动类 4. 控制层 5. POJO 四. 服务消费者 1. 添加依赖 2. 配置文件 3. 启动类 4. Feign服务 5. 控制层 五. 测试 1. 测试get请求 2. 测试post请求json数据格式 3. 测试头部中包含信息 一. 概要 我们知道,现在最火且最有技术含量的技术莫过于SpringCloud微服务了,所以今天壹哥就带大家来学习一下微服务的核心的组件之一,

  • hibernate4快速入门实例详解

    Hibernate是什么 Hibernate是一个轻量级的ORMapping框架 ORMapping原理(Object RelationalMapping) ORMapping基本对应规则: 1:类跟表相对应 2:类的属性跟表的字段相对应 3:类的实例与表中具体的一条记录相对应 4:一个类可以对应多个表,一个表也可以对应对个类 5:DB中的表可以没有主键,但是Object中必须设置主键字段 6:DB中表与表之间的关系(如:外键)映射成为Object之间的关系 7:Object中属性的个数和名称可

  • spring boot + jpa + kotlin入门实例详解

    spring boot +jpa的文章网络上已经有不少,这里主要补充一下用kotlin来做. kotlin里面的data class来创建entity可以帮助我们减少不少的代码,比如现在这个User的Entity,这是Java版本的: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String firstName; private S

  • java中switch选择语句代码详解

    switch结构(开关语句)的语法 switch(表达式 ){ --->类型为int.char case 常量1 :--->case 结构可以有多个 //语句块1 break; --->程序跳出switch结构 case 常量n :--->常量的值不能相同 //语句块n break; default:--->和if结构中的 else作用相同 //语句块 break; } 下面看一段代码示例,有详细的注释,大家可以参考: public class SwitchStu{ /* s

  • java迭代器和for循环优劣详解

    在进行迭代的时候,程序运行的效率也是我们挑选迭代方法的重要原因.目前有三种迭代方法:for循环.迭代器和Foreach.前两者相信大家都非常熟悉,为了更加直观分析效率的不同,我们还加入Foreach一起比较.下面我们就三种方法的概念进行理解,然后ArrayList中探索三种方法的效率. 1.概念理解 for循环:是支持迭代的一种通用结构,是最有效,最灵活的循环结构 迭代器:是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的 Foreach:通过阅读源码我们还发现一个It

  • Java安全框架——Shiro的使用详解(附springboot整合Shiro的demo)

    Shiro简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理 三个核心组件:Subject, SecurityManager 和 Realms Subject代表了当前用户的安全操作 SecurityManager管理所有用户的安全操作,是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务. Realm充当了Shiro与应用安全数据间的"桥梁"或者"连接器&q

  • Java基础之switch分支结构详解

    一.基本语法 二.流程图 1.画出 swtich 出流程 2.案例说明流程图 三.快速入门 案例:Switch01.java 请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d,e,f,g a 表示星期一,b 表示星期二 - 根据用户的输入显示相应的信息.要求使用 switch 语句完成 代码: /* 案例:Switch01.java 请编写一个程序,该程序可以接收一个字符,比如:a,b,c,d,e,f,g a表示星期一,b表示星期二 - 根据用户的输入显示相应的信息.要求使用 swi

  • Java基础篇之反射机制详解

    目录 1.反射概述 1.1什么是反射 1.2.反射能干什么 2.解剖类 2.1反射构造方法 2.1.1反射无参的构造函数 2.1.2反射“一个参数”的构造函数 2.1.3反射“多个参数”的构造函数 2.1.4反射“私有”的构造函数 2.1.5反射得到类中所有的构造函数 2.2反射类中的方法 2.3反射类中的属性字段 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1.使用new关键字:这是我们最常见的也是最简单的创建对象的方式

随机推荐