- 浏览: 7875 次
- 性别:
- 来自: 北京
最新评论
Java字符串操作小记
JAVA 把字符串间的若干空格保留一个
javascript和java里的回车换行符的处理
tomcat 配置 小记
Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,轻微时,会使系统性能急剧下降,严重时,将导致系统无法运行,影响系统的稳定性。当内存不够用时,常见的问题就是报tomcat内存益处错误,从儿导致客户端包500错误的,如下:解决方法主要是加大TOMCAT可利用内存,并在程序当中加大内存使用。因此根据应用的需求,有必要调整JVM使用内存的大小。现在将手工修改tomcat内存的方法及注意事项列出,希望能对新人有所帮助。
tomcat提供了两种安装模式,即免安装(*.zip)和安装(*.exe)方式。针对不同的安装方式下修改tomcat内存大小的方法几注意问题(windows环境):
方式1:当选择安装方式时,可以在安装tomcat的过程进行设置tomcat初始化内存的大小。但是假如说在安装时没有选择,或者应用改变了,需要增加tomcat内存时怎么半呢?此时,我们就要手工修改tomcat的一些文件了:
看了很多网上的资料,都是说修改<CATALINA_HOME>\bin\catalina.bat文件的内容,即在里面增加一行代码:
set JAVA_OPTS=-Xms512m -Xmx512m //表示初始化最小可用内存和最大可用内存都是512MB(修改相应值即可)
就可以将JAVA虚拟机分配内存 508.0625MB的!
但是很多人修改后,发现修改并没有起作用,即通过windows的服务启动tomcat时,实际的内存还是默认的,修改的设置并没有起作用;而通过<CATALINA_HOME>\bin\startup.bat 启动却是生效的。这是为什么呢?因为在安装过程中,JVM的初始化参数已经写在注册表中了,由于没有修改注册表中相关参数,所以以windows服务方式启动时,修改的并没有生效。而通过<CATALINA_HOME>\bin\startup.bat 启动直接是通过<CATALINA_HOME>\bin\catalina.bat文件中的配置的。你需要重新加载到系统服务中才生效,或者你手工在注册表中查找修改启动值,加载到服务中的时候参数已经配置好了,自己修改artup.bat不会改变注册表中的参数设置。
解决方法:修改注册表中的参数,加入JVM初始化内存的参数:
方式2:针对免安装的用户,也可以通过将tomcat注册为windows的一个服务的方式来实现:‘
我们可以对service.bat文件做一些其他修改,使tomcat更加能满足我们各种不同需求时的要求
1. 如果让tomcat编译jsp文件,就在PR_CLASSPATH中加入J2SDK的tools.jar
修改前:
set PR_CLASSPATH=%CATALINA_HOME%\bin\bootstrap.jar
修改后:
set PR_CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\bin\bootstrap.jar
2.要使用一个特定的JVM,就要修改jvm的参数;要使注册的windows服务的启动方式为自动,增加--Startup Automatic,这个是比较常用的;要用定制的server.xml配置文件并且传递多个参数给StartClass,要修改StartParams的值,各个值之间用分号分隔:
修改前:
3. 指定最大和最小的内存限制,要增加jvm的初始参数
修改前:
4.有时注册windows服务成功后,但是启动服务时显示“发生服务特定错误: 0.”
就是因为jvm没有指定,修改Jvm auto为Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll"后重新注册windows服务就可以启动了。
Struts2中 用OGNL表达式定义字符串常量 与单个字符常量需要注意的一个小细节
具体记录如下:
注意上面红色部分的标识。当定义的变量为单个字符是,必须外面是单引号,字符用双引号引起。
附:转载OGNL表达式相关的知识点:
OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
为什么使用OGNL
相对于其它的表达式语言,OGNL的功能更为强大,它提供了很多高级而必需的特性,例如强大的类型转换功能、静态或实例方法的执行、跨集合投影,以及动态lambda表达式定义等。
OGNL基础
OGNL表达式的计算都是围绕OGNL上下文来进行的,OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类(实现了 java.util.Map接口)来表示。OGNL上下文可以包含一个或多个JavaBean对象,在这些对象中有一个是特殊的,这个对象就是上下文的根 (root)对象。如果在写表达式的时候,没有指定使用上下文中的哪一个对象,那么根对象将被假定为表达式所依据的对象。
在OGNL上下文中,只能有一个根对象,如果你访问根对象,那么在写表达式的时候,直接写对象的属性就可以了;否则,你需要使用“#key”前缀,例如表达式#namager.name。
OGNL表达式
OGNL表达式的基础单元就是导航链,通常简称为链(chain)。最简单的链由下列部分组成:
1、属性名:如name和manager.name;
2、方法调用:如manager.hashCode(),返回manager对象的散列码;
3、数组索引:如emals[0],返回当前对象的邮件列表中的第一个邮件地址。
所有OGNL表达式的计算都是在当前对象的上下文中,一个链简单地使用链中先前链接的结果作为下一步计算的当前对象。我们看如下所示的链:
name.toCharArray()[0].numericValue.toString()
这个表达式按照下列的步骤进行计算:
1、获取根对象的name属性;
2、在String结果上调用toCharArray()方法;
3、从char数组中提取第一个字符;
4、从提取的字符对象上行到numericValue属性(这个字符被表示为Character对象,Character类有一个getNumericValue()方法);
5、在Integer对象结果上调用toString()方法。
这个表达式最终结果是最后返回的toString()方法调用返回的字符串。
常量
OGNL支持的所有常量类型:
1、字符串常量:
以单引号或双引号括起来的字符串。如”hello”,’hello’。
不过要注意的是,如果是单个字符的字符串常量,必须使用双引号。
2、字符常量:
以单引号括起来的字符。如’a'。
3、数值常量:
除了Java中的int、long、float和double外,OGNL还让你使用“b”或“B”后缀指定BigDecimal常量,用“h”“H”后缀指定BigInteger常量。
4、布尔常量:
true和false。
5、null常量。
操作符
OGNL除了支持所有的Java操作符外,还支持以下几种:
1、逗号,
与C语言中的逗号操作符类似。
2、花括号{}
用于创建列表,元素之间用逗号分隔。
3、in和not in
用于判断一个值是否在集合中。
访问JavaBean的属性
假如有一个employee对象作为OGNL上下文的根对象,那对于下面的表达式:
1、name
对应的java代码是employee.getName();
2、address.country
对应的java代码是employee.getAddress().getCountry();
访问静态方法和静态字段
@class@method(args) //调用静态方法
@class@field //调用静态字段
其中class必须给出完整的类名(包括包名),如果省略class,那么默认使用的类是java.util.Math,如:
@@min(5,3)
@@max(5,3)
@@PI
索引访问
OGNL支持多种索引方式的访问。
1、数组和列表索引
在OGNL中,数组和列表可以大致看成是一样的。
如:array[0]、list[0]。表达式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
2、JavaBean的索引属性
要使用索引属性,需要提供两对setter和getter方法,一对用于数组,一对用于数组中的元素。
如:有一个索引属性interest,它的getter和setter如下
对于表达式interest[2],OGNL可以正确解释这个表达式,调用getInterest(2)方法。如果是设置的情况下,会调用setInterest(2,value)方法。
3、OGNL对象的索引属性
JavaBean的索引属性只能使用整型作为索引,OGNL扩展了索引属性的概念,可以使用任意的对象来作为索引。
对集合进行操作
1、创建集合:
创建列表
使用花括号将元素包含起来,元素之间使用逗号分隔。如{’zhangsan’,'lisi’,'wangwu’}
创建数组
OGNL中创建数组与Java语言中创建数组类似。
创建Map
Map使用特殊的语法来创建 #{”key”:value, ……}
如果想指定创建的Map类型,可以在左花括号前指定Map实现类的类名。如:
#@java.util.LinkedHashMap@{”key”:”value”,….}
Map通过key来访问,如map["key"]或map.key。
2、投影
OGNL提供了一种简单的方式在一个集合中对每一个元素闻调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称之为投影。
假如employees是一个包含了employee对象的列表,那么
#employees.{name}将返回所有雇员的名字的列表。
在投影期间,使用#this变量来引用迭代中的当前元素。
如:objects.{#this instanceof String? #this: #this.toString()}
3、选择
OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。
如#employees.{?#this.salary>3000}
将返回薪水大于3000的所有雇员的列表。
#employees.{^#this.salary>3000}
将返回第一个薪水大于3000的雇员的列表。
#employees.{$#this.salary>3000}
将返回最后一个薪水大于3000的雇员的列表。
lambda表达式
lambda表达式的语法是: :[...]。OGNL中的lambda表达式只能使用一个参数,这个参数通过#this引用。
如:
OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
为什么使用OGNL
相对于其它的表达式语言,OGNL的功能更为强大,它提供了很多高级而必需的特性,例如强大的类型转换功能、静态或实例方法的执行、跨集合投影,以及动态lambda表达式定义等。
OGNL基础
OGNL表达式的计算都是围绕OGNL上下文来进行的,OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类(实现了 java.util.Map接口)来表示。OGNL上下文可以包含一个或多个JavaBean对象,在这些对象中有一个是特殊的,这个对象就是上下文的根 (root)对象。如果在写表达式的时候,没有指定使用上下文中的哪一个对象,那么根对象将被假定为表达式所依据的对象。
在OGNL上下文中,只能有一个根对象,如果你访问根对象,那么在写表达式的时候,直接写对象的属性就可以了;否则,你需要使用“#key”前缀,例如表达式#namager.name。
OGNL表达式
OGNL表达式的基础单元就是导航链,通常简称为链(chain)。最简单的链由下列部分组成:
1、属性名:如name和manager.name;
2、方法调用:如manager.hashCode(),返回manager对象的散列码;
3、数组索引:如emals[0],返回当前对象的邮件列表中的第一个邮件地址。
所有OGNL表达式的计算都是在当前对象的上下文中,一个链简单地使用链中先前链接的结果作为下一步计算的当前对象。我们看如下所示的链:
name.toCharArray()[0].numericValue.toString()
这个表达式按照下列的步骤进行计算:
1、获取根对象的name属性;
2、在String结果上调用toCharArray()方法;
3、从char数组中提取第一个字符;
4、从提取的字符对象上行到numericValue属性(这个字符被表示为Character对象,Character类有一个getNumericValue()方法);
5、在Integer对象结果上调用toString()方法。
这个表达式最终结果是最后返回的toString()方法调用返回的字符串。
常量
OGNL支持的所有常量类型:
1、字符串常量:
以单引号或双引号括起来的字符串。如”hello”,’hello’。
不过要注意的是,如果是单个字符的字符串常量,必须使用双引号。
2、字符常量:
以单引号括起来的字符。如’a'。
3、数值常量:
除了Java中的int、long、float和double外,OGNL还让你使用“b”或“B”后缀指定BigDecimal常量,用“h”“H”后缀指定BigInteger常量。
4、布尔常量:
true和false。
5、null常量。
操作符
OGNL除了支持所有的Java操作符外,还支持以下几种:
1、逗号,
与C语言中的逗号操作符类似。
2、花括号{}
用于创建列表,元素之间用逗号分隔。
3、in和not in
用于判断一个值是否在集合中。
访问JavaBean的属性
假如有一个employee对象作为OGNL上下文的根对象,那对于下面的表达式:
1、name
对应的java代码是employee.getName();
2、address.country
对应的java代码是employee.getAddress().getCountry();
访问静态方法和静态字段
@class@method(args) //调用静态方法
@class@field //调用静态字段
其中class必须给出完整的类名(包括包名),如果省略class,那么默认使用的类是java.util.Math,如:
@@min(5,3)
@@max(5,3)
@@PI
索引访问
OGNL支持多种索引方式的访问。
1、数组和列表索引
在OGNL中,数组和列表可以大致看成是一样的。
如:array[0]、list[0]。表达式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
2、JavaBean的索引属性
要使用索引属性,需要提供两对setter和getter方法,一对用于数组,一对用于数组中的元素。
如:有一个索引属性interest,它的getter和setter如下
对于表达式interest[2],OGNL可以正确解释这个表达式,调用getInterest(2)方法。如果是设置的情况下,会调用setInterest(2,value)方法。
3、OGNL对象的索引属性
JavaBean的索引属性只能使用整型作为索引,OGNL扩展了索引属性的概念,可以使用任意的对象来作为索引。
对集合进行操作
1、创建集合:
创建列表
使用花括号将元素包含起来,元素之间使用逗号分隔。如{’zhangsan’,'lisi’,'wangwu’}
创建数组
OGNL中创建数组与Java语言中创建数组类似。
创建Map
Map使用特殊的语法来创建 #{”key”:value, ……}
如果想指定创建的Map类型,可以在左花括号前指定Map实现类的类名。如:
#@java.util.LinkedHashMap@{”key”:”value”,….}
Map通过key来访问,如map["key"]或map.key。
2、投影
OGNL提供了一种简单的方式在一个集合中对每一个元素闻调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称之为投影。
假如employees是一个包含了employee对象的列表,那么
#employees.{name}将返回所有雇员的名字的列表。
在投影期间,使用#this变量来引用迭代中的当前元素。
如:objects.{#this instanceof String? #this: #this.toString()}
3、选择
OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。
如#employees.{?#this.salary>3000}
将返回薪水大于3000的所有雇员的列表。
#employees.{^#this.salary>3000}
将返回第一个薪水大于3000的雇员的列表。
#employees.{$#this.salary>3000}
将返回最后一个薪水大于3000的雇员的列表。
lambda表达式
lambda表达式的语法是: :[...]。OGNL中的lambda表达式只能使用一个参数,这个参数通过#this引用。
如:
Struts2 字符串截取
<s:set name="hello" value="'Hello Miky as Miky'"></s:set> ----定义源字符串
<s:property value="#hello.substring(#hello.indexOf('as')+2)"/> ---输出字符串。结果为 Miky
posted @ 2009-05-05 22:55 MikyTan 阅读(108) | 评论 (0) | 编辑 收藏
JSP 中使用Struts2的值 (Strust2 中调用JAVA的公共类方法)
Struts2的值是保存在ValueStack中的,假设有一个字符串str,我们一般是这么取值的:
<s:property value="str"/> 或者 ${str}
如果想在jsp中使用的话,可以这么取:
<%@ page import="com.opensymphony.xwork2.util.ValueStack" %>
……
<%= ((ValueStack)request.getAttribute("struts.valueStack")).findString("str") %>
也可以把ValueStack中的值先放到attribute中,然后直接取attribute的值:
<s:set name="str" value="%{str}" />
<%=request.getAttribute("str") %>
struts2的页面中调用函数
方法一:
func是类com.common.Constant里面的一个静态方法
str是动态的参数
方法二:
func是类com.common.StrutsHelper里面的一个普通方法
str是动态方法
s:bean其实是对类StrutsHelper的实例化,跟方法一有些区别,方法一里的函数必须是静态的
产品时间段(StartDate,EndDate)SQL查询
表 a 字段,id,开始时间,结束时间,价格
1,2008-01-01,2008-09-10,220.0
2,2008-09-11,2008-09-30,280.0
3,2008-10-01,2008-10-10,320.0
3,2008-10-11,2008-12-31,350.0
输入一个开始时间,一个结束时间,返回这段时间内每天的价格,最好返回每天的日期和对应的价格
例输入开始时间2008-09-09,结束时间2008-09-13
返回
2008-09-09,220
2008-09-10,220
2008-09-11,280
2008-09-12,280
2008-09-13,280
方案一:采用存储过程的方案!
方案二:采用Case方案
id 开始时间 结束时间 价格
----------- ------------------------------------------------------ ------------------------------------------------------ ------
1 2008-09-09 00:00:00.000 2008-09-10 00:00:00.000 220.0
2 2008-09-11 00:00:00.000 2008-09-13 00:00:00.000 280.0
posted @ 2009-04-23 20:50 MikyTan 阅读(150) | 评论 (0) | 编辑 收藏
jQuery实现input文本框内灰色提示文本效果 和 input标签获取焦点是文本框内提示信息清空
摘要: 一、jQuery实现input文本框内灰色提示文本效果 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <titl... 阅读全文
posted @ 2009-04-23 11:50 MikyTan 阅读(2949) | 评论 (0) | 编辑 收藏
酒店价格间夜显示(JavaScript 实现)
摘要: 酒店间夜价格显示实现: 跨周: <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC&... 阅读全文
posted @ 2009-04-21 13:31 MikyTan 阅读(64) | 评论 (0) | 编辑 收藏
JavaScript 取Table表格中的值
注意,为了兼容IE跟FireFix,不要用 innerText
xmlbeans dom level 3 not implemented
今天在用XmlBeans解析XML DOC时,遇到“xmlbeans dom level 3 not implemented”的解决办法!
问题产生的原因:
1、由于在生成的XML结构中插入了一些未在XSD中定义的节点,那么这些节点无法用XMLBeans所采用的对象的方法获取,只能采用DOM的方式来处理,但在处理的过程中报
COPY 非原创
JAVA 把字符串间的若干空格保留一个
String str="你 好, Fuck You"; System.out.println(str.replaceAll("\\s+"," "));
javascript和java里的回车换行符的处理
request.getParameter("modelTail").replaceAll("<br>",String.valueOf((char)13)).replaceAll("<bt>",String.valueOf((char)10)) content.replaceAll(String.valueOf((char)13),"<br>").replaceAll(String.valueOf((char)10),"<bt>") document.all.txtContent.value = (varGet2.Content).replace("<br>",String.fromCharCode(13)).replace("<bt>",String.fromCharCode(10)); javascript里的String.fromCharCode 和 strObj.charCodeAt(index)
tomcat 配置 小记
Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,轻微时,会使系统性能急剧下降,严重时,将导致系统无法运行,影响系统的稳定性。当内存不够用时,常见的问题就是报tomcat内存益处错误,从儿导致客户端包500错误的,如下:解决方法主要是加大TOMCAT可利用内存,并在程序当中加大内存使用。因此根据应用的需求,有必要调整JVM使用内存的大小。现在将手工修改tomcat内存的方法及注意事项列出,希望能对新人有所帮助。
tomcat提供了两种安装模式,即免安装(*.zip)和安装(*.exe)方式。针对不同的安装方式下修改tomcat内存大小的方法几注意问题(windows环境):
方式1:当选择安装方式时,可以在安装tomcat的过程进行设置tomcat初始化内存的大小。但是假如说在安装时没有选择,或者应用改变了,需要增加tomcat内存时怎么半呢?此时,我们就要手工修改tomcat的一些文件了:
看了很多网上的资料,都是说修改<CATALINA_HOME>\bin\catalina.bat文件的内容,即在里面增加一行代码:
set JAVA_OPTS=-Xms512m -Xmx512m //表示初始化最小可用内存和最大可用内存都是512MB(修改相应值即可)
如在catalina.bat的 rem ----- Execute The Requested Command echo Using CATALINA_BASE: %CATALINA_BASE% echo Using CATALINA_HOME: %CATALINA_HOME% echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR% echo Using JAVA_HOME: %JAVA_HOME% 这一栏改为 rem ----- Execute The Requested Command set JAVA_OPTS=-Xms512m -Xmx512m echo Using CATALINA_BASE: %CATALINA_BASE% echo Using CATALINA_HOME: %CATALINA_HOME% echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR% echo Using JAVA_HOME: %JAVA_HOME%
就可以将JAVA虚拟机分配内存 508.0625MB的!
但是很多人修改后,发现修改并没有起作用,即通过windows的服务启动tomcat时,实际的内存还是默认的,修改的设置并没有起作用;而通过<CATALINA_HOME>\bin\startup.bat 启动却是生效的。这是为什么呢?因为在安装过程中,JVM的初始化参数已经写在注册表中了,由于没有修改注册表中相关参数,所以以windows服务方式启动时,修改的并没有生效。而通过<CATALINA_HOME>\bin\startup.bat 启动直接是通过<CATALINA_HOME>\bin\catalina.bat文件中的配置的。你需要重新加载到系统服务中才生效,或者你手工在注册表中查找修改启动值,加载到服务中的时候参数已经配置好了,自己修改artup.bat不会改变注册表中的参数设置。
解决方法:修改注册表中的参数,加入JVM初始化内存的参数:
HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions 值为 -Dcatalina.home="C:\ApacheGroup\Tomcat 5.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed" -Xrs 如加入 -Xms512m -Xmx800m
方式2:针对免安装的用户,也可以通过将tomcat注册为windows的一个服务的方式来实现:‘
我们可以对service.bat文件做一些其他修改,使tomcat更加能满足我们各种不同需求时的要求
1. 如果让tomcat编译jsp文件,就在PR_CLASSPATH中加入J2SDK的tools.jar
修改前:
set PR_CLASSPATH=%CATALINA_HOME%\bin\bootstrap.jar
修改后:
set PR_CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\bin\bootstrap.jar
2.要使用一个特定的JVM,就要修改jvm的参数;要使注册的windows服务的启动方式为自动,增加--Startup Automatic,这个是比较常用的;要用定制的server.xml配置文件并且传递多个参数给StartClass,要修改StartParams的值,各个值之间用分号分隔:
修改前:
"%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm auto --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop 修改后: "%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll" --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams "-config;%CUSTOM_SERVERXML_FILE%;-nonaming;start" --StopParams stop --Startup Automatic
3. 指定最大和最小的内存限制,要增加jvm的初始参数
修改前:
"%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions "-Dcatalina.base=%CATALINA_BASE%;-Dcatalina.home=%CATALINA_HOME%;-Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed" --StartMode jvm --StopMode jvm 修改后: "%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions "-Xms128M;-Xmx256M;-Dcatalina.base=%CATALINA_BASE%;-Dcatalina.home=%CATALINA_HOME%;-Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed" --StartMode jvm --StopMode jvm
4.有时注册windows服务成功后,但是启动服务时显示“发生服务特定错误: 0.”
就是因为jvm没有指定,修改Jvm auto为Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll"后重新注册windows服务就可以启动了。
Struts2中 用OGNL表达式定义字符串常量 与单个字符常量需要注意的一个小细节
具体记录如下:
<s:set name="fieldType" value="'condition'"></s:set> <s:set name="countryID" value="'CHN'"></s:set> <s:set name="corpCenter" value="#session.opType.corpCenter"></s:set> <s:set name="corpID" value="#session.opType.corpID"></s:set> <s:set name="corpType" value="#session.opType.corpType"></s:set> <s:set name="agentID" value=""></s:set> <s:set name="city" value=""></s:set> <s:set name="agentType" value='"A"'></s:set>
注意上面红色部分的标识。当定义的变量为单个字符是,必须外面是单引号,字符用双引号引起。
<s:action name="ReportBeanListAction" id="reportBeanSkyechoAgentListAction"> <s:param name="agentID"><s:property value="agentID" /></s:param> <s:param name="city"><s:property value="city" /></s:param> <s:param name="corpID"><s:property value="corpID" /></s:param> <s:param name="corpCenter"><s:property value="corpCenter" /></s:param> <s:param name="agentType"><s:property value="agentType" /></s:param> </s:action>
附:转载OGNL表达式相关的知识点:
OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
为什么使用OGNL
相对于其它的表达式语言,OGNL的功能更为强大,它提供了很多高级而必需的特性,例如强大的类型转换功能、静态或实例方法的执行、跨集合投影,以及动态lambda表达式定义等。
OGNL基础
OGNL表达式的计算都是围绕OGNL上下文来进行的,OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类(实现了 java.util.Map接口)来表示。OGNL上下文可以包含一个或多个JavaBean对象,在这些对象中有一个是特殊的,这个对象就是上下文的根 (root)对象。如果在写表达式的时候,没有指定使用上下文中的哪一个对象,那么根对象将被假定为表达式所依据的对象。
在OGNL上下文中,只能有一个根对象,如果你访问根对象,那么在写表达式的时候,直接写对象的属性就可以了;否则,你需要使用“#key”前缀,例如表达式#namager.name。
OGNL表达式
OGNL表达式的基础单元就是导航链,通常简称为链(chain)。最简单的链由下列部分组成:
1、属性名:如name和manager.name;
2、方法调用:如manager.hashCode(),返回manager对象的散列码;
3、数组索引:如emals[0],返回当前对象的邮件列表中的第一个邮件地址。
所有OGNL表达式的计算都是在当前对象的上下文中,一个链简单地使用链中先前链接的结果作为下一步计算的当前对象。我们看如下所示的链:
name.toCharArray()[0].numericValue.toString()
这个表达式按照下列的步骤进行计算:
1、获取根对象的name属性;
2、在String结果上调用toCharArray()方法;
3、从char数组中提取第一个字符;
4、从提取的字符对象上行到numericValue属性(这个字符被表示为Character对象,Character类有一个getNumericValue()方法);
5、在Integer对象结果上调用toString()方法。
这个表达式最终结果是最后返回的toString()方法调用返回的字符串。
常量
OGNL支持的所有常量类型:
1、字符串常量:
以单引号或双引号括起来的字符串。如”hello”,’hello’。
不过要注意的是,如果是单个字符的字符串常量,必须使用双引号。
2、字符常量:
以单引号括起来的字符。如’a'。
3、数值常量:
除了Java中的int、long、float和double外,OGNL还让你使用“b”或“B”后缀指定BigDecimal常量,用“h”“H”后缀指定BigInteger常量。
4、布尔常量:
true和false。
5、null常量。
操作符
OGNL除了支持所有的Java操作符外,还支持以下几种:
1、逗号,
与C语言中的逗号操作符类似。
2、花括号{}
用于创建列表,元素之间用逗号分隔。
3、in和not in
用于判断一个值是否在集合中。
访问JavaBean的属性
假如有一个employee对象作为OGNL上下文的根对象,那对于下面的表达式:
1、name
对应的java代码是employee.getName();
2、address.country
对应的java代码是employee.getAddress().getCountry();
访问静态方法和静态字段
@class@method(args) //调用静态方法
@class@field //调用静态字段
其中class必须给出完整的类名(包括包名),如果省略class,那么默认使用的类是java.util.Math,如:
@@min(5,3)
@@max(5,3)
@@PI
索引访问
OGNL支持多种索引方式的访问。
1、数组和列表索引
在OGNL中,数组和列表可以大致看成是一样的。
如:array[0]、list[0]。表达式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
2、JavaBean的索引属性
要使用索引属性,需要提供两对setter和getter方法,一对用于数组,一对用于数组中的元素。
如:有一个索引属性interest,它的getter和setter如下
public String[] interest; public String[] getInterest(){ return interest;} public void setInterest(String[] interest){ this.interest=interest;} public String getInterest(int i){ return interest[i]} public void setInterest(int i, String newInterest){ interest[i]=newInterest;}
对于表达式interest[2],OGNL可以正确解释这个表达式,调用getInterest(2)方法。如果是设置的情况下,会调用setInterest(2,value)方法。
3、OGNL对象的索引属性
JavaBean的索引属性只能使用整型作为索引,OGNL扩展了索引属性的概念,可以使用任意的对象来作为索引。
对集合进行操作
1、创建集合:
创建列表
使用花括号将元素包含起来,元素之间使用逗号分隔。如{’zhangsan’,'lisi’,'wangwu’}
创建数组
OGNL中创建数组与Java语言中创建数组类似。
创建Map
Map使用特殊的语法来创建 #{”key”:value, ……}
如果想指定创建的Map类型,可以在左花括号前指定Map实现类的类名。如:
#@java.util.LinkedHashMap@{”key”:”value”,….}
Map通过key来访问,如map["key"]或map.key。
2、投影
OGNL提供了一种简单的方式在一个集合中对每一个元素闻调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称之为投影。
假如employees是一个包含了employee对象的列表,那么
#employees.{name}将返回所有雇员的名字的列表。
在投影期间,使用#this变量来引用迭代中的当前元素。
如:objects.{#this instanceof String? #this: #this.toString()}
3、选择
OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。
如#employees.{?#this.salary>3000}
将返回薪水大于3000的所有雇员的列表。
#employees.{^#this.salary>3000}
将返回第一个薪水大于3000的雇员的列表。
#employees.{$#this.salary>3000}
将返回最后一个薪水大于3000的雇员的列表。
lambda表达式
lambda表达式的语法是: :[...]。OGNL中的lambda表达式只能使用一个参数,这个参数通过#this引用。
如:
#fact= :[ #this<=1 ? 1 : #this* #fact ( #this-1) ], #fact(30) #fib= :[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)
OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。
为什么使用OGNL
相对于其它的表达式语言,OGNL的功能更为强大,它提供了很多高级而必需的特性,例如强大的类型转换功能、静态或实例方法的执行、跨集合投影,以及动态lambda表达式定义等。
OGNL基础
OGNL表达式的计算都是围绕OGNL上下文来进行的,OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类(实现了 java.util.Map接口)来表示。OGNL上下文可以包含一个或多个JavaBean对象,在这些对象中有一个是特殊的,这个对象就是上下文的根 (root)对象。如果在写表达式的时候,没有指定使用上下文中的哪一个对象,那么根对象将被假定为表达式所依据的对象。
在OGNL上下文中,只能有一个根对象,如果你访问根对象,那么在写表达式的时候,直接写对象的属性就可以了;否则,你需要使用“#key”前缀,例如表达式#namager.name。
OGNL表达式
OGNL表达式的基础单元就是导航链,通常简称为链(chain)。最简单的链由下列部分组成:
1、属性名:如name和manager.name;
2、方法调用:如manager.hashCode(),返回manager对象的散列码;
3、数组索引:如emals[0],返回当前对象的邮件列表中的第一个邮件地址。
所有OGNL表达式的计算都是在当前对象的上下文中,一个链简单地使用链中先前链接的结果作为下一步计算的当前对象。我们看如下所示的链:
name.toCharArray()[0].numericValue.toString()
这个表达式按照下列的步骤进行计算:
1、获取根对象的name属性;
2、在String结果上调用toCharArray()方法;
3、从char数组中提取第一个字符;
4、从提取的字符对象上行到numericValue属性(这个字符被表示为Character对象,Character类有一个getNumericValue()方法);
5、在Integer对象结果上调用toString()方法。
这个表达式最终结果是最后返回的toString()方法调用返回的字符串。
常量
OGNL支持的所有常量类型:
1、字符串常量:
以单引号或双引号括起来的字符串。如”hello”,’hello’。
不过要注意的是,如果是单个字符的字符串常量,必须使用双引号。
2、字符常量:
以单引号括起来的字符。如’a'。
3、数值常量:
除了Java中的int、long、float和double外,OGNL还让你使用“b”或“B”后缀指定BigDecimal常量,用“h”“H”后缀指定BigInteger常量。
4、布尔常量:
true和false。
5、null常量。
操作符
OGNL除了支持所有的Java操作符外,还支持以下几种:
1、逗号,
与C语言中的逗号操作符类似。
2、花括号{}
用于创建列表,元素之间用逗号分隔。
3、in和not in
用于判断一个值是否在集合中。
访问JavaBean的属性
假如有一个employee对象作为OGNL上下文的根对象,那对于下面的表达式:
1、name
对应的java代码是employee.getName();
2、address.country
对应的java代码是employee.getAddress().getCountry();
访问静态方法和静态字段
@class@method(args) //调用静态方法
@class@field //调用静态字段
其中class必须给出完整的类名(包括包名),如果省略class,那么默认使用的类是java.util.Math,如:
@@min(5,3)
@@max(5,3)
@@PI
索引访问
OGNL支持多种索引方式的访问。
1、数组和列表索引
在OGNL中,数组和列表可以大致看成是一样的。
如:array[0]、list[0]。表达式:{’zhangsan’,'lisi’,'wangwu’}[1]等。
2、JavaBean的索引属性
要使用索引属性,需要提供两对setter和getter方法,一对用于数组,一对用于数组中的元素。
如:有一个索引属性interest,它的getter和setter如下
public String[] interest; public String[] getInterest(){ return interest;} public void setInterest(String[] interest){ this.interest=interest;} public String getInterest(int i){ return interest[i]} public void setInterest(int i, String newInterest){ interest[i]=newInterest;}
对于表达式interest[2],OGNL可以正确解释这个表达式,调用getInterest(2)方法。如果是设置的情况下,会调用setInterest(2,value)方法。
3、OGNL对象的索引属性
JavaBean的索引属性只能使用整型作为索引,OGNL扩展了索引属性的概念,可以使用任意的对象来作为索引。
对集合进行操作
1、创建集合:
创建列表
使用花括号将元素包含起来,元素之间使用逗号分隔。如{’zhangsan’,'lisi’,'wangwu’}
创建数组
OGNL中创建数组与Java语言中创建数组类似。
创建Map
Map使用特殊的语法来创建 #{”key”:value, ……}
如果想指定创建的Map类型,可以在左花括号前指定Map实现类的类名。如:
#@java.util.LinkedHashMap@{”key”:”value”,….}
Map通过key来访问,如map["key"]或map.key。
2、投影
OGNL提供了一种简单的方式在一个集合中对每一个元素闻调用相同的方法,或者抽取相同的属性,并将结果保存为一个新的集合,称之为投影。
假如employees是一个包含了employee对象的列表,那么
#employees.{name}将返回所有雇员的名字的列表。
在投影期间,使用#this变量来引用迭代中的当前元素。
如:objects.{#this instanceof String? #this: #this.toString()}
3、选择
OGNL提供了一种简单的方式来使用表达式从集合中选择某些元素,并将结果保存到新的集合中,称为选择。
如#employees.{?#this.salary>3000}
将返回薪水大于3000的所有雇员的列表。
#employees.{^#this.salary>3000}
将返回第一个薪水大于3000的雇员的列表。
#employees.{$#this.salary>3000}
将返回最后一个薪水大于3000的雇员的列表。
lambda表达式
lambda表达式的语法是: :[...]。OGNL中的lambda表达式只能使用一个参数,这个参数通过#this引用。
如:
#fact= :[ #this<=1 ? 1 : #this* #fact ( #this-1) ], #fact(30) #fib= :[#this==0 ? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)
Struts2 字符串截取
<s:set name="hello" value="'Hello Miky as Miky'"></s:set> ----定义源字符串
<s:property value="#hello.substring(#hello.indexOf('as')+2)"/> ---输出字符串。结果为 Miky
posted @ 2009-05-05 22:55 MikyTan 阅读(108) | 评论 (0) | 编辑 收藏
JSP 中使用Struts2的值 (Strust2 中调用JAVA的公共类方法)
Struts2的值是保存在ValueStack中的,假设有一个字符串str,我们一般是这么取值的:
<s:property value="str"/> 或者 ${str}
如果想在jsp中使用的话,可以这么取:
<%@ page import="com.opensymphony.xwork2.util.ValueStack" %>
……
<%= ((ValueStack)request.getAttribute("struts.valueStack")).findString("str") %>
也可以把ValueStack中的值先放到attribute中,然后直接取attribute的值:
<s:set name="str" value="%{str}" />
<%=request.getAttribute("str") %>
struts2的页面中调用函数
方法一:
<s:set name="str" value="'Hello World'"></s:set> <s:property value="%{@com.common.Constant@func(#str)}"/>
func是类com.common.Constant里面的一个静态方法
str是动态的参数
方法二:
<s:bean name="com.common.StrutsHelper" id="helper" /> <s:set name="str" value="'Hello World'"></s:set> <s:property value="#helper.func(#str)" />
func是类com.common.StrutsHelper里面的一个普通方法
str是动态方法
s:bean其实是对类StrutsHelper的实例化,跟方法一有些区别,方法一里的函数必须是静态的
产品时间段(StartDate,EndDate)SQL查询
表 a 字段,id,开始时间,结束时间,价格
1,2008-01-01,2008-09-10,220.0
2,2008-09-11,2008-09-30,280.0
3,2008-10-01,2008-10-10,320.0
3,2008-10-11,2008-12-31,350.0
输入一个开始时间,一个结束时间,返回这段时间内每天的价格,最好返回每天的日期和对应的价格
例输入开始时间2008-09-09,结束时间2008-09-13
返回
2008-09-09,220
2008-09-10,220
2008-09-11,280
2008-09-12,280
2008-09-13,280
方案一:采用存储过程的方案!
create table T([id] int,[开始时间] datetime,[结束时间] datetime,[价格] numeric(4,1)) insert into T select 1,'2008-01-01','2008-09-10',220.0 union all select 2,'2008-09-11','2008-09-30',280.0 union all select 3,'2008-10-01','2008-10-10',320.0 union all select 3,'2008-10-13','2008-12-31',350.0 select * from T go --Code create procedure GetTimePrice(@begintime datetime,@endtime datetime) as declare @tmptime datetime declare @tmp table (dt datetime,price numeric(4,1))--结果表 begin set @tmptime=@begintime while @tmptime<=@endtime begin insert into @tmp select @tmptime,价格 from t where @tmptime between 开始时间 and 结束时间 set @tmptime=DATEADD(dd,1,@tmptime) end select * from @tmp end go exec GetTimePrice '2008-09-09','2008-09-14'--执行 --Drop drop table T drop procedure GetTimePrice
方案二:采用Case方案
set nocount on create table T([id] int,[开始时间] datetime,[结束时间] datetime,[价格] numeric(4,1)) insert into T select 1,'2008-01-01','2008-09-10',220.0 union all select 2,'2008-09-11','2008-09-30',280.0 union all select 3,'2008-10-01','2008-10-10',320.0 union all select 3,'2008-10-11','2008-12-31',350.0 declare @bgnTime datetime set @bgnTime = '2008-09-09' declare @endTime datetime set @endTime = '2008-09-13' select id ,case when [开始时间]<@bgnTime then @bgnTime else [开始时间] end as [开始时间] -- 让输出结果更贴近参数表现出来 ,case when [结束时间]>@endTime then @endTime else [结束时间] end as [结束时间] -- 让输出结果更贴近参数表现出来 ,[价格] from T where [开始时间]<@endTime and [结束时间]>@bgnTime -- id,开始时间,结束时间 -- 1,2008-09-09 00:00:00.000,2008-09-10 00:00:00.000 -- 2,2008-09-11 00:00:00.000,2008-09-13 00:00:00.000 drop table T
id 开始时间 结束时间 价格
----------- ------------------------------------------------------ ------------------------------------------------------ ------
1 2008-09-09 00:00:00.000 2008-09-10 00:00:00.000 220.0
2 2008-09-11 00:00:00.000 2008-09-13 00:00:00.000 280.0
posted @ 2009-04-23 20:50 MikyTan 阅读(150) | 评论 (0) | 编辑 收藏
jQuery实现input文本框内灰色提示文本效果 和 input标签获取焦点是文本框内提示信息清空
摘要: 一、jQuery实现input文本框内灰色提示文本效果 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <titl... 阅读全文
posted @ 2009-04-23 11:50 MikyTan 阅读(2949) | 评论 (0) | 编辑 收藏
酒店价格间夜显示(JavaScript 实现)
摘要: 酒店间夜价格显示实现: 跨周: <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC&... 阅读全文
posted @ 2009-04-21 13:31 MikyTan 阅读(64) | 评论 (0) | 编辑 收藏
JavaScript 取Table表格中的值
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE> New Document </TITLE> <META NAME="Generator" CONTENT="EditPlus"> <META NAME="Author" CONTENT=""> <META NAME="Keywords" CONTENT=""> <META NAME="Description" CONTENT=""> </HEAD> <BODY onload="getTableValue()"> <script language="javascript"> function getTableValue(){ alert(document.getElementById('table1').rows[0].cells[0].innerHTML); //or alert(document.getElementById('table1').rows.item(0).cells.item(0).innerHTML); } </script> <table id="table1"> <tr> <td>1</td> <td>2</td> </tr> <tr> <td>3</td> <td>2</td> </tr> </table> </BODY> </HTML>
注意,为了兼容IE跟FireFix,不要用 innerText
xmlbeans dom level 3 not implemented
今天在用XmlBeans解析XML DOC时,遇到“xmlbeans dom level 3 not implemented”的解决办法!
问题产生的原因:
1、由于在生成的XML结构中插入了一些未在XSD中定义的节点,那么这些节点无法用XMLBeans所采用的对象的方法获取,只能采用DOM的方式来处理,但在处理的过程中报
“xmlbeans dom level 3 not implemented” //实例化一个文档构建器工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); //通过文档构建器工厂获取一个文档构建器 DocumentBuilder builder = factory.newDocumentBuilder(); //通过文档通过文档构建器构建一个文档实例 AssertionDocument assertionDoc = AssertionDocument.Factory.parse(new File(”xml/assertion.xml”), loadOptions); Document doc = builder.parse(new InputSource(new StringReader(assertionDoc.toString()))); doc.getDocumentElement().setIdAttribute(”AssertionID”, true);
COPY 非原创
相关推荐
除了Java基础之外,还有一小部分web方面的知识,如:JSP、EL表达式、JSTL、过滤器与监听器之类的知识,但是只有一小部分
5. **学习杂记**:学习加密算法不仅需要理解算法原理,还要熟悉Java提供的加密API。实践是提升技能的关键,通过编写示例代码,理解如何创建密钥、初始化Cipher对象、处理加密和解密过程。同时,了解加密过程中的常见...
- **jre**:Java 运行时环境,包含了运行 Java 程序所需的库和虚拟机。 - **src.zip**:源代码归档文件,通常包含了一个项目的全部源代码。 以上是对给定文件中提到的基础知识点的详细解释,涵盖了计算机编程领域的...
然而,Eclipse需要Java运行环境支持,因此你需要先安装JRE(Java Runtime Environment)和JDK(Java Development Kit)。JRE提供运行Java程序所需的环境,JDK则包含开发工具。下载并安装jre-6u23-windows-i586.exe和...
本篇将深入探讨Java多线程的相关知识,结合《java随笔杂记.doc》文档中的内容,我们将覆盖以下几个方面: 1. **线程的创建方式** - 实现`Runnable`接口:创建一个实现了`Runnable`接口的类,然后将其实例传递给`...
在Java并发编程中,AbstractQueuedSynchronizer(AQS)是一个重要的抽象类,它是实现锁和其他同步组件的基础。AQS通过一个int类型的state变量来管理锁的状态,这个状态可以是独占模式(exclusive mode)或共享模式...
在本篇《SpringMVC杂记(五) JSR303数据验证》中,我们将深入探讨SpringMVC框架如何集成并使用JSR303(JavaBeans Validation)来进行数据验证,这是一种强大的验证机制,可以确保应用程序接收到的数据是合法且符合...
首先,Listener(监听器)是Java Servlet规范中的一部分,主要用于监听特定事件并执行相应操作。常见的Listener包括HttpSessionListener、ServletContextListener和ServletRequestListener等。例如,...
3. **Java编译**:Java Compiler将R文件、Java源代码、aidl转换的Java接口统一编译为.class文件。 4. **DEX生成**:通过dx工具将.class文件转换为Dalvik可执行的.dex文件。 5. **资源打包**:将处理后的资源文件、...
### STS、Maven与Nexus操作指南及配置详解 ...综上所述,通过详尽配置STS、Maven以及Nexus,可以建立一个高效的Java项目开发与构建环境,不仅提升了代码管理效率,还优化了依赖组件的下载和更新流程。
【Linux基础命令杂记】 在Linux环境中,掌握基础命令对于日常运维和开发工作至关重要。这里列举了一些常用的Linux命令,以及如何在Linux系统中与MySQL数据库交互。 1. **登录远程MySQL**: 使用命令 `mysql -h ...
```java @SessionAttributes("stepData") public class WizardController { // ... } ``` 这样,名为"stepData"的模型属性将在用户在向导的不同步骤之间导航时保持其值。 2. 多步骤流程管理: 在每个步骤中...
"Miscellany: Raizunne 杂记的 Minecraft mod 存储库"是一个专注于1.7.10版本的Minecraft模组集合,为游戏带来了一系列丰富多样的新元素和功能,让玩家在游戏中享受到更多元化的乐趣。 首先,我们要明确,...
程序员考试刷题讲座问题/杂记 使用hackerrank、codecademy、codesignal解决练习题 修改数组,比较 公共和静态是默认的? (是在讲座中) 所以局部变量没有默认值,但实例(类)变量有 使用随机 第 9 课的幻灯片 44 ...
zxing.java源码解析 个人技术博客 前言 开卷有益。 写在最前,长期以来,技术学习并没有养成分享的习惯。没有好好成体系的整理自己所学的知识,时间长了也容易遗忘。 仓库名起名PlayPen,这个名字源于我上一家公司一...
Java 数据库 Linux 杂记 :bullseye: :hot_beverage: :floppy_disk: :cloud: :memo: :black_nib:本仓库有来源自己总结,网上收集,视频笔记,如果有区别之处,可以联系我进行删除。 :scroll:笔记仓库: ...
#### 六、杂记 - **Namenode和Secondarynamenode的关系**: Namenode是HDFS的核心组成部分,负责管理文件系统的命名空间及客户端对文件的访问。而Secondarynamenode的主要职责是辅助Namenode,它定期合并fsimage文件...
jbpm,全称为Java Business Process Management,是一款开源的工作流管理系统,用于实现业务流程自动化。它在企业级应用中广泛使用,特别是在需要管理复杂工作流程的系统中。通过对jbpm的学习,我们可以深入理解业务...
通过阅读这个系列,你可以深入了解面向底层的C语言,以及面向业务的面向对象编程语言,比如JAVA和C++,同时还能接触到游戏开发的实例。 C语言是计算机科学中的基石,它让你能够直接与硬件交互,理解内存管理、指针...