分类 Java Web 下的文章

粗浅了解了一下Velocity模板引擎的原理

今天阅读了一篇文章,关于Velocity模板引擎原理的,很有收获,所以简单的概括一下。

其实,一直在思考Velocity这种模板引擎和JSP的区别,今天才恍然大悟。
其实Velocity可以称得上是半个语言了,所有的Velocity模板都会被分解成语法抽象树(AST)。如果对语法抽象树没有概念的话,可以了解一下《自制编程语言》一书(其实我也没有看过这本书)。
但是如何将Java的Context和Velocity最后分解出的语法抽象树匹配起来,这个才是问题所在。

这边可以对照一下JSP,JSP作为纯正的Java,自然不用担心变量的匹配的问题,所有通过Request的Attributes转发到JSP的对象都可以恢复原来格式的对象来调用。
但是Velocity中分解出的语法抽象树却需要通过反射等功能来获取Java变量的值,替换语法抽象树中的节点。

Servelt如何判断用户首次访问站点是否需要进行URL重写?

看到《Head First Servlet&JSP》的URL重写的时候,对这边就有疑问了。

Servlet如何判断客户端不支持Cookie而进行URL重写呢?毕竟用户的第一次访问站点都是不可能带Cookie的,那么如何判断这个是用户首次访问站点还是因为用户的浏览器不支持Cookie?

然后,找到了一篇文章:http://dk05408.iteye.com/blog/2103257,发现这个问题Servlet处理的太简单了。简单的来说,就是不处理,所有的用户第一次访问站点的情况都当成不支持Cookie处理,进行URL重写。等到下次访问的时候,就能正确判断支持不支持Cookie了。

这样的话,那么Servlet就会对每一个不支持Cookie的请求都会尝试设置Cookie,这也是一种没办法的办法。

servlet项目如何添加和使用第三方jar

在Java Web中,我们用到第三方类库的机会很多,那么当我们手动管理依赖的时候,我们该如何添加和使用第三方jar文件。

在此,我们用于举例的第三方jar是普及程度极高的slf4j。

1、前往slf4j官网下载slf4j的zip压缩包,这边下载的是slf4j-1.7.21.zip。解压缩文件夹,待用。

2、在已有的servlet代码里面加上以下几句:
import org.slf4j.LoggerFactory;

`LoggerFactory.getLogger({className}.class).info("Hello World");
注:{className}需要替换成你的servlet类的名称

3、编译servlet文件,需要在-classpath参数里面加上slf4j-api.1.7.21.jar。
比如原来的-classpath参数是"/path/to/servlet-api.jar",现在需要改成"/path/to/servlet-api.jar:/path/to/slf4j-api.1.7.21.jar"。
注:/path/to/需要替换成具体的路径

4、tomcat之类的容器不会像java这个命令一样可以方便的加上-classpath参数,所以有个专门用来放jar文件的路径:WEB-INF/lib/。当tomcat启动的时候,类似于java命令自动添加了-classpath参数。
你需要复制slf4j-api-1.7.21.jar和slf4j-simple-1.7.21.jar两个jar文件到该路径。

5、添加了jar文件之后,不要忘记重启tomcat,此时添加了第三方的servlet就可以正常运行了。

Java 5.0的静态导入

一直不知道Java 5.0以后提供了一种叫做静态导入(static import)的功能,可以能够导入静态方法。

但是关于这种功能有不小的争议,我们来看:

这是Java 5.0的新功能:一把双刃剑。有些人很喜欢这个主意,有些人恨死它了。如果你讨厌多打几个字,那你回喜欢这项功能。但是它的缺点是会让程序比较难阅读。

基本上,这个功能是让你import静态的类、变量或enum时能够少打几个字。

旧式的写法:

import java.lang.Math;
class NoStatic {
    public static void main(String[] args) {
        System.out.println("sqrt"  + Math.sqrt(2.0));
        System.out.println("tan" + Math.tan(60));
    }
}

这里可以看到虽然我们用到了import,但是import只能导入到类。所以静态方法和变量我们不得不重复输入多次。

使用static import的写法:

import static java.lang.System.out;
import static java.lang.Math.*;
class WithStatic {
    public static void main(String[] args) {
        out.println("sqrt" + sqrt(2.0));
        out.println("tan" + tan(60));
    }
}

这里可以看到我们用了static import,就可以导入静态的类方法、变量或enum。

[转]Java中子类继承父类时是否继承构造函数

Java继承中队构造函数是不继承的,只是调用(隐式或显式)。
以下是例子

public class FatherClass {

    public FatherClass() {
        System.out.println(100);
    }

    public FatherClass(int age) {
        System.out.println(age);
    }
}

public class SonClass extends FatherClass {
    public SonClass() {
        
    }
    
    public SonClass(int c) {
        System.out.println(1234);
    }

    public static void main(String[] args) {
        SonClass s = new SonClass(66);
    }
}

编译后执行结果是什么呢?

分析SonClass s= new SonClass(66);执行这句时的调用。

public SonClass(int c) {
    System.out.println(1234);//系统会先调用父类的无参数构造函数super()
}

在这个构造函数中,等价于:

public SonClass(int c) {
    super();
    system.out.println(1234);
}

所以结果是
100
1234

在创建子类的对象时,Java虚拟机首先执行父类的构造方法,然后在执行子类的构造方法。在多级继承的情况下,将从继承树的最上层的父类开始,依次执行各个类的构造方法,这可以保证子类对象从所有直接或间接父类中继承的实例变量都被正确地初始化。

如果子类构造是这样写的:

public SonClass(int c) {
    super(22);//必须是第一行,否则不能编译//显式调用了super后,系统就不再调用无参的super()了。
    System.out.println(1234);
}

执行结果是
22
1234


总结一:构造函数不能继承,只能调用而已。

如果父类没有无参构造函数,创建子类时,不能编译,除非在构造函数代码体中的第一行,必须是第一行显式调用父类有参构造函数,如下:

public SonClass() {
    super(777);//显示调用父类有参构造函数
    System.out.println(66);
}

如果不显式调用父类有参构造函数,系统会默认调用父类无参构造函数super();
但是父类中没有无参构造函数,所以它不就是不能调用了。所以编译就通不过了。

总结二:创建有参构造函数后,系统就不再有默认无参构造函数。

如果没有任何构造函数,系统会默认有一个无参构造函数。