Spring Security

SecurityFilterChain SecurityFilterChain 是 Spring Security 的核心抽象,代表一条作用于 HTTP 请求的安全过滤器链。每个进入应用的请求都会依次经过链中的若干 Filter,完成认证(Authentication)、授权(Authorization)、CSRF 防护、会话管理等工作。 底层机制:从 Servlet Filter 到 Spring Security Servlet 规范本身有 Filter 接口和 FilterChain 接口。Spring Security 通过以下两层代理接入这套机制: DelegatingFilterProxy:在 Servlet 容器(Tomcat)层面注册的 Filter,作用是把请求桥接到 Spring 容器中的 Bean。它本身不做安全逻辑,只是一个"入口代理"。 FilterChainProxy:Spring 容器中的真正实现,也是一个特殊的 Filter。它持有所有注册的 SecurityFilterChain Bean,收到请求后,按顺序匹配第一条能处理该 URL 的链,然后依次执行链中的每个 Filter。 HTTP 请求 → Tomcat FilterChain → DelegatingFilterProxy(Servlet Filter,桥接到 Spring) → FilterChainProxy(Spring Bean) → SecurityFilterChain 1(匹配 /api/**) UsernamePasswordAuthenticationFilter BearerTokenAuthenticationFilter ExceptionTranslationFilter AuthorizationFilter ... → SecurityFilterChain 2(匹配 /**) ... 定义一个 SecurityFilterChain @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain apiSecurityChain(HttpSecurity http) throws Exception { http .securityMatcher("/api/**") // 只匹配 /api/** 路径 .authorizeHttpRequests(auth -> auth .requestMatchers("/api/public/**").permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态,适合 JWT ) .csrf(csrf -> csrf.disable()); // REST API 通常关闭 CSRF return http.build(); } } HttpSecurity 是 SecurityFilterChain 的构建器,调用 .build() 后生成链实例并注册为 Bean。 ...

2026-05-12 · 2 min · 358 words · -

Lombok

Lombok 是一个 Java 编译器插件,通过注解在编译期自动生成 getter/setter、构造器、equals/hashCode、toString、Builder 等样板代码,让源文件保持简洁。 发音:来自印度尼西亚龙目岛(Lombok Island),读作 LOM-bok,重音在第一个音节。 出现时间:2009 年首次发布,比 Spring Boot(2014 年)早了五年,与 Spring 没有直接关系,是独立的 Java 工具。 原理:利用 Java 编译器的注解处理器(Annotation Processing)在 javac 编译时修改语法树,将生成的方法直接写入 .class 字节码,源文件里没有这些方法但编译产物里有。IDE 需要安装 Lombok 插件才能识别生成的方法。 解决了什么问题 Java 要求显式写大量与业务无关的样板代码,一个普通的 JavaBean 需要: // 不用 Lombok:一个 User 类要写几十行 public class User { private Long id; private String name; private String email; public User() {} public User(Long id, String name, String email) { ... } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // ... 还有 equals / hashCode / toString ... } 用 Lombok: ...

2026-05-12 · 2 min · 392 words · -

Spring IoC 与依赖注入

IoC(Inversion of Control,控制反转)是 Spring 的核心机制。它把"创建和管理对象"的控制权从应用代码交给 Spring 容器,应用代码只需声明依赖,容器负责提供。 IoC 的具体实现方式叫 DI(Dependency Injection,依赖注入),容器通过构造器、字段或 Setter 方法将依赖对象注入进来。 IoC 解决了什么问题 传统写法中,对象自己负责创建依赖: // 传统写法:自己创建依赖,紧耦合 public class OrderService { private UserDao userDao = new UserDaoImpl(); // 自己 new,换实现要改代码 private EmailService email = new EmailService("smtp.example.com", 465); } 这带来三个问题: 紧耦合:OrderService 直接依赖具体实现类,换实现必须修改源码 难以测试:无法替换成 Mock 对象,单元测试困难 对象生命周期散乱:每次 new 都产生新对象,无法复用单例 IoC 写法: // IoC 写法:声明需要什么,容器负责提供 @Service public class OrderService { @Autowired private UserDao userDao; // 容器注入,不关心具体实现 @Autowired private EmailService emailService; } 切换实现时只需修改容器配置,OrderService 代码本身不用动。 ...

2026-05-12 · 3 min · 432 words · -

企业应用架构模式

什么是企业应用架构模式 企业应用架构模式(Patterns of Enterprise Application Architecture,简称 PoEAA) 由 Martin Fowler 在 2002 年出版的同名书中系统整理,专门解决企业级应用中反复出现的架构问题。 它与 GoF 23 种设计模式的区别: GoF 设计模式(1994) 企业应用架构模式(2002) 关注层面 对象级别,类与类之间的协作 应用架构级别,层与层之间的设计 典型问题 如何创建对象、如何解耦行为 如何组织 Web 层、如何访问数据库、如何处理并发 典型模式 Factory、Observer、Strategy Front Controller、Repository、Unit of Work 两套模式不冲突,可以同时使用。 Web 表现层模式 Front Controller(前端控制器) 所有 HTTP 请求通过单一入口,集中处理身份验证、日志、权限等横切关注点,再路由到具体处理器。 所有请求 → Front Controller → Dispatcher → 具体 Handler Spring MVC 实现:DispatcherServlet 是标准的 Front Controller 实现,映射到 / 接收所有请求,通过 HandlerMapping 路由到对应的 @Controller 方法。 详见 Front Controller Pattern。 Page Controller(页面控制器) 每个页面或 URL 对应一个独立的控制器类。原始 Servlet 就是这种模式——/users 对应 UsersServlet,/orders 对应 OrdersServlet。 ...

2026-05-11 · 1 min · 190 words · -

Spring Boot

Spring Boot 是什么 Spring Boot 是 Pivotal (现为 VMware/Broadcom)在 2014 年推出的框架,建立在 Spring Framework 之上,目标是简化整个 Spring 生态的开发、配置和部署。它不只是简化 Spring MVC,同样简化了 Spring Data(数据库访问)、Spring Security(认证授权)、Spring Messaging(消息队列)等全家桶的配置。 核心理念是 “约定优于配置”(Convention over Configuration):框架提前定好"默认约定",只要遵循这些约定,就不需要写任何配置;只有想偏离默认行为时,才需要显式配置。 例如,classpath 里有 spring-boot-starter-web,Spring Boot 就约定你要启动一个 Web 服务,自动完成:注册 DispatcherServlet、内嵌 Tomcat 监听 8080 端口、注册 Jackson 用于 JSON 序列化。你什么都不写,java -jar app.jar 就能跑起来。需要覆盖默认行为时,只在 src/main/resources/application.yml 中写偏离默认值的部分: server: port: 9090 # 只需声明偏离默认值的配置 也可通过命令行参数临时覆盖:java -jar app.jar --server.port=9090,优先级高于 application.yml。 出现背景 Spring Boot(2014)与微服务架构的兴起同期出现。2014 年 Martin Fowler 发表了微服务架构的奠基性文章,微服务要求每个服务独立部署、快速启动、进程隔离。传统的 WAR 包 + 外部 Tomcat 的部署方式与这一需求存在明显矛盾,Spring Boot 正是为了解决这一问题而生。 ...

2026-05-11 · 8 min · 1615 words · wiloon

Spring Boot + PostgreSQL 持久层框架

主流持久层框架 Spring Data JPA + Hibernate Spring Boot 默认推荐,依赖 spring-boot-starter-data-jpa ORM 框架,用注解映射对象和表 自动生成 SQL,支持 JPQL / Criteria API 适合领域模型复杂的场景 MyBatis / MyBatis-Plus 半自动 ORM,SQL 写在 XML 或注解中 对 SQL 控制力强,适合复杂查询 MyBatis-Plus 提供代码生成、分页等增强功能 JOOQ 类型安全的 SQL DSL,SQL 风格写法 编译期检查 SQL,适合喜欢写 SQL 的团队 商业数据库需付费版 Spring Data JDBC 比 JPA 更轻量,无懒加载、缓存等复杂特性 SQL 更透明,适合简单 CRUD R2DBC(响应式) 非阻塞响应式驱动,配合 WebFlux 使用 依赖 spring-boot-starter-data-r2dbc 选型建议 场景 推荐 快速开发,标准 CRUD Spring Data JPA 复杂 SQL,精细控制 MyBatis-Plus 强类型 SQL,重查询业务 JOOQ 响应式架构 R2DBC 连接池 Spring Boot 默认使用 HikariCP 作为连接池。 ...

2026-04-25 · 3 min · 467 words · -

JDK 17 新特性

概述 JDK 17 是 Java 的长期支持版本(LTS),于 2021 年 9 月发布。相比 JDK 16,JDK 17 引入了多项新特性和改进,同时也包含了一些孵化特性的正式毕业版本。 正式特性(JEP) JEP 306: 恢复始终严格的浮点语义 将浮点运算恢复为始终严格模式(strict),删除了 strictfp 关键字的限制效果。在历史上,Java 曾因不同硬件平台的差异引入了扩展精度模式,随着现代硬件的普及,该差异不再存在,因此恢复了一致的浮点行为。 JEP 356: 增强型伪随机数生成器 提供新的接口和实现用于伪随机数生成器(PRNG),新增了 RandomGenerator 接口和多个算法实现,如 Xoshiro256PlusPlus、L64X128MixRandom 等。 RandomGenerator generator = RandomGeneratorFactory.of("L64X128MixRandom").create(); int randomInt = generator.nextInt(100); JEP 382: 新的 macOS 渲染管道 使用 Apple Metal API 实现 Java 2D 渲染管道,替代已废弃的 OpenGL API,提升在 macOS 上的图形渲染性能。 JEP 391: macOS/AArch64 移植 将 JDK 移植到 macOS/AArch64(Apple Silicon)平台,支持原生运行于 M1 及后续芯片的 Mac 电脑。 JEP 398: 废弃 Applet API 正式废弃 Applet API,标记为 @Deprecated(forRemoval = true)。浏览器早已不再支持 Java 插件,该 API 已无实际用途。 ...

2026-04-25 · 3 min · 440 words · -

JDK 8 新特性

JDK 8 相对于 JDK 7 引入的主要新特性: Lambda 表达式 函数式接口(Functional Interface) Stream API 方法引用(Method Reference) 默认方法(Default Method) Optional 新的日期时间 API(java.time) Nashorn JavaScript 引擎 Base64 并发增强(CompletableFuture、StampedLock、LongAdder) 重复注解(Repeating Annotations) 类型注解(Type Annotations) PermGen 移除,改用 Metaspace Lambda 表达式 Lambda 来自数学中的 λ 演算(Lambda Calculus),是函数式编程的理论基础。函数式编程的核心思想是:函数是"一等公民",可以像普通值一样被传递、赋值、返回。JDK 8 引入 Lambda,本质上是给 Java 这门面向对象语言加入了函数式编程的能力。 Lambda 表达式允许将函数(即 Lambda 表达式本身)作为参数传递,简化匿名内部类的写法。 语法结构 (参数列表) -> 方法体 (参数列表):传入的参数,无参数时写空括号 () ->:箭头操作符,读作 “goes to”,分隔参数列表和方法体 方法体:要执行的逻辑 Runnable 是一个接口(java.lang.Runnable),只有一个无参方法 void run(),因此参数列表为空 ()。 // JDK 7:匿名内部类写法 Runnable r = new Runnable() { @Override public void run() { System.out.println("Hello"); } }; // JDK 8:Lambda 写法,箭头右边等价于 run() 的方法体 Runnable r = () -> System.out.println("Hello"); 将函数作为参数传递 JDK 8 之前,Java 无法直接传递"一段逻辑",只能把逻辑包装成匿名对象再传递。Lambda 表达式让你可以直接把逻辑作为参数传入方法,这就是"将函数作为参数传递"的含义。 ...

2026-04-25 · 3 min · 431 words · -

Exception Handling

异常捕捉的确是对性能有影响的,那是因为一旦异常被抛出,函数也就跟着 return 了。而程序在执行时需要处理 函数栈 的上下文,这会导致性能变得很慢,尤其是线程栈比较深的时候。但从另一方面来说,异常的抛出基本上表明程序的错误。程序在绝大多数情况下,应该是在没有异常的情况下运行的, 所以,有异常的情况应该是少数的情况,不会影响正常处理的性能问题。 对于我们并不期望会发生的事,我们可以使用异常捕捉;对于我们觉得可能会发生的事,使用返回码。 https://time.geekbang.org/column/article/675 你觉得自己是一个Java专家吗?是否肯定自己 已经全面掌握了Java的异常处理机制?在下面这段代码中,你能够迅速找出异常处理的六个问题吗? 1 OutputStreamWriter out = … 2 java.sql.Connection conn = … 3 try { // ⑸ 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 “select uid, name from user”); 7 while (rs.next()) 8 { 9 out.println(“ID: " + rs.getString(“uid”) // ⑹ 10 “,姓名: " + rs.getString(“name”)); 11 } 12 conn.close(); // ⑶ 13 out.close(); 14 } 15 catch(Exception ex) // ⑵ 16 { 17 ex.printStackTrace(); //⑴,⑷ ...

2026-03-23 · 6 min · 1146 words · -

JMM, Java Memory Model, java 内存模型

JMM, Java Memory Model, java 内存模型 Java内存模型,是指Java程序在运行时内存的模型,而Java代码是运行在Java虚拟机之上的,由Java虚拟机通过解释执行(解释器)或编译执行(即时编译器)来完成, 所以Java内存模型,也就是指Java虚拟机的运行时内存模型。 Java内存比较流行的说法便是堆和栈,这其实是非常粗略的一种划分,这种划分的"堆"对应内存模型的Java堆,“栈"是指虚拟机栈,然而Java内存模型远比这更复杂 @startuml skinparam componentStyle rectangle skinparam nodesep 10 skinparam ranksep 10 component "Java Run-time Data Areas" { [heap] component thread0 { [PC Register] as pc0 [thread stack] as ts0 [Native Method Stack] as nms0 pc0 -[hidden]-> ts0 ts0 -[hidden]-> nms0 } component thread1 { [PC Register] as pc1 [thread stack] as ts1 [Native Method Stack] as nms1 pc1 -[hidden]-> ts1 ts1 -[hidden]-> nms1 } thread0 --[hidden]--> heap thread1 --[hidden]--> heap component "method area" as ma { [constant pool] as cp } heap -[hidden]-> ma } @enduml Java 虚拟机的内存空间 (运行时数据区)分为 5 个部分: 程序计数器, PC register Java 虚拟机栈, JVM stack, 线程栈, thread stack 本地方法栈, native method stack 堆, heap 方法区, method area,方法区里面还有一个常量池 线程私有的数据区: 程序计数器,虚拟机栈,本地方法栈 所有线程共有的数据区: Java堆,方法区 ...

2021-09-21 · 3 min · 596 words · -

自动装箱 拆箱

自动装箱 拆箱 Java作为面向对象语言,有人认为所看到的都是对象,事实上,在Java SE 5之前,基本类型默认并不是采用对象存在的如果您想要把基本类型作为对象来处理,就必须自行转换,不过,在Java SE 5之后,为基本数据类型提供了自动装箱和拆箱功能,使得将基本类型转换为对象变得极其便捷。 在这里来捋一捋java的基本数据类型,不理不要紧,一理才发现俺也掌握的不是那么明确,在这里俺也再次学习下 总计有八个,分别是 byte字节型 (一个字节) ,char字符型 (两个字节) ,short短整型 (两个字节) ,int整型 (四个字节) , long长整型 (八个字节) ,float浮点型 (四个字节) ,double 双精度浮点型 (八个字节) ,boolean型 (一个字节) 在javase5之前,如果想要把基本数据类型作为对象来操作,就需要采用对应的对象,来把它们打包才行 现在虽然不用这样了,但其中也有一些要注意的地方,俺揪出来晒晒。 先说说类和对象,建立个概念吧先 类-可以认为是对象的设计图 对象-是按照设计图实现了的具体工具 先这么简单理解吧,如果真要扯开了说,那可是软件工程里面的一门专业课,我们有个概念就好 之所以要将基本类型数据打包成为对象,原因很简单,是因为对象可以携带更多的数据。 手动、自动装箱拆箱示例 Long,Integer,Double,Float,Boolean等等的类就是所谓的wrapper类,就跟wrapper这个单词所代表的意思一样,就是提供一个"包装,加壳",把基本数据类型放在里面,来看代码,体会下先 public class WrapperDemo{ public staticvoid main(String[] args){ int data1=21; int data2=24; //打包成为对象 Integer data1Wrapper = new Integer(data1); Integer data2Wrapper = new Integer(data2); //原始数据直接除以3 System.out.println(data1/3); //将数据打包,转换为double型,除以3 System.out.println(data1Wrapper.doubleValue()/3); //比较 System.out.println(data1Wrapper.compareTo(data2Wrapper)); } } 图1-1 WrapperDemo的运行结果 通过上面的代码和运行结果,看到了将基本数据类型打包成为对象带来的好处了吧,别着急,这还只是javase5之前的做法,在javase5之后就已经支持自动装箱和拆箱了,在这,就不再单独写代码出来了,只写几个能说明问题的语句就可以了,相信很容易理解的。 javase5之前,手动打包 Integer data1 = new Integer(10); ...

2020-06-30 · 1 min · 201 words · -

Front Controller Pattern

概述 Front Controller Pattern(前端控制器模式)来自 Martin Fowler 的《企业应用架构模式》(Patterns of Enterprise Application Architecture,2002),属于 Web 层架构模式,不是 GoF 23 种设计模式的一部分。 详见 企业应用架构模式。 解决的问题 在原始 Servlet 时代,每个 URL 对应一个独立的 Servlet 类,这是 Page Controller 模式: /users → UsersServlet /orders → OrdersServlet /products → ProductsServlet 每个 Servlet 都要自己处理身份验证、日志记录、权限检查,代码大量重复。随着 URL 增多,web.xml 里的注册条目也膨胀。 Front Controller 的解法是单一入口: 所有请求 → FrontController(统一处理横切关注点)→ Dispatcher → 具体处理器 三个角色 Front Controller:所有请求的唯一入口,集中处理身份验证、权限验证、日志追踪等横切关注点 Dispatcher:将请求路由到对应的具体处理器(View/Handler) View / Handler:真正处理业务逻辑的模块 Spring MVC 中的实现 Spring MVC 的 DispatcherServlet 是 Front Controller 模式的标准实现: ...

2017-02-12 · 2 min · 234 words · -

java maven 可执行 jar/ executable jar, maven-assembly-plugin

java maven 可执行 jar/ executable jar, maven-assembly-plugin 在pom中加入 maven-assembly-plugin <project> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.wiloon.java.lock.TestFutex</mainClass> </manifest> </archive> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> mvn clean package assembly:single # 如果没执行过 mvn package 会报错: Cannot include project artifact: com.wiloon.java:pingd-java:jar:1.0-SNAPSHOT; it doesn't have an associated file or directory. java -jar target/pingd-java-1.0-SNAPSHOT-jar-with-dependencies.jar

2016-12-16 · 1 min · 63 words · -

java UDP

java UDP 一. UDP协议定义 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据报分组、组装和不能对数据包的排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。 二. 使用UDP的原因 它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和OICQ就是使用的UDP协议。在选择使用协议的时候,选择UDP必须要谨慎。在网络质量令人不十分满意的环境下,UDP协议数据包丢失会比较严重。 三. 在Java中使用UDP协议编程的相关类 InetAddress 用于描述和包装一个Internet IP地址。有如下方法返回实例: getLocalhost(): 返回封装本地地址的实例。 getAllByName(String host): 返回封装Host地址的InetAddress实例数组。 getByName(String host): 返回一个封装Host地址的实例。其中,Host可以是域名或者是一个合法的IP地址。 InetAddress.getByAddress(addr): 根据地址串返回InetAddress实例。 InetAddress.getByAddress(host, addr): 根据主机地符串和地址串返回InetAddress实例。 DatagramSocket 用于接收和发送UDP的Socket实例。该类有3个构造函数: DatagramSocket(): 通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。程序会让操作系统分配一个可用的端口。 DatagramSocket(int port): 创建实例,并固定监听Port端口的报文。通常用于服务端 DatagramSocket(int port, InetAddress localAddr): 这是个非常有用的构建器,当一台机器拥有多于一个IP地址的时候,由它创建的实例仅仅接收来自LocalAddr的报文。 DatagramSocket具有的主要方法如下: receive(DatagramPacket d): 接收数据报文到d中。receive方法产生一个"阻塞"。“阻塞"是一个专业名词,它会产生一个内部循环,使程序暂停在这个地方,直到一个条件触发。 send(DatagramPacket dp): 发送报文dp到目的地。 setSoTimeout(int timeout): 设置超时时间,单位为毫秒。 close(): 关闭DatagramSocket。在应用程序退出的时候,通常会主动释放资源,关闭Socket,但是由于异常地退出可能造成资源无法回收。所以,应该在程序完成时,主动使用此方法关闭Socket,或在捕获到异常抛出后关闭Socket。 DatagramPacket 用于处理报文,它将Byte数组、目标地址、目标端口等数据包装成报文或者将报文拆卸成Byte数组。应用程序在产生数据包是应该注意,TCP/IP规定数据报文大小最多包含65507个,通常主机接收548个字节,但大多数平台能够支持8192字节大小的报文。DatagramPacket类的构建器共有4个: DatagramPacket(byte[] buf, int length): 将数据包中Length长的数据装进Buf数组,一般用来接收客户端发送的数据。 DatagramPacket(byte[] buf, int offset, int length): 将数据包中从Offset开始、Length长的数据装进Buf数组。 DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort): 从Buf数组中,取出Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。 ...

2015-08-24 · 2 min · 273 words · -

Java读 环境变量

Java读 环境变量 http://ling091.iteye.com/blog/354052 读取环境变量时可以使用 System.getProperty 或 System.getenv 方法。 System.getProperty 方法 ( JDK1.4 ) 用来读取针对 JVM 的属性,如程序当前的运行路径、路径分隔符、 Java 版本等, ( 见 System.getProperty() 参数大全 ) ,它也可以读取在运行程序时设置的自定义属性。 获取一个JVM已定义属性 //获取系统当前的运行路径 System.out.println(“current path = " + System.getProperty(“user.dir”) ); 输出: current path = E:\program\java\test\Test 获取应用程序的属性: 在命令中输入下面的命令,其中的-D用于设置一个属性 -D= SET myvar=Hello world SET myothervar=nothing java -Dmyvar="%myvar%” -Dmyothervar="%myothervar%" myClass myClass中读取这些属性 String myvar = System.getProperty(“myvar”); String myothervar = System.getProperty(“myothervar”); 如果要读取操作系统的环境变量 (如 Path 、 TEMP 或 TMP 、 JAVA_HOME 等。) 则可以使用 System.getenv 方法,但是由于某些原因,该方法被去掉了,直到 JDK1.5 后,该方法又被加进去 [3] 。 ...

2015-08-14 · 1 min · 119 words · -

java 字符串, 比较

java 字符串, 比较 java简单的字符串大小比较——compareTo()方法 在java编程中,我们会偶尔遇到字符串大小比较的问题,compareTo()方法很简单就实现这种功能。该方法用于判断一个字符串是大于、等于还是小于另一个字符串。判断字符串大小的依据是根据它们在字典中的顺序决定的。 语法: Str1.compareTo(Str2); 其返回的是一个int类型值。若Str1等于参数字符串Str2字符串,则返回0;若该Str1按字典顺序小于参数字符串Str2,则返回值小于0;若Str1按字典顺序大于参数字符串Str2,则返回值大于0。 java中的compareto方法,返回参与比较的前后两个字符串的asc码的差值,看下面一组代码 String a="a",b="b"; System.out.println(a.compareto.b); 则输出-1; 若a="a",b="a"则输出0; 若a="b",b="a"则输出1; 单个字符这样比较,若字符串比较长呢?? 若a=“ab”,b=“b”,则输出-1; 若a=“abcdef”,b=“b"则输出-1; 也就是说,如果两个字符串首字母不同,则该方法返回首字母的asc码的差值; 如果首字母相同呢?? 若a=“ab”,b=“a”,输出1; 若a=“abcdef”,b=“a"输出5; 若a=“abcdef”,b=“abc"输出3; 若a=“abcdef”,b=“ace"输出-1; 即参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值,如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值 参考: http://blog.sina.com.cn/s/blog_8a7200cd010104nx.html http://www.blogjava.net/hgc-ghc/archive/2013/03/28/397084.html //char 转String String str = String.valueOf(c); //判断字符大小写 if( Character.isUpperCase(c)) 1、字节数组转换为字符串 byte[] byBuffer = new byte[20]; … … String strRead = new String(byBuffer); strRead = String.copyValueOf(strRead.toCharArray(), 0, byBuffer.length]); 2、字符串转换成字节数组 byte[] byBuffer = new byte[200]; String strInput=“abcdefg”; byBuffer= strInput.getBytes(); ...

2015-08-13 · 1 min · 76 words · -

ConcurrentHashMap

ConcurrentHashMap ConcurrentHashMap 是一个线程安全的Hash Table,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并 且其内部的结构可以让其在进行写操作的时候能够将锁的粒度保持地尽量地小,不用对整个ConcurrentHashMap加锁。 jdk1.7 由 Segment 数组、HashEntry 组成,和 HashMap 一样,仍然是数组加链表。 它的核心成员变量: /** * Segment 数组,存放数据时首先需要定位到具体的 Segment 中。 */ final Segment<K,V>[] segments; transient Set<K> keySet; transient Set<Map.Entry<K,V>> entrySet; Segment 是 ConcurrentHashMap 的一个内部类,主要的组成如下: static final class Segment<K,V> extends ReentrantLock implements Serializable { private static final long serialVersionUID = 2249069246763182397L; // 和 HashMap 中的 HashEntry 作用一样,真正存放数据的桶 transient volatile HashEntry<K,V>[] table; transient int count; transient int modCount; transient int threshold; final float loadFactor; } 和 HashMap 非常类似,唯一的区别就是其中的核心数据如 value ,以及链表都是 volatile 修饰的,保证了获取时的可见性。 ...

2015-08-12 · 8 min · 1510 words · -

A cycle was detected in the build path of project

A cycle was detected in the build path of project 解决Eclipse中Java工程间循环引用而报错的问题 如果我们的项目包含多个工程 (project) ,而它们之间又是循环引用的关系,那么Eclipse在编译时会抛出如下一个错误信息: “A cycle was detected in the build path of project: XXX” 解决方法非常简单: Eclipse Menu -> Window -> Preferences… -> Java -> Compiler -> Building -> Building path problems -> Circular dependencies -> 将Error改成Warning http://blog.csdn.net/kcai678/article/details/4668993

2015-08-10 · 1 min · 48 words · -

java.net.InetAddress

java.net.InetAddress http://www.cnblogs.com/hnrainll/archive/2012/01/09/2317515.html java.net.InetAddress类的使用 1.1. 简介 IP地址是IP使用的32位 (IPv4) 或者128位 (IPv6) 位无符号数字,它是传输层协议TCP,UDP的基础。InetAddress是Java对IP地址的封装,在java.net中有许多类都使用到了InetAddress,包括ServerSocket,Socket,DatagramSocket等等。 InetAddress的实例对象包含以数字形式保存的IP地址,同时还可能包含主机名 (如果使用主机名来获取InetAddress的实例,或者使用数字来构造,并且启用了反向主机名解析的功能) 。InetAddress类提供了将主机名解析为IP地址 (或反之) 的方法。 InetAddress对域名进行解析是使用本地机器配置或者网络命名服务 (如域名系统 (Domain Name System,DNS) 和网络信息服务 (Network Information Service,NIS) ) 来实现。对于DNS来说,本地需要向DNS服务器发送查询的请求,然后服务器根据一系列的操作,返回对应的IP地址,为了提高效率,通常本地会缓存一些主机名与IP地址的映射,这样访问相同的地址,就不需要重复发送DNS请求了。在java.net.InetAddress类同样采用了这种策略。在默认情况下,会缓存一段有限时间的映射,对于主机名解析不成功的结果,会缓存非常短的时间 (10秒) 来提高性能。 1.2. InetAddress对象的获取 InetAddress的构造函数不是公开的 (public) ,所以需要通过它提供的静态方法来获取,有以下的方法: static InetAddress[] getAllByName(String host) static InetAddress getByAddress(byte[] addr) static InetAddress getByAddress(String host,byte[] addr) static InetAddress getByName(String host) static InetAddress getLocalHost() 在这些静态方法中,最为常用的应该是getByName(String host)方法,只需要传入目标主机的名字,InetAddress会尝试做连接DNS服务器,并且获取IP地址的操作。代码片段如下,注意我们假设以下的代码,都是默认导入了java.net中的包,在程序的开头加上import java.net.*,否则需要指定类的全名java.net.InetAddress。 InetAddress address=InetAddress.getByName(“www.baidu.com”); 注意到这些方法可能会抛出的异常。如果安全管理器不允许访问DNS服务器或禁止网络连接,SecurityException会抛出,如果找不到对应主机的IP地址,或者发生其他网络I/O错误,这些方法会抛出UnknowHostException。所以需要写如下的代码: try { InetAddress address=InetAddress.getByName(“www.baidu.com”); System.out.println(address); } catch(UnknownHostException e) { e.printStackTrace(); } 下面是一则完整的例子: package org.dakiler.javanet.chapter1; import java.net.InetAddress; ...

2015-08-05 · 1 min · 153 words · -

java ByteBuffer

java ByteBuffer ByteBuffer 是 NIO 里用得最多的 Buffer, 它包含两个实现方式: HeapByteBuffer 是基于Java堆的实现, 而 DirectByteBuffer 则使用了 unsafe 的 API 进行了堆外的实现。这里只说 HeapByteBuffer。 Buffer 类 定义了一个可以线性存放primitive type数据的容器接口。Buffer主要包含了与类型 (byte, char…) 无关的功能。 值得注意的是Buffer及其子类都不是线程安全的。 每个Buffer都有以下的属性: capacity 这个Buffer最多能放多少数据。capacity一般在buffer被创建的时候指定。 limit 在Buffer上进行的读写操作都不能越过这个下标。当写数据到buffer中时,limit一般和capacity相等,当读数据时, limit代表buffer中有效数据的长度。 position 读/写操作的当前下标。当使用buffer的相对位置进行读/写操作时,读/写会从这个下标进行,并在操作完成后, buffer会更新下标的值。 mark 一个临时存放的位置下标。调用mark()会将mark设为当前的position的值,以后调用reset()会将position属性设 置为mark的值。mark的值总是小于等于position的值,如果将position的值设的比mark小,当前的mark值会被抛弃掉。 这些属性总是满足以下条件: 0 <= mark <= position <= limit <= capacity limit和position的值除了通过limit()和position()函数来设置,也可以通过下面这些函数来改变: Buffer clear() 把position设为0,把limit设为capacity,一般在把数据写入Buffer前调用。 Buffer flip() 把limit设为当前position,把position设为0,一般在从Buffer读出数据前调用。 Buffer rewind() 把position设为0,limit不变,一般在把数据重写入Buffer前调用。 Buffer 对象有可能是只读的, 这时, 任何对该对象的写操作都会触发一个 ReadOnlyBufferException isReadOnly()方法可以用来判断一个Buffer是否只读。 Buffer是一个抽象的基类 派生类: ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer ...

2015-08-05 · 4 min · 754 words · -