代码的可维护性是评价项目的非常重要的指标之一!其中,代码的编码规范就是最基础的表现!
首先,命名必须规范:
包(package)名必须全部使用小写字母,例如cn.huang.spring.Controller
这样的包名就是不对的,其中的Controller
子包的首字母不应该大写!
所有的类、接口的首字母必须大写,如果名称由多个单词组成,第2个单词开始,每个单词的首字母也必须是大写的,例如:NullPointerException
、FileNotFoundException
、ArrayIndexOutOfBoundsException
……
所有的属性、方法、局部变量、参数的名称都必须是首字母小写,如果名称由多个单词组成,第2个单词开始,每个单词的首字母也必须是大写的
所有的常量的名称中,每个字母都必须是大写的,如果由多个单词组成,则各单词之间使用下划线分隔,例如:state_ok
应该写成STATE_OK
绝大部分的属性应该使用名词,例如:name
、age
……
绝大部分的方法应该使用动词作为前缀,例如:setName
、getName
不遵守以上命名原则的属性或方法应该是疑问类型的属性或方法,例如:isAlive
、hasNext
,即使用is
或has
作为前缀
代码的版式也非常重要:
如果对代码的正确版式不太了解,可以使用Eclipse的Source
菜单中的Format
指令,使Eclipse来帮助排版!
其它……
发出请求
只能通过表单(Form)或Javascript代码发出POST请求,而发出GET请求的方式则更多,除了这2种做法以外,还可以通过改变浏览器的地址栏中的URL来发出GET请求!所以,发GET请求比发POST请求更加简单!
传输特点
GET请求的参数会暴露在URL中,不适合传输较私密的数据,例如密码,并且,受到URL长度的限制,GET请求不适合传递大量的数据,例如发邮件、上传文件都不可以使用GET请求!
POST请求的参数不会暴露在URL中,可以传输任何数据(传输过程没有额外的加密处理),并且,传输数据没有长度限制!
相比之下,POST请求更加有优势,但是,POST请求的发出限制略高,不便于刷新,并且,无法分享页面!
如果项目结构(Eclipse的左侧)提示了任何错误,都应该在Problems
面板中查看详情,有些错误可能并不体现在某个文件或代码中。
如果Eclipse默认没有显示该面板,可以点击Window
菜单中的Show View
项打开,如果在Show View
下仍没有Problems
,可以选择Other
项再查找。
移除旧版本
在Libraries
下,对旧版的JDK/JRE点右键,选择Build Path
中的Remove ...
选项,即可移除。
添加新版本
对项目名称点右键,选择Build Path
中的Configure
,在弹出的对话框中,选择Libraries
选项卡,然后点击右侧的Add Library
按钮,在弹出的新对话框中选择JRE System Library
并点击Next
,通常在下个界面中第3项即是当前系统安装的JDK/JRE版本!
如果在这个面板中没有所需的JDK/JRE版本,则点击Installed JREs
按钮并浏览到本机中安装JDK/JRE的目录进行选择即可。
每个类都有构造方法,用于确定对象的创建过程,当需要创建对象时,使用例如new Object();
这样的语法,就是在调用构造方法。
在编写类的时候,可以不需要显式的编写构造方法,当没有显式的编写时,编译器将自动添加公有的、无参数的构造方法!如果已经显式的编写了任何构造方法,编译器将不会自动添加构造方法!
构造方法也是方法,可以重载。
每次创建对象时,都会默认先调用其父类的构造方法!即:
public class User {
public User() {
super(); // 调用其父类的构造方法
}
}
且:使用super
关键字调用父类的构造方法的语句,必须编写在子类的构造方法中,必须是子类构造方法中的第1条有效代码!
抽象类的构造方法不允许直接调用,即不允许使用new
语法调用抽象类的构造方法来直接创建抽象类的对象!
通常,会在以下情景中自定义构造方法:
更便捷的创建对象,会自定义若干个带参数的构造方法,使得创建对象时就可以直接确定某些属性的值;
需要确定创建对象时,就执行的任务,或确定某些属性的值;
需要限制创建对象,可能将构造方法的访问权限设置得更加严格!
由于使用的系统不同,可能某些系统上快捷键不同,或会发生冲突,如果无法调整,则应该使用Source
菜单中对应的功能。
转发的本质是客户端只发出了1次请求,而重定向的话,客户端发出了2次请求。
转发是发生在服务端内部的,对于客户端而言,并不知道服务端内部有转发的过程,即使是控制器(无论是SpringMVC中的Controller还是传统的Servlet)转发到了JSP,对于客户端而言,也并不知晓。
在执行转发时,URL是不会发生变化的,而重定向会发生变化!
如果需要将较多的数据进行传递,可以使用转发!而重定向则不适合大量数据的传递,因为重定向对应的是2次请求,而2次请求之间数据并不共享!
如果需要地址栏发生变化,与当前页面显示的内容匹配,则必须使用重定向!
服务端对客户端进行响应时,除了有响应的正文以外,还会有响应代码。常见的响应码:
2xx:正确响应,例如:200、206
3xx:重定向,例如:301、302
4xx:请求错误,例如:400、404、405、406
5xx:服务器内部错误,例如:500
使用enum
关键字可以声明枚举类型,例如:
public enum RequestMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}
定义枚举的前提是:可以穷举所有可能的值,每个值都不相同,并不关心值本身而只关心它表达的意义。
在开发规范中,认为凡是用户提交的数据,永远是不可靠的,应该对数据进行有效性验证!
通常,关于数据格式(长度、组成字符)的验证,应该使用正则表达式来验证!
package cn.tedu.spring.util;
/**
* 字符验证工具类
* @author adminitartor
*/
public class TextValidator {
/**
* 验证用户名的正则表达式
* 验证规则:
*
* - 必须由4~16字符组成;
* - 必须由大写字母、小写字母、数字、下划线组成,不允许使用其它字符;
* - 第1个字符必须是大写或小写字母。
*
*/
public static final String REG_EXP_USERNAME
= "[a-zA-Z]{1}[a-zA-Z0-9_]{3,15}";
/**
* 检查用户名的格式是否正确
* @param username 用户名
* @return 如果用户名符合验证规则,则返回true,否则,返回false
* @see #REG_EXP_USERNAME
*/
public static boolean checkUsername(String username) {
if (username == null) {
return false;
}
return username.matches(REG_EXP_USERNAME);
}
}
一个完整的计算机硬件系统应该包括:运算器、控制器、存储器、输入设备、输出设备。
存储器分为内部存储器(内存/主存)和外部存储器(外存/辅存)。
内存只有:主板上的ROM、CPU内部的Cache(高速缓存)、内存条(RAM)。
RAM:Random Access Memory。
通常在开发领域讨论的内存指的都是内存条。
RAM的特性有:
它是唯一一个CPU可以直接访问的硬件;
一旦断电,内存中的所有数据会全部丢失;
正在执行的程序和数据必须在内存中。
使用static
可以修饰类的成员(属性/成员变量、方法、内部类、内部接口)。
它的特性是:唯一、常驻
唯一:假设Person
类中存在被static
修饰的static int hands = 2;
,无论把Person
类new
多少次,无论使用哪个对象调用hands
属性,对应的都是同一个值,所以,被static修饰的成员不归属于任何一个对象,在调用时,应该使用 类名.成员 的语法来调用,而不推荐使用 对象.成员 来调用。
常驻:被static
修饰的成员,会在它所在的类的名称第一次出现在运行的代码中时,就会被加载到内存,并且,会持续的一直在内存中,所以,表现出“常驻内存”的特性!所以,被static修饰的成员不可以直接访问非static成员!
由于static
成员是唯一的,所以,慎用static
修饰属性(成员变量),因为可能存在多线程下的数据安全问题(多个线程、同时、对同一个数据、进行修改,则可能导致线程安全问题)。
由于static
成员是常驻的,所以,无论是用于修饰哪种类型的成员,都应该慎用,因为可能过度的消耗内存!
内存泄露的主要原因是:尝试释放某个资源,却无法释放,而该资源将持续占用内存,却又无法被使用!
当垃圾回收机制尝试回收垃圾时,可能发现这些数据仍处于“使用状态”(可能与另一些资源保持了连接等等),则不会把这些数据视为垃圾,也就不会回收这些数据占用的内存空间!而由于程序中已经无法再使用变量操作这些数据了,对于开发者而言,这些数据已经用不着了,所以,就出现了“用不着的数据没有被当作垃圾来回收,反而一直占用内存”的现象!
所以,少量的内存泄露是没有明显的危害,但是,如果积少成多,会导致可用内存越来越少,当少到极点还继续使用,就会导致数据溢出。
解决内存泄露的做法就是:及时释放掉不需要使用的资源,例如流等等,应该及时调用close()
方法进行归还或关闭。
另外,关于垃圾回收,JVM中的垃圾回收机制会定期自动清理垃圾数据,无须开发者手动释放数据所占用的内存空间,即使调用System.gc()
方法也不能保证垃圾回收机制马上来回收数据!
字符集相当于一本字典,记录了每个字符与二进制码的对应关系!
a 110 0001
在ASCII码中,记录了英文输入法下的所有字母、数据、标点符号与二进制码的对应关系。
由于1个字节只有8个二进制位,无法表示中文(汉字的字符种类太多),所以,需要使用2个字节,即16个二制位来表达!
常见的支持中文的编码有:UTF-8、GBK、GB2312……,还有一些其它编码是完全不支持中文的,例如:ISO8859-1、latin1……
由于支持中文的编码格式有多种,但是,每种编码的二进制码与汉字的对应关系不一样,所以,如果存和取的时候,使用了不同的编码,就会导致乱码!
所以,解决乱码的答案:使用统一的、支持中文的编码。
在项目中,需要统一编码的位置:存储位置(例如数据库等)、显示位置(例如HTML/JSP页面、终端/控制台等)、传输过程(接收请求时、响应时、连接数据库时)、程序源代码……
首先,这2个组件的执行切入点不相同,过滤器是执行在所有的Servlet
之前的,而拦截器是执行在DispatcherServlet
之后、控制器之前的。
过滤器是Java EE体系中的,使用时,需要在web.xml
中进行配置,而拦截器是SpringMVC框架中的,使用时,需要在Spring的配置文件中进行配置。
过滤器的过滤规则相对比较简单,只能通过
节点配置它的适用范围,而拦截器的过滤规则相对比较灵活,即可以配置多项黑名单,还可以配置多项白名单。