1. 复现问题
今天在测试解析jwt token
时,如下代码所示:
/**
* 测试token
*
* @author 念兮为美
* @datetime 2022/8/24:15:45
* @return
*/
@Test
public void tokenGener() {
String token ="eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoxLFwidXNlcm5hbWVcIjpcImFkbWluXCJ9IiwiZXhwIjoxNjYxMzI5NTQ5fQ.bJANmLzpCYbSQ-3ymJ5DX-PMnY1FAWf0Q7OmFXEN3a-ngh-2Og31tisdiXI57SIxdE_X7nY-p4_XcUv-ZeiUQQ";
token = token.substring(0, token.indexOf(":"));
JSONObject jsonObject = jwtConfig.parseToken(token);
System.out.println(jsonObject);
}
报错如下错误:
2. 分析问题
分析错误中java.lang.StringIndexOutOfBoundsException: String index out of range: -1
这句最关键的信息,简单理解就是字符串下标越界
。
通过分析indexOf
方法和substring
方法,解决这个问题。
- indexOf方法
我们不妨看看indexOf
的源码和注释:
/**
* Returns the index within this string of the first occurrence of the
* specified substring.
*
* The returned index is the smallest value k for which:
*
* this.startsWith(str, k)
*
* If no such value of k exists, then {@code -1} is returned.
*
* @param str the substring to search for.
* @return the index of the first occurrence of the specified substring,
* or {@code -1} if there is no such occurrence.
*/
public int indexOf(String str) {
return indexOf(str, 0);
}
其从指定的索引开始,返回其第一次出现的指定子串的索引位置,如果不存在这样的子串,则返回-1。
显然,我们上述token
并不存在:
,因而token.indexOf(":")
返回的是-1
。
token.substring(0, token.indexOf(":"));
就变成了token.substring(0, -1);
- substring方法
我们不妨看看substring
的源码和注释,如下所示:
/**
* Returns a string that is a substring of this string. The
* substring begins at the specified {@code beginIndex} and
* extends to the character at index {@code endIndex - 1}.
* Thus the length of the substring is {@code endIndex-beginIndex}.
*
* 举例:
* "hamburger".substring(4, 8) returns "urge"
* "smiles".substring(1, 5) returns "mile"
*
* @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if the
* {@code beginIndex} is negative, or
* {@code endIndex} is larger than the length of
* this {@code String} object, or
* {@code beginIndex} is larger than
* {@code endIndex}.
*/
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
结合token.substring(0, -1);
可知: beginIndex=0,endIndex = -1,int subLen = endIndex - beginIndex = (-1)-0 = -1;
。既然subLen<0
,所以就报出 StringIndexOutOfBoundsException
异常。
我们不妨看看StringIndexOutOfBoundsException
源码,如下所示:
/**
* Constructs a new {@code StringIndexOutOfBoundsException}
* class with an argument indicating the illegal index.
*
* @param index the illegal index.
*/
public StringIndexOutOfBoundsException(int index) {
super("String index out of range: " + index);
}
这里的index
参数就是subLen
的值,也就是-1。
3. 解决问题
既然知道了问题所在,我便将测试代码进行如下修改:
@Test
public void tokenGener() {
String token ="eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ7XCJ1c2VySWRcIjoxLFwidXNlcm5hbWVcIjpcImFkbWluXCJ9IiwiZXhwIjoxNjYxMzI5NTQ5fQ.bJANmLzpCYbSQ-3ymJ5DX-PMnY1FAWf0Q7OmFXEN3a-ngh-2Og31tisdiXI57SIxdE_X7nY-p4_XcUv-ZeiUQQ";
int index = token.indexOf(":") ;
if (index > 0){
token = token.substring(0, index);
}
JSONObject jsonObject = jwtConfig.parseToken(token);
System.out.println(jsonObject);
}
即可成功运行,如下图所示:
4. 出现该错误的常见方法,比如charAt()等
StringIndexOutOfBoundsException
是我们开发中常见的问题,遇到这种问题不要着急,一般我们截取字符串的位置【index】出现了错误。
除了substring
会抛出这个异常,以下几个方法也会抛出该异常:
-
String.charAt()
-
String.codePointAt()
-
String.codePointBefore()
-
String.subSequence()
-
String.getChars()
-
String.getBytes()