第二周

HttpServletRequest.getSession的两种方式
HttpServletRequest.getSession(ture) 等同于 HttpServletRequest.getSession()
HttpServletRequest.getSession(false) 等同于 如果当前Session没有就为null;

需要注意的地方是request.getSession() 等同于 request.getSession(true),除非我们确认session一定存在或者sesson不存在时明确有创建session的需要,否则尽量使用request.getSession(false)。在使用request.getSession()函数,通常在action中检查是否有某个变量/标记存放在session中。这个场景中可能出现没有session存在的情况,正常的判断应该是这样:
1.HttpSession session = request.getSession(false);  
2.if (session != null) {  
3.    String user_name = session.getAttribute("user_name");  
4.}  
如果项目中用到了Spring(其实只要是Java的稍大的项目,Spring是一个很好的选择),对session的操作就方便多了。如果需要在Session中取值,可以用WebUtils工具(org.springframework.web.util.WebUtils)的getSessionAttribute(HttpServletRequest request, String name)方法,
1./** 
2. * Check the given request for a session attribute of the given name. 
3. * Returns null if there is no session or if the session has no such attribute. 
4. * Does not create a new session if none has existed before! 
5. * @param request current HTTP request 
6. * @param name the name of the session attribute 
7. * @return the value of the session attribute, or <code>null</code> if not found 
8. */  
9.public static Object getSessionAttribute(HttpServletRequest request, String name) {  
10.    Assert.notNull(request, "Request must not be null");  
11.    HttpSession session = request.getSession(false);  
12.    return (session != null ? session.getAttribute(name) : null);  
13.}  
注:Assert是Spring工具包中的一个工具,用来判断一些验证操作,本例中用来判断reqeust是否为空,若为空就抛异常。
上面的代码又可以简洁一下啦,看吧:
[java] view plaincopy
1.HttpSession session = request.getSession(false);  
2.String user_name = WebUtils.getSessionAttribute(reqeust, "user_name");  
request.getHeader():
getHeader("Host"):请求的地址。
getHeader("Referer"):请求的完整地址.
getHeader("Accept-Language"):语言。。

request.getHeader(x-requested-with)
可以看到 Ajax 请求多了个 x-requested-with ,可以利用它,request.getHeader("x-requested-with"); 为 null,则为传统同步请求,为 XMLHttpRequest,则为 Ajax 异步请求。



过滤器的生命周期一般都要经过下面三个阶段
初始化
当容器第一次加载该过滤器时,init() 方法将被调用。该类在这个方法中包含了一个指向 Filter Config 对象的引用。我们的过滤器实际上并不需要这样做,因为其中没有使用初始化信息,这里只是出于演示的目的。

过滤
过滤器的大多数时间都消耗在这里。doFilter方法被容器调用,同时传入分别指向这个请求响应链中的 Servlet Request、Servlet Response 和 Filter Chain 对象的引用。然后过滤器就有机会处理请求,将处理任务传递给链中的下一个资源(通过调用 Filter Chain 对象引用上的 doFilter方法),之后在处理控制权返回该过滤器时处理响应。

析构
容器紧跟在垃圾收集之前调用 destroy()方法,以便能够执行任何必需的清理代码。

关于chain.doFilter(request,response)
他的作用是将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是你请求的资源。 一般filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一起 
request -> filter1 -> filter2 ->filter3 -> .... -> request resource.

@SuppressWarnings
J2SE 提供的最后一个批注是 @SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。
一点背景:J2SE 5.0 为 Java 语言增加了几个新的特性,并且和它们一起增加了许多新的警告并承诺在将来增加更多的警告。您可以为 "javac" 增加 -Xlint 参数来控制是否报告这些警告(如上面的 @Deprecated 部分所示)。
默认情况下,Sun 编译器以简单的两行的形式输出警告。通过添加 -Xlint:keyword 标记(例如 -Xlint:finally),您可以获得关键字类型错误的完整说明。通过在关键字前面添加一个破折号,写为 -Xlint:-keyword,您可以取消警告。(-Xlint 支持的关键字的完整列表可以在 javac 文档页面上找到。)下面是一个清单:

@SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,您就可以添加一个 @SuppressWarnings 批注,以使您不会再看到警告。虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止您对警告无动于衷 — 您看到的每一个警告都将值得注意。
下面是使用 @SuppressWarnings 来取消 deprecation 警告的一个例子:
 
public class DeprecatedExample2 {  @Deprecated  public static void foo() {  }}public class DeprecatedUser2 {  @SuppressWarnings(value={"deprecation"})public static void main(String[] args) {    DeprecatedExample2.foo();  }}
 
@SuppressWarnings 批注接收一个 "value" 变量,该变量是一个字符串数组,它指示将取消的警告。合法字符串的集合随编译器而变化,但在 JDK 上,可以传递给 -Xlint 的是相同的关键字集合(非常方便)。并且要求编译器忽略任何它们不能识别的关键字,这在您使用一些不同的编译器时非常方便。
因为 @SuppressWarnings 批注仅接收一个参数,并为该参数使用了特殊的名称 "value",所以您可以选择省略 value=,作为一种方便的缩写:
 
 
public class DeprecatedUser2 {  @SuppressWarnings({"deprecation"})public static void main(String[] args) {    DeprecatedExample2.foo();  }}
 
您可以将单个数组参数中的任意数量的字符串值传递给批注,并在任何级别上放置批注。例如,以下示例代码指示将取消整个类的 deprecation 警告,而仅在 main() 方法代码内取消 unchecked 和 fallthrough 警告:
 
import java.util.*;@SuppressWarnings({"deprecation"})public class NonGenerics {  @SuppressWarnings({"unchecked","fallthrough"})public static void main(String[] args) {    Runtime.runFinalizersOnExit();    List list = new ArrayList();    list.add("foo");  }  public static void foo() {    List list = new ArrayList();    list.add("foo");  }}
 
@SuppressWarnings 是否比前两个批注更有用?绝对是这样。不过,在 JDK 1.5.0 版本中还没有完全支持该批注,如果您用 1.5.0 来尝试它,那么它将类似无操作指令。调用 -Xlint:-deprecation 也没有任何效果。Sun 没有声明什么时候将增加支持,但它暗示这将在即将推出的一个 dot 版本中实现。
更进一步
如果您试图在 Javadocs 页面中查看这些属性,那么您可能很难找到它们。它们位于核心的 java.lang 包中,但有点隐蔽,它们出现在 Javadoc 类的最底端,列在 Exceptions 和 Errors 后面。



阿里巴巴推出的国产数据库连接池,据网上测试对比,比目前的DBCP或C3P0数据库连接池性能更好
 Druid数据库连接池的使用
简单使用介绍
Druid与其他数据库连接池使用方法基本一样(与DBCP非常相似),将数据库的连接信息全部配置给DataSource对象
 
下面给出2种配置方法实例:
1. 纯Java代码创建
dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUsername("root");dataSource.setPassword("11111111");dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/jspdemo"); dataSource.setInitialSize(5);dataSource.setMinIdle(1); dataSource.setMaxActive(10); // 启用监控统计功能 dataSource.setFilters("stat");// for mysql  dataSource.setPoolPreparedStatements(false);
 
2. 基于Spring创建
 
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">       <!-- 基本属性 url、user、password -->      <property name="url" value="${jdbc_url}" />      <property name="username" value="${jdbc_user}" />      <property name="password" value="${jdbc_password}" />      <!-- 配置初始化大小、最小、最大 -->      <property name="initialSize" value="1" />      <property name="minIdle" value="1" />       <property name="maxActive" value="20" />      <!-- 配置获取连接等待超时的时间 -->      <property name="maxWait" value="60000" />      <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->      <property name="timeBetweenEvictionRunsMillis" value="60000" />      <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->      <property name="minEvictableIdleTimeMillis" value="300000" />      <property name="validationQuery" value="SELECT 'x'" />      <property name="testWhileIdle" value="true" />      <property name="testOnBorrow" value="false" />      <property name="testOnReturn" value="false" />      <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->      <property name="poolPreparedStatements" value="true" />      <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />      <!-- 配置监控统计拦截的filters -->      <property name="filters" value="stat" /></bean>
启用Web监控统计功能需要在Web应用的web.xml中加入这个Servlet声明
<filter>
        <filter-name>DruidWebStatFilter</filter-name>
        <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
        <init-param>
            <param-name>exclusions</param-name>
            <param-value>/static/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>DruidWebStatFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
    <!-- druid监控 -->
    <servlet>
        <servlet-name>DruidStatView</servlet-name>
        <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DruidStatView</servlet-name>
        <url-pattern>/druid/*</url-pattern>
    </servlet-mapping>


Spring.xml配置:
<!-- 数据源配置, 使用 BoneCP 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
  <!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
 
    <!-- 基本属性 url、user、password -->
    <property name="url" value="jdbc:mysql://127.0.0.1:3306/html580?useUnicode=true&characterEncoding=utf-8" />
    <property name="username" value="root" />
    <property name="password" value="123456" />
 
    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="3" />
    <property name="minIdle" value="3" />
    <property name="maxActive" value="20" />
 
    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000" />
 
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
 
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000" />
 
    <property name="validationQuery" value="SELECT 'x'" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="false" />
    <property name="testOnReturn" value="false" />
 
    <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle使用)
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> -->
 
    <!-- 配置监控统计拦截的filters -->
  <property name="filters" value="stat" />
</bean>



  <servlet>      <servlet-name>DruidStatView</servlet-name>      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>  </servlet>  <servlet-mapping>      <servlet-name>DruidStatView</servlet-name>      <url-pattern>/druid/*</url-pattern>  <servlet-mapping>
通过 http://ip:port/druid/ 地址访问即可
 
项目地址
https://github.com/AlibabaTech/druid/wiki
直接下载发布版本即可,没必要下载源码重新编译
其中的FAQ部分很有参考价值

 Statement.RETURN_GENERATED_KEYS的作用:
常用在insert语句中,用于获取刚插入这行的自动增长的ID值
使用 PreparedStatement.RETURN_GENERATED_KEYS  可以获取刚刚插入自增ID值
例:
/************ 新增数据并返回新增数据的ID *********************/
	@SuppressWarnings("finally")
	public int insert(String sql, Object... params) {
		int executeUpdate_int = 0;
		boolean transactionCompleted  = false;
		int retry = 3;
		int returnId = -1;
		do {
			try {
				ct = connectWithDB();
				pS = ct.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
				for (int i = 0; i < params.length; i++) {
					pS.setObject(i + 1, params[i]);
				}
				// 执行操作
				executeUpdate_int = pS.executeUpdate();
				transactionCompleted = true;
				System.out.println("executeUpdate_int = " + executeUpdate_int);
				if(executeUpdate_int>0){
					LogFileWriter.write(DBUtil.class, "DataBase", "", "执行"+sql+"在第"+(4-retry)+"次的时候成功");
//ps.getGeneratedKeys(),获取自动增长数据行的数据集
					ResultSet r = pS.getGeneratedKeys();
		            if(r.next())
		            {
//r.getInt(1),获取第一列的int值
		            	returnId = r.getInt(1);
		            }
				}
	            
			} catch (SQLException e) {
				// TODO: handle exception
				//e.printStackTrace();
				String sqlState = e.getSQLState();  
				LogFileWriter.write(DBUtil.class, "DataBase", "",  "执行"+sql+"异常:"+e.getMessage()+"&sqlState:"+sqlState);
				if ("08S01".equals(sqlState) || "40001".equals(sqlState)||"08003".equals(sqlState))   
					{                  
						retry --;  
						LogFileWriter.write(DBUtil.class, "DataBase", "",  "执行"+sql+":重试第"+(3-retry)+"次");
					} else {                  
						retry = 0;              
					}
				//System.out.println(retry);
			} finally {
				DBUtil.getInstance().shutDownDB();
				return returnId;
			}
		} while (!transactionCompleted && (retry > 0));
	}


StringUtils的用法:
StringUtils 方法的操作对象是 java.lang.String 类型的对象,是 JDK 提供的 String 类型操作方法的补充,并且是 null 安全的(即如果输入参数 String 为 null 则不会抛出 NullPointerException ,而是做了相应处理,例如,如果输入为 null 则返回也是 null 等,具体可以查看源代码)。 
除了构造器,StringUtils 中一共有130多个方法,并且都是 static 的,所以我们可以这样调用 StringUtils.xxx() 
下面分别对一些常用方法做简要介绍: 
1. public static boolean isEmpty(String str) 
判断某字符串是否为空,为空的标准是 str==null 或 str.length()==0 
下面是 StringUtils 判断是否为空的示例: 

StringUtils.isEmpty(null) = true 
StringUtils.isEmpty("") = true 
StringUtils.isEmpty(" ") = false //注意在 StringUtils 中空格作非空处理 
StringUtils.isEmpty(" ") = false 
StringUtils.isEmpty("bob") = false 
StringUtils.isEmpty(" bob ") = false 

2. public static boolean isNotEmpty(String str) 
判断某字符串是否非空,等于 !isEmpty(String str) 
下面是示例: 

StringUtils.isNotEmpty(null) = false 
StringUtils.isNotEmpty("") = false 
StringUtils.isNotEmpty(" ") = true 
StringUtils.isNotEmpty(" ") = true 
StringUtils.isNotEmpty("bob") = true 
StringUtils.isNotEmpty(" bob ") = true 
3. public static boolean isBlank(String str) 
判断某字符串是否为空或长度为0或由空白符(whitespace) 构成 
下面是示例: 
StringUtils.isBlank(null) = true 
StringUtils.isBlank("") = true 
StringUtils.isBlank(" ") = true 
StringUtils.isBlank(" ") = true 
StringUtils.isBlank("\t \n \f \r") = true //对于制表符、换行符、换页符和回车符 

StringUtils.isBlank() //均识为空白符 
StringUtils.isBlank("\b") = false //"\b"为单词边界符 
StringUtils.isBlank("bob") = false 
StringUtils.isBlank(" bob ") = false 
4. public static boolean isNotBlank(String str) 
判断某字符串是否不为空且长度不为0且不由空白符(whitespace) 构成,等于 !isBlank(String str) 
下面是示例: 

StringUtils.isNotBlank(null) = false 
StringUtils.isNotBlank("") = false 
StringUtils.isNotBlank(" ") = false 
StringUtils.isNotBlank(" ") = false 
StringUtils.isNotBlank("\t \n \f \r") = false 
StringUtils.isNotBlank("\b") = true 
StringUtils.isNotBlank("bob") = true 
StringUtils.isNotBlank(" bob ") = true 
5. public static String trim(String str) 
去掉字符串两端的控制符(control characters, char <= 32) , 如果输入为 null 则返回null 
下面是示例: 
StringUtils.trim(null) = null 
StringUtils.trim("") = "" 
StringUtils.trim(" ") = "" 
StringUtils.trim(" \b \t \n \f \r ") = "" 
StringUtils.trim(" \n\tss \b") = "ss" 
StringUtils.trim(" d d dd ") = "d d dd" 
StringUtils.trim("dd ") = "dd" 
StringUtils.trim(" dd ") = "dd" 
6. public static String trimToNull(String str) 
去掉字符串两端的控制符(control characters, char <= 32) ,如果变为 null 或"",则返回 null 
下面是示例: 
StringUtils.trimToNull(null) = null 
StringUtils.trimToNull("") = null 
StringUtils.trimToNull(" ") = null 
StringUtils.trimToNull(" \b \t \n \f \r ") = null 
StringUtils.trimToNull(" \n\tss \b") = "ss" 
StringUtils.trimToNull(" d d dd ") = "d d dd" 
StringUtils.trimToNull("dd ") = "dd" 
StringUtils.trimToNull(" dd ") = "dd" 
7. public static String trimToEmpty(String str) 
去掉字符串两端的控制符(control characters, char <= 32) ,如果变为 null 或 "" ,则返回 "" 
下面是示例: 
StringUtils.trimToEmpty(null) = "" 
StringUtils.trimToEmpty("") = "" 
StringUtils.trimToEmpty(" ") = "" 
StringUtils.trimToEmpty(" \b \t \n \f \r ") = "" 
StringUtils.trimToEmpty(" \n\tss \b") = "ss" 
StringUtils.trimToEmpty(" d d dd ") = "d d dd" 
StringUtils.trimToEmpty("dd ") = "dd" 
StringUtils.trimToEmpty(" dd ") = "dd" 
8. public static String strip(String str) 
去掉字符串两端的空白符(whitespace) ,如果输入为 null 则返回 null 
下面是示例(注意和 trim() 的区别): 
StringUtils.strip(null) = null 
StringUtils.strip("") = "" 
StringUtils.strip(" ") = "" 
StringUtils.strip(" \b \t \n \f \r ") = "\b" 
StringUtils.strip(" \n\tss \b") = "ss \b" 
StringUtils.strip(" d d dd ") = "d d dd" 
StringUtils.strip("dd ") = "dd" 
StringUtils.strip(" dd ") = "dd" 
9. public static String stripToNull(String str) 
去掉字符串两端的空白符(whitespace) ,如果变为 null 或"",则返回 null 
下面是示例(注意和 trimToNull() 的区别): 
StringUtils.stripToNull(null) = null 
StringUtils.stripToNull("") = null 
StringUtils.stripToNull(" ") = null 
StringUtils.stripToNull(" \b \t \n \f \r ") = "\b" 
StringUtils.stripToNull(" \n\tss \b") = "ss \b" 
StringUtils.stripToNull(" d d dd ") = "d d dd" 
StringUtils.stripToNull("dd ") = "dd" 
StringUtils.stripToNull(" dd ") = "dd" 
10. public static String stripToEmpty(String str) 
去掉字符串两端的空白符(whitespace) ,如果变为 null 或"" ,则返回"" 
下面是示例(注意和 trimToEmpty() 的区别): 
StringUtils.stripToNull(null) = "" 
StringUtils.stripToNull("") = "" 
StringUtils.stripToNull(" ") = "" 
StringUtils.stripToNull(" \b \t \n \f \r ") = "\b" 
StringUtils.stripToNull(" \n\tss \b") = "ss \b" 
StringUtils.stripToNull(" d d dd ") = "d d dd" 
StringUtils.stripToNull("dd ") = "dd" 
StringUtils.stripToNull(" dd ") = "dd" 

以下方法只介绍其功能,不再举例: 
11. public static String strip(String str, String stripChars) 
去掉 str 两端的在 stripChars 中的字符。 
如果 str 为 null 或等于"" ,则返回它本身; 
如果 stripChars 为 null 或"" ,则返回 strip(String str) 。 
12. public static String stripStart(String str, String stripChars) 
和11相似,去掉 str 前端的在 stripChars 中的字符。 
13. public static String stripEnd(String str, String stripChars) 
和11相似,去掉 str 末端的在 stripChars 中的字符。 
14. public static String[] stripAll(String[] strs) 
对字符串数组中的每个字符串进行 strip(String str) ,然后返回。 
如果 strs 为 null 或 strs 长度为0,则返回 strs 本身 
15. public static String[] stripAll(String[] strs, String stripChars) 
对字符串数组中的每个字符串进行 strip(String str, String stripChars) ,然后返回。 
如果 strs 为 null 或 strs 长度为0,则返回 strs 本身 
16. public static boolean equals(String str1, String str2) 
比较两个字符串是否相等,如果两个均为空则也认为相等。 
17. public static boolean equalsIgnoreCase(String str1, String str2) 
比较两个字符串是否相等,不区分大小写,如果两个均为空则也认为相等。 
18. public static int indexOf(String str, char searchChar) 
返回字符 searchChar 在字符串 str 中第一次出现的位置。 
如果 searchChar 没有在 str 中出现则返回-1, 
如果 str 为 null 或 "" ,则也返回-1 
19. public static int indexOf(String str, char searchChar, int startPos) 
返回字符 searchChar 从 startPos 开始在字符串 str 中第一次出现的位置。 
如果从 startPos 开始 searchChar 没有在 str 中出现则返回-1, 
如果 str 为 null 或 "" ,则也返回-1 
20. public static int indexOf(String str, String searchStr) 
返回字符串 searchStr 在字符串 str 中第一次出现的位置。 
如果 str 为 null 或 searchStr 为 null 则返回-1, 
如果 searchStr 为 "" ,且 str 为不为 null ,则返回0, 
如果 searchStr 不在 str 中,则返回-1 
21. public static int ordinalIndexOf(String str, String searchStr, int ordinal) 
返回字符串 searchStr 在字符串 str 中第 ordinal 次出现的位置。 
如果 str=null 或 searchStr=null 或 ordinal<=0 则返回-1 
举例(*代表任意字符串): 
StringUtils.ordinalIndexOf(null, *, *) = -1 
StringUtils.ordinalIndexOf(*, null, *) = -1 
StringUtils.ordinalIndexOf("", "", *) = 0 
StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0 
StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1 
StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2 
StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5 
StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1 
StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4 
StringUtils.ordinalIndexOf("aabaabaa", "bc", 1) = -1 
StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0 
StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0 
22. public static int indexOf(String str, String searchStr, int startPos) 
返回字符串 searchStr 从 startPos 开始在字符串 str 中第一次出现的位置。 
举例(*代表任意字符串): 
StringUtils.indexOf(null, *, *) = -1 
StringUtils.indexOf(*, null, *) = -1 
StringUtils.indexOf("", "", 0) = 0 
StringUtils.indexOf("aabaabaa", "a", 0) = 0 
StringUtils.indexOf("aabaabaa", "b", 0) = 2 
StringUtils.indexOf("aabaabaa", "ab", 0) = 1 
StringUtils.indexOf("aabaabaa", "b", 3) = 5 
StringUtils.indexOf("aabaabaa", "b", 9) = -1 
StringUtils.indexOf("aabaabaa", "b", -1) = 2 
StringUtils.indexOf("aabaabaa", "", 2) = 2 
StringUtils.indexOf("abc", "", 9) = 3 
23. public static int lastIndexOf(String str, char searchChar) 
基本原理同18 
24. public static int lastIndexOf(String str, char searchChar, int startPos) 
基本原理同19 
25. public static int lastIndexOf(String str, String searchStr) 
基本原理同20 
26. public static int lastIndexOf(String str, String searchStr, int startPos) 
基本原理同22 
另附: 
String 的 split(String regex) 方法的用法 
如果我们需要把某个字符串拆分为字符串数组,则通常用 split(String regex) 来实现。 
例如: 
Java代码 复制代码 

1. String str = "aa,bb,cc,dd"; 
2. String[] strArray = str.split(","); 
3. System.out.println(strArray.length); 
4. for (int i = 0; i < strArray.length; i++) { 
5. System.out.println(strArray[i]); 
6. } 

String str = "aa,bb,cc,dd"; String[] strArray = str.split(","); System.out.println(strArray.length); for (int i = 0; i < strArray.length; i++) { System.out.println(strArray[i]); } 

结果为: 
4 
aa 
bb 
cc 
dd 
如果, 
String str = "aa.bb.cc.dd"; 
String[] strArray = str.split("."); 
则结果为:0 
为什么结果不是我们所想的呢,原因是参数 String regex 是正则表达式 (regular expression) 而不是普通字符串,而 "." 在正则表达式中有特殊含义,表示匹配所有单个字符。如果要那样拆分,我们必须给 "." 进行转义,String[] strArray = str.split(".") 修改为 String[] strArray = str.split("\\.") 即可。 
另外有关 StringUtils 的详细 API 请参见官方网站: 

HttpClient 基本功能的使用
GET 方法
使用 HttpClient 需要以下 6 个步骤:
1. 创建 HttpClient 的实例
2. 创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址
3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例
4. 读 response
5. 释放连接。无论执行方法是否成功,都必须释放连接
6. 对得到后的内容进行处理
1、当不需要使用任何证书访问https网页时,只需配置信任任何证书
http://hougbin.iteye.com/blog/1196063
http://www.ibm.com/developerworks/cn/opensource/os-httpclient/

Java代码  
1.HttpClient http = new HttpClient();  
2.String url = "https://payment.cib.com.cn/payment/api/rest";  
3.Protocol myhttps = new Protocol("https", new MySSLProtocolSocketFactory(), 443);   
4.Protocol.registerProtocol("https", myhttps);   
5.PostMethod post = new PostMethod(url);  
6.	httpclient.executeMethod(post);
7.	String res = post.getResponseBodyAsString();
8.post.releaseConnection();// 释放连接


Json相关
对于element方法产生的结果,会已数组作为遍历对象,大小为1, $('#contenttype'+data.type).html(data.name)只会执行一次;
对于fromObject方法产生的结果,会已json对象作为遍历对象,大小为4, 更方便一些;
JSON-lib包是一个beans,collections,maps,java arrays 和XML和JSON互相转换的包。在本例中,我们将使用JSONObject类创建JSONObject对象,然后我们打印这些对象的值。为了使用JSONObject对象,我们要引入"net.sf.json"包。为了给对象添加元素,我们要使用put()方法。
package com.hwy;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
public class JSONObjectSample {
 //创建JSONObject对象   
    private static JSONObject createJSONObject(){   
        JSONObject jsonObject = new JSONObject();   
        jsonObject.put("username","huangwuyi");   
        jsonObject.put("sex", "男");   
        jsonObject.put("QQ", "999999999");   
        jsonObject.put("Min.score", new Integer(99));   
        jsonObject.put("nickname", "梦中心境");   
        return jsonObject;   
    }   
    public static void main(String[] args) {   
        JSONObject jsonObject = JSONObjectSample.createJSONObject();   
        //输出jsonobject对象   
        System.out.println("jsonObject==>"+jsonObject);   
           
        //判读输出对象的类型   
        boolean isArray = jsonObject.isArray();   
        boolean isEmpty = jsonObject.isEmpty();   
        boolean isNullObject = jsonObject.isNullObject();   
        System.out.println("isArray:"+isArray+" isEmpty:"+isEmpty+" isNullObject:"+isNullObject);  
           
        //添加属性   
        jsonObject.element("address", "福建省厦门市");   
        System.out.println("添加属性后的对象==>"+jsonObject);   
           
        //返回一个JSONArray对象   
        JSONArray jsonArray = new JSONArray();   
        jsonArray.add(0, "this is a jsonArray value");   
        jsonArray.add(1,"another jsonArray value");   
        jsonObject.element("jsonArray", jsonArray);   
        JSONArray array = jsonObject.getJSONArray("jsonArray");   
        System.out.println("返回一个JSONArray对象:"+array);   
        //添加JSONArray后的值   
//        {"username":"huangwuyi","sex":"男","QQ":"999999999","Min.score":99,"nickname":"梦中心境","address":"福建省厦门市","jsonArray":["this is a jsonArray value","another jsonArray value"]} 
        System.out.println("结果="+jsonObject);   
           
        //根据key返回一个字符串   
        String username = jsonObject.getString("username");   
        System.out.println("username==>"+username);  
        
        //把字符转换为 JSONObject
        String temp=jsonObject.toString();
        JSONObject object = JSONObject.fromObject(temp);
        //转换后根据Key返回值
        System.out.println("qq="+object.get("QQ"));
        
    }  
}


TimeUnit是什么?
TimeUnit是java.util.concurrent包下面的一个类,TimeUnit提供了可读性更好的线程暂停操作,通常用来替换Thread.sleep(),在很长一段时间里Thread的sleep()方法作为暂停线程的标准方式,几乎所有Java程序员都熟悉它,事实上sleep方法本身也很常用而且出现在很多面试中。如果你已经使用过Thread.sleep(),当然我确信你这样做过,那么你一定熟知它是一个静态方法,暂停线程时它不会释放锁,该方法会抛出InterrupttedException异常(如果有线程中断了当前线程)。但是我们很多人并没有注意的一个潜在的问题就是它的可读性。Thread.sleep()是一个重载方法,可以接收长整型毫秒和长整型的纳秒参数,这样对程序员造成的一个问题就是很难知道到底当前线程是睡眠了多少秒、分、小时或者天。看看下面这个Thread.sleep()方法:
1	Thread.sleep(2400000)
粗略一看,你能计算出当前线程是等待多长时间吗?可能有些人可以,但是对于大多数程序员来说这种写法的可读性还是很差的,你需要把毫秒转换成秒和分,让我们来看看另外一个例子,这个例子比前面那个例子可读性稍微好一点:
1	Thread.sleep(4*60*1000);
这比前面那个例子已经好多了,但是仍然不是最好的,你注意到睡眠时间用毫秒,不容易猜出当前线程将等待4分钟。TimeUnit类解决了这个问题,通过指定DAYS、HOURS、MINUTES,SECONDS、MILLISECONDS和NANOSECONDS。java.utils.concurrent .TimeUnit 是Java枚举应用场景中最好的例子之一,所有TimeUnit都是枚举实例,让我们来看看线程睡眠4分钟用TimeUnit是如何使用的。
1	TimeUnit.MINUTES.sleep(4);  // sleeping for 1 minutes
类似你可以采用秒、分、小时级别来暂停当前线程。你可以看到这比Thread的sleep方法的可读的好多了。记住TimeUnit.sleep()内部调用的Thread.sleep()也会抛出InterruptException。你也可以查看JDK源代码去验证一下。下面是一个简单例子,它展示如果使用TimeUnit.sleep()方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20	/**
 *
 * Java program to demonstrate how to use TimeUnit.sleep() method in Java.
 * TimeUnit is a new way of introducing pause in Java program.
 * @author Javin
 */
public class TimeUnitTest {
 
    public static void main(String args[]) throws InterruptedException {
 
        System.out.println("Sleeping for 4 minutes using Thread.sleep()");
        Thread.sleep(4 * 60 * 1000);
        System.out.println("Sleeping for 4 minutes using TimeUnit sleep()");
 
        TimeUnit.SECONDS.sleep(4);
        TimeUnit.MINUTES.sleep(4);
        TimeUnit.HOURS.sleep(1);
        TimeUnit.DAYS.sleep(1);
    }
}
除了sleep的功能外,TimeUnit还提供了便捷方法用于把时间转换成不同单位,例如,如果你想把秒转换成毫秒,你可以使用下面代码:
1	TimeUnit.SECONDS.toMillis(44)
它将返回44,000
TimeUnit vs Thread.sleep()
目前我们讨论使用TimeUnit的好处是提高了可读性,但是有时候觉得其他方法更好,因为Thread.sleep()伴随java很早就出现了,几乎所有程序员都知道Thread.sleep(),都知道是将当前线程暂停,而对TimeUnit并不太熟悉。两个原因:一是对比起Thread.sleep(),TimeUnit不是很常用,第二是在它不在Thread类中,就像wait和notify同样不是在Thread中,反正这些需要一段时间才能被采用,并成为一个标准的方式。
总结来说在你想用Thread.sleep()方法的地方你最好使用TimeUnit.sleep()方法来代替。它不尽可以提高代码的可读性而且能更加熟悉java.util.concurrent包,因为TimeUnit在并发编程中也是一个关键API。
何谓getDefaultInstance? 
从处理流程中可以看出,首先是从缓存中查找是否有properties存在 
如果存在,则加载默认的properties 
如果不存在才加载用户自己定义的properties, 
所以当一个应用为每个用户独立创建properties的时候,还是应该调用getInstance, 
除非你希望有一个默认的properties让用户使用
session.getdefaultinstance和getinstance的区别 :
 如果想要同时使用两个帐号发送javamail,比如使用1@a.com发送1#邮件,使用2@a.com发送2#邮件,这时候,你就需要同时创建两个java.mail.Session对象。但是如果你仍然使用Session.getDefaultInstance创建session对象的话,你会发现,第二个username:2@a.com创建的session永远都和第一个一样,这是为什么呢?因为,getDefaultInstance是真正单例模式,而且,里面的username和password属性是final型的,无法更改。所以,你会发现两封email都是由1@a.com发出来的。所以这个时候你要使用javax.mail.Session.getInstance()方法来创建session对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发哥1997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值