Fork me on GitHub

Object Graph Navigation Language

Object Graph Navigation Language

概念

对象导航图语言(Object Graph Navigation Language),简称OGNL,是应用于Java中的一个开源表达式语言(Expression Language),它被集成在Struts2等框架中,作用是对数据进行访问,它拥有类型转换、访问对象方法、操作集合对象等功能。

应用

参考

Ognl 表达式的基本使用方法:one:

Expression Language

Expression Language

Literal Expressions

A literal expression is evaluated to the text of the expression, which is of type String. A literal expression does not use the ${} or #{} delimiters.

If you have a literal expression that includes the reserved ${} or #{} syntax, you need to escape these characters as follows:

  • By creating a composite expression as shown here:

    1
    ${'${'}exprA}
    1
    #{'#{'}exprB}

    The resulting values would then be the strings ${exprA} and #{exprB}.

  • By using the escape characters \$ and \# to escape what would otherwise be treated as an eval-expression:

    1
    \${exprA}
    1
    \#{exprB}

    The resulting values would again be the strings ${exprA} and #{exprB}.

When a literal expression is evaluated, it can be converted to another type. Table 6-2 shows examples of various literal expressions and their expected types and resulting values.

Table 6-2 Literal Expressions

Expression Expected Type Result
Hi String Hi
true Boolean Boolean.TRUE
42 int 42

Literal expressions can be evaluated immediately or deferred and can be either value or method expressions. At what point a literal expression is evaluated depends on where it is being used. If the tag attribute that uses the literal expression is defined to accept a deferred value expression, when referencing a value, the literal expression is evaluated at a point in the lifecycle that is determined by other factors, such as where the expression is being used and to what it is referring.

In the case of a method expression, the method that is referenced is invoked and returns the specified String literal. For example, the h:commandButton tag of the guessnumber application uses a literal method expression as a logical outcome to tell the JavaServer Faces navigation system which page to display next.

Operators

In addition to the . and [] operators discussed in Value and Method Expressions, the EL provides the following operators, which can be used in rvalue expressions only:

  • Arithmetic: +, - (binary), *, / and div, % and mod, - (unary)
  • Logical: and, &&, or, ||, not, !
  • Relational: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le. Comparisons can be made against other values or against Boolean, string, integer, or floating-point literals.
  • Empty: The empty operator is a prefix operation that can be used to determine whether a value is null or empty.
  • Conditional: A ? B : C. Evaluate B or C, depending on the result of the evaluation of A.

The precedence of operators highest to lowest, left to right is as follows:

  • [] .
  • () (used to change the precedence of operators)
  • - (unary) not ! empty
  • * / div % mod
  • + - (binary)
  • < > <= >= lt gt le ge
  • == != eq ne
  • && and
  • || or
  • ? :

Examples of EL Expressions

Table 6-3 contains example EL expressions and the result of evaluating them.

Table 6-3 Example Expressions

EL Expression Result
${1 > (4/2)} false
${4.0 >= 3} true
${100.0 == 100} true
${(10*10) ne 100} false
${'a' < 'b'} true
${'hip' gt 'hit'} false
${4 > 3} true
${1.2E4 + 1.4} 12001.4
${3 div 4} 0.75
${10 mod 4} 2
${!empty param.Add} False if the request parameter named Add is null or an empty string.
${pageContext.request.contextPath} The context path.
${sessionScope.cart.numberOfItems} The value of the numberOfItems property of the session-scoped attribute named cart.
${param['mycom.productId']} The value of the request parameter named mycom.productId.
${header["host"]} The host.
${departments[deptName]} The value of the entry named deptName in the departments map.
${requestScope['javax.servlet.forward.servlet_path']} The value of the request-scoped attribute named javax.servlet.forward.servlet_path.
#{customer.lName} Gets the value of the property lName from the customer bean during an initial request. Sets the value of lName during a postback.
#{customer.calcTotal} The return value of the method calcTotal of the customer bean.

参考

The Java EE 6 Tutorial Expression Language

JSR 341: Expression Language 3.0

nginx 基本使用

nginx

配置

Nginx 实现 HTTP 自动跳转到 HTTPS 页面

建议在 Nginx 虚拟主机配置文件对应的网站配置段中增加跳转项 if...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server
{
listen 80;
server_name www.websoft9.com;
index readme.html index.html index.htm;
root /data/nas/www.websoft9.com;
error_log /var/log/nginx/www.websoft9.com-error.log crit;
access_log /var/log/nginx/www.websoft9.com-access.log;
include conf.d/extra/*.conf;

# HTTP to HTTPS
if ($scheme = http) {
return 301 https://$host$request_uri;
}

listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/www.websoft9.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.websoft9.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

参考

Nginx从安装到高可用,一篇搞定!

免费证书

nginx实践

要不要上培训班

转载文章

目前,由于大量青年学子有志于进入IT行业,但苦于缺乏系统的指导,因此形成了一个巨大的IT培训市场。各培训机构瞅准了这个市场机遇,大量招募相关学子,形成了培训市场异常火爆的局面。仅我校周围,就有多家培训机构或盘踞于此,或打有巨幅广告。若眼界再放远一点,培训机构更是遍地开花,从JAVA到网络不一而论。由于情况各异,笔者不可能一一分析到位,在此仅针对本科层次的青年学子要不要上JAVA培训班这个问题做一探讨,以期对读者有所借鉴。

开门见山地说,笔者对参加JAVA培训班一事是明确反对的。理由如下:

一、培训费用高昂。
  
纵观各培训机构的培训费用,往往动辄几千,甚至上万。这对于我们大部分青年学子的家庭来说,无疑是个沉重的负担。比如,笔者比较熟悉的我校学生,多来自普通家庭,负担之大自不必说。

 二、某些培训机构爆出诚信丑闻。
  
近来爆出的培训机构作假的丑闻(读者可在网上搜索,笔者也听说过某培训机构帮助其学员做假的案例),使某些公司对培训机构出来的学生有了一定的偏见。这样,上培训班反而有可能降低顺利就业的几率。而且,某些培训机构的欺诈行为,也损害了相关学子的合法利益。

三、培训机构很难培养学员的技术核心竞争力。
  
培训机构能让你短期掌握到相关具体的技术,但很难提高学员的技术核心竞争力,这一点最关键。什么是你的技术核心竞争力?IT行业技术更新快,新技术层出不穷,更要命的是相关技术体系纷繁庞杂,涉及的知识面极广。因此,许多投身于JAVA编程的人都感到要学习的知识太多了,总也学不完。在这种情况下,你的技术核心竞争力就是指你扎实的基础,以及在此基础上快速学习各种新技术的能力,独自发现问题、探索解决问题之道的主动性和能力。

实践证明,只有具备了这种能力,才能够以不变应新技术的万变,这也是企业对员工技术能力的最佳期盼。而培养这种能力,就需要以大量的自学经历为基础。上培训班的话,虽然能使你快速入门,但是却剥夺了你独自探索的机会,不利于这种最核心、最有价值的能力的培养。

因此,对有志于从事JAVA开发的青年学子而言,笔者建议如下:

 一、学好数学和英语。
  
在基础年级(大一、大二)要把数学和英语的底子打牢。不要小看数学,觉得它没有用,它能培养你的抽象思维能力,提高思维的严密性,这种能力是程序设计最为重要的能力。计算机说到底就是数学,只是目前我们还暂时没有认识到这一点,但不代表它不是。学好英语将使你能够顺利阅读原版技术资料,一般最新、最权威、最全面的技术资料都是用英语书写的。另外若想进外企的话,英语的重要性自不必说。前段时间CSDN做过调查,英语水平的高低与程序员的收入水平是成正比的。

二、重视基础。
  
一般现在理科本科生的入门语言是C语言。建议大家在学习的时候一定要认真学习,亲自动手编程,不要老是怀疑有没有用,这是浮躁的表现。C语言是迄今为止最经典的语言,它能够培养你程序设计的基本功。C语言学不好,后面再学习JAVA,就会徒增很多难度。而且,目前C语言在嵌入式开发和系统开发方面仍然占用重要地位,你说有用吗?重视基础的另外一个方面就是不要急于学习流行技术,而要先把如Servlet相关知识学好,这样才能灵活自如地学习后面的知识。重视基础的第三个方面是要做到知其然,并知其所以然。这样才能对知识理解深刻,灵活应用,见到新技术的时候也能迅速掌握。其实,很多新技术看似时髦,但深究起来本质上变化不大。只要基础扎实,就能迅速学会,没啥了不起的。

三、一定要亲自动手编程。
  
这一点是毋庸置疑的,就像不下水游泳永远都学不会游泳一样,不亲自动手编程,也永远学不会编程。在亲自动手编程的过程中,既是对新知识的学习,也是对旧知识的巩固。要学会从编程中找到乐趣——当你千辛万苦实现了一个功能的时候,是不是很happy呢?这样就不会再把学习当成一种痛苦,而是一种快乐,形成良性循环。在程序出错的时候,在你悉心的调试过程中,你对知识理解的深刻度,知识掌握的熟练度,你独立发现问题、解决问题的能力就在无形中增长。也就是说,培养了你的技术核心竞争力。

四、与好友结伴学习。
  
这样可以互相鼓励,互相学习,避免有些问题迟迟得不到解决而打击了自信心,也可有效避免自己的惰性。

五、学会参考已有资源。
  
可从网上下载一些优秀的视频看,这样就相当于免费上了一些培训班。找本权威的书还是必要的,可以帮助你从宏观上把握知识的体系结构。现在网上虽有很多有用的信息,但致命的弱点是过于碎片化,不利于系统的学习,参考起来也很困难。

  六、善于猜想。
  
很多科学发现就来源于猜想,学习JAVA也是一样。有时遇到一些不明白的问题,就可以发挥自己的想象力,猜想:是不是这样啊?然后通过写代码、查资料验证。经验告诉笔者,这样还经常能猜对!这样你是不是很高兴呢?学习兴趣是不是更浓厚了呢?由于是自己猜想出来的,自然记忆深刻。而且,猜想既是科学研究的一种手段,也是探索程序设计(不限于JAVA),甚至探索任何领域知识的一个强大武器。这就是你独立解决问题的能力——上面提到的技术核心竞争力之一!

七、可上些入门级的培训课程。
  
若实在觉得自学有困难,可上些入门级的培训课程。万事开头难嘛!刚开始学习的时候由于不知道的太多,感觉无从下手,这也很正常。这时可花较少的钱上点入门级课程。一旦入门,就自己单干,这时难度就小多了。

说了这么多,真心希望能对广大有志于IT行业的青年学子有所帮助。但具体怎么走,还是你自己拿决定吧!

祝同学们一步一个脚印,IT之路前程似锦!

(后记:本博文自从发表后就受到很多热情读者的关注,这令笔者十分意外、欣喜,在此向读者朋友的认可表示深深的感谢。在写博文时,考虑到不是每个搞IT的都一定是计算机专业毕业的,实际上也没有必要一定得是,因此在“重视基础”这一块里就没有强调计算机专业基础课程的重要性。但现在感觉不妥,特添加此后记。实际上,笔者认为:最重要的基础是数学,第二重要的基础就是计算机专业的基础课程,如C语言、数据结构、算法、计算机组成和操作系统等等。这些基础将决定着你的技术能达到的高度。对于计算机专业的同学来讲,你们应该庆幸自己大学期间就是专门学习这些课程的;当然非计算机专业的同学也没有必要气馁。只要你的大学是认真读下来的,你的学习能力就一定很强,在工作中再学习这些知识也不是什么难事儿。我一贯都认为,大学最重要的学习是学习能力的培养,而不是专业知识的学习。祝大家IT之路前程似锦!) 

©著作权归作者所有:来自51CTO博客作者NashMaster2011的原创作品,请联系作者获取转载授权,否则将追究法律责任
关于该不该上JAVA培训班的一点看法
https://blog.51cto.com/legend2011/690362

idea 使用技巧

IDEA

概念

配置

常用插件

问题

  • idea 编译项目时,报内存溢出,系统资源不足

原因:idea设置编译器内存默认为700MB,需求超过这个范围则会抛出以上错误。

解决:

参考

mybatis 源码

Mybatis

概念

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

整体架构

基础支持层

  • 反射模块:提供封装的反射 API,方便上层调用。
  • 类型转换:为简化配置文件提供了别名机制,并且实现了 Java 类型和 JDBC 类型的互转。
  • 日志模块:能够集成多种第三方日志框架。
  • 资源加载模块:对类加载器进行封装,提供加载类文件和其它资源文件的功能。
  • 数据源模块:提供数据源实现并能够集成第三方数据源模块。
  • 事务管理:可以和 Spring 集成开发,对事务进行管理。
  • 缓存模块:提供一级缓存和二级缓存,将部分请求拦截在缓存层。
  • Binding 模块:在调用 SqlSession 相应方法执行数据库操作时,需要指定映射文件中的 SQL 节点,MyBatis 通过 Binding 模块将自定义 Mapper 接口与映射文件关联,避免拼写等错误导致在运行时才发现相应异常。

核心处理层

  • 配置解析:MyBatis 初始化时会加载配置文件、映射文件和 Mapper 接口的注解信息,解析后会以对象的形式保存到 Configuration 对象中。
  • SQL 解析与 scripting 模块:MyBatis 支持通过配置实现动态 SQL,即根据不同入参生成 SQL
  • SQL 执行与结果解析:Executor 负责维护缓存和事务管理,并将数据库相关操作委托给 StatementHandlerParmeterHadler 负责完成 SQL 语句的实参绑定并通过 Statement 对象执行 SQL,通过 ResultSet 返回结果,交由 ResultSetHandler 处理。
  • 插件:支持开发者通过插件接口对 MyBatis 进行扩展。

接口层

SqlSession 接口定义了暴露给应用程序调用的 API,接口层在收到请求时会调用核心处理层的相应模块完成具体的数据库操作。

技巧

Mybatis include入参实现sql可复用

1
2
3
4
5
6
7
8
9
10
11
12
13
<select id="selectById" resultMap="BaseResultMap">
select
my.*
FROM
sys_user my
<include refid="test_where"/>
</select>

<sql id="test_where">
WHERE
my.id = 1
</sql>
-- 执行结果:select my.* FROM sys_user my WHERE my.id = 1

通过property标签动态传参,使用时用 ${PROPERTY_NAME}.

在 if 等标签和代码段中都可使用.

注意:
mybatis中有两种传入动态参数的方式:#{}和${}
#{} 占位符:对传入的参数会做预编译,也就是会当做字符串来处理

${} 拼接符:对传入的参数不会做任何的处理,也就是说传递什么就是什么
举例:

  1. select * from sys_user where id = #{id} and name = #{name}
    最后执行的sql:select * from sys_user where id = ‘1’ and name = ‘zhangsan’
  2. select * from sys_user where id = ${id} and name = ${name}
    最后执行的sql:select * from sys_user where id = 1 and name = zhangsan (这里zhangsan没有单引号,因此会报错。如果需要加单引号,则需要手动在传参时传入。)

ognl表达式测试

OGNL 是 Object-Graph Navigation Language 的缩写,对象-图行导航语言,语法为:#{ }。

OGNL 作用是在对象和视图之间做数据的交互,可以存取对象的属性和调用对象的方法,通过表达式可以迭代出整个对象的结构图。

MyBatis常用OGNL表达式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

// 构建一个OgnlContext对象
OgnlContext context = (OgnlContext) Ognl.createDefaultContext(this,
new DefaultClassResolver(),
new DefaultTypeConverter(),
new DefaultMemberAccess(true));

Map<String,Object> hashMap=new HashMap<>(1);
hashMap.put("name", "aa");
context.setRoot(hashMap);
String expression="name =='aa'";
try {
Boolean flag = (Boolean) Ognl.getValue(expression, context, context.getRoot());
System.out.println(flag);
} catch (OgnlException e) {
e.printStackTrace();
}

参考

官档

github

博客1

mybatis教程

poi基本使用

POI

基本使用

设置列宽

列实际显示字符个数

setColumnWidth(int columnIndex, int width)设置的宽度包括4像素的边距填充(每侧两个),加上网格线的1像素填充。

如果字符宽度为w像素, w单位为一个字符宽度的1/256,设置列宽字符个数为count,则实际可见字符数X:
X * (w * 256) + 5 = count * (w * 256)
转换公式:
X = count - 5/w
可见实际可见字符数比设置字符数略小。

将某个excel中的某一列列宽设置为35(该数值是Excel中显示的列宽值)

1
sheet.setColumnWidth(0,35 * 256 + 184);

根据行号获取字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static String getColumnName(int columnNum) {

int first;

int last;

String result = "";

if (columnNum > 256)

columnNum = 256;

first = columnNum / 27;

last = columnNum - (first * 26);

if (first > 0)

result = String.valueOf((char) (first + 64));

if (last > 0)

result = result + String.valueOf((char) (last + 64));

return result;

}

存储过程

存储过程

概念

存储过程Procedure是一组为了完成特定功能的SQL语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。

存储过程中可以包含逻辑控制语句和数据操纵语句,它可以接受参数、输出参数、返回单个或多个结果集以及返回值。

与function 区别

SELECT get_foo(myColumn) FROM mytable is not valid if get_foo() is a procedure, but you can do that if get_foo() is a function. The price is that functions have more limitations than a procedure。

创建

1
2
3
4
5
6
CREATE [OR REPLACE] PROCEDURE procedure_name 
[(parameter_name [IN | OUT | IN OUT] type [, ...])]
{IS | AS}
BEGIN
< procedure_body >
END procedure_name;

create_procedure ::=

Description of the illustration create_procedure.gif

See:

invoker_rights_clause ::=

Description of the illustration invoker_rights_clause.gif

示例

区块,条件,循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- --区块
begin
```
end;

-- -- 条件
if condition then
statement
else
statement
end if;

-- -- 循环
while condition DO
statement
end while;

调用

调用存储过程:call 存储过程名()。

删除

DROP PROCEDURE [if exists] 存储过程名;

其他

Comparator接口解读

Comparator 接口源码解读

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
In the foregoing description, the notation sgn(expression) designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.
The implementor must ensure that sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y. (This implies that compare(x, y) must throw an exception if and only if compare(y, x) throws an exception.)
The implementor must also ensure that the relation is transitive: ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
Finally, the implementor must ensure that compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z.
It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is “Note: this comparator imposes orderings that are inconsistent with equals.”

格物致知

格物致知

  • 灯芯

毛细现象

毛细现象(又称毛细管作用)是指液体在细管状物体或多孔物体内部,由“液体与物体间附着力”和“因液体分子间内聚力而产生的表面张力”组合而成,令液体在不需施加外力的情况下,流向细管状物体或细缝的现象;该现象可以令液体克服地心引力而上升。此属于一种液体界面现象。

常见的是液体和固体之间的附着力大于液体本身内聚力的情况,如:布料、毛笔、多孔物体吸水、蜡油沿着棉线上升。而毛细管本身则是内径等于或小于1毫米的细管,主要用于医事检验及建筑材料上,一般非专业人员反而较少见。(注:植物根部吸收的水分能够经由茎内维管束上升,除了利用毛细现象外,最主要的原因是蒸散作用)。

  • 水缸-管子-送水

虹吸(siphon或syphon)是一种流体力学现象,可以不借助泵而抽吸液体。处于较高位置的液体充满一根倒U形的管状结构(称为虹吸管)之后,开口于更低的位置。虹吸管两端液体的重量差距造成液体压力差距,液体压力差能够推动液体越过最高点,向低端排放。

中国九龙杯原理

  • 撒盐除雪的原理

    撒盐除雪是利用了盐的可溶性、吸潮性和盐水的低冰点等特点,当盐撒在雪上的时候,由于盐的可溶性和吸潮性,使得盐会吸收雪表面的水分,从而使盐开始溶化,成为溶液侵蚀雪层。当盐与雪一同溶化成盐水后,由于盐水的凝固温度比水低,因此盐水很难结冰形成冰层,这就是撒盐除雪的原理。

物理

涡流管

  • © 2015-2024 DXShelley
  • Powered by Hexo Theme Ayer

请我喝杯咖啡吧~~~

支付宝
微信