俗话说“好记性不如烂笔头”,编程的海洋如此的浩大,养成做笔记的习惯是成功的一步!
此笔记是博主在做javaee开发的时候写的笔记,记录了一些比较容易让新手困扰的地方,笔记都是博主自己一字一字编写和记录,有错误的地方欢迎大家指正。
1、web.xml的路径不能写成/*.action,只能/*或*.action,其中*.action也默认要求需要访问时需要加/访问,如/aaa.action才是效的。
web.xml的匹配路径*是提倡最长匹配的,即如果有路径/abc和/*,会优先使用/abc。关于/*和*.action,/*也可以匹配到.action后缀的情况,但是如果增加了后缀,则优先匹配*.action的后缀。
web.xml的最长匹配与Spring配置事务的方法名不同,它是从上到下进行匹配,即有method="*"和method="abc",如果method="*"排在前面,则会先匹配到最先的method="*"而进行事务使用。
2、Servlet的监听器(Listener)比过滤器(Filter)先执行,例如ServletRequestListener监听器,在有请求时(请求包括jsp页面请求),会先调用见监听器的requestInitialized()方法,在调用拦截器的doFilter()方法。
Listener、Filter、Interceptor他们都是项目启动时启动,但监听器会先启动,并且它们都是单例模式。默认情况下,过滤器过滤请求相应的方式(REQUEST),如果需要过滤转发等方式,需要修改web.xml的配置。
过滤器的执行顺序是按web.xml的 <filter-mapping>配置顺序进行执行的,特殊的,如果<filter-mapping>配置的是拦截<servlet-name>将低于<url-pattern>,即会在<url-pattern>执行后才执行<servlet-name>而不管配置的顺序。
3、javabean对象之所以要实现Serialable接口,是因为了可以将数据保存到硬盘中。
例:如果tomcat服务器关闭后,会把Sesison对象保存到硬盘上,如果Session域里的值javabean实现了Serialable接口则也会得到保存,
那么在tomcat重启后,Session里的域里的值将还会存在,可以避免用户再次去登录(前提是浏览器重未关闭过)。
4、对于jsp页面的请求地址,如果在地址前不加入项目名,tomcat服务器后默认加上项目名。即使用缺省地址(不加入项目名,但地址前必须不能有/开头)也可以进行访问。
5、一般来说。内网都放在WEB-INF/的目录下,因为比较安全且便于权限的设置,而外网通常都直接网站WebRoot/下,这样访问速度快且效率会更高一些,通常一个项目
两种情况都具备,具体情况具体分析。
6、对于jsp的包含include指令,静态包含是直接发布时就嵌入,动态包含是运行时才嵌入。因为包含是给服务器使用的(tomcat都运行时需要先编译jsp故是服务器使用),故不需要写项目名,又因服务端使用的
原因,故包含可以直接包含WEB-INF下的页面。只包含部分代码的叫做jsp的片段,后缀可以是jspf。注意,每一个jsp或jspf开头都必须包含一下代码:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
附加:一般页面的最外层不要使用百分比(%)来设置大小,因为它是相对于浏览器的,如果浏览器放大缩小将直接影响到最外层的标签,容易引起变形。
而内层的大小则应该使用百分比(%)来设置大小,它是相对于上层的,这样便于最外层修改大小。
7、在创建javaBean对象时,应该使用保包装类型而不是基本类型,因为当数据库返回的数据是NULL时,使用包装类对象可以接收NULL,而基本类型就做不到。
相反的,在定义参数的类型时,应该使用基本类型,尽量不要是自定义的对象或包装对象,以最低要求来获得方法的使用。
8、Servlet获取目标地址的方法分析:
request.getRequestURL(); //获得整个目标网址名 http://localhost:8080/myshop/user/confirm.jsp
request.getRequestURI(); //获得在当前项目下的目标地址 /myshop/user/confirm.jsp
String goURL=request.getServletPath(); // 用户想去的地址(即目标地址),不包括工程名 /user/confirm.jsp
String param=request.getQueryString(); // 获取URL后面的参数
//如果想获取一个带参数的URL进行重新请求,使用如下方法
if(param!=null){
goURL+="?" + param;
}
9、页面缓存分析(默认情况下是开启缓存的):
<9.1> <meta http-equiv="pragma" content="no-cache"> : 是HTTP1.0的配置,在HTTP1.1中以及不使用。
<meta http-equiv="cache-control" content="no-cache"> :是现在HTTP1.1的设置, no-cache 此参数仅仅支持IE 不支持火狐, 可以使用 no-store 两种浏览器都支持
<meta http-equiv="expires" content="0"> :指页面的缓存时间,单位为分钟,-1表示不缓存该页面(但不禁止,表示页面刷新时重新去服务端获取)。只有在没有设置no-cache参数时才有效。
<9.2> 禁止页面缓存使用才能使网页过期,能确保每个浏览器都支持
<%response.setHeader("cache-control", "no-store");
response.setHeader("cache-control", "no-store");
//虽然这是http1.0的缓存功能,但还是要补上,因为有些浏览器还是使用http1.0版本
response.setHeader("pragma", "no-cache");
response.setDateHeader("expires", -1);
%>
而使用下面的禁止页面缓存代码方式有些浏览器并不支持,故不建议使用
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<9.3> 注意:Servlet的转发跟请求不同,转发时属于服务器内部使用的方式,相当与跳转,如果请求的是POST方式,那么转发到某个页面后,还是属于POST的请求,
如果是使用GET方法,那么转发到某个页面后,该页面还是属于GET的请求方式。
<9.4 >浏览器默认默认的请求方式是GET,所有的重定向都是属于GET请求,包括Servletd和Seruts2的重定向都是一样。
<9.5> POST和GET的区别:
(1)、封装参数的区别:
get请求时把参数加入到请求头(即地址)中,且不能传递文件。
post请求时把参数加入到请求体中,可以传递文件。
(2)、缓存功能的区别,如果使用了禁止缓存功能:
使用get请求访问页面,在按后退的时候不会有"页面过期"提示,而是会直接到服务器端重新获取数据。
使用post请求访问页面,在按后退的时候会有"页面过期"提示,不会直接去服务端请求数据。
(3)、如果短时间内请求相同的地址:
使用get请求时,会变成自动使用缓存,而不再重新请求。
使用post请求时,每一次的请求都会都会向服务请重新进行请求。
附加:如果点击浏览地址按回车,那么将会是变成get请求,当再次请求时也将会使用缓存。
10、关于GBK、GB2312、UTF-8、ISO8859-1,这四个编码方式的英文和数字都是相互兼容的,即英文和数字他们的编码表都是一样的。
11、把项目直接放入到tomcat的wabapps/ROOT下,那么访问时可以直接进行访问而不需使用项目名.(项目名的文件夹不要拷贝进来)
12、注意,一个客户是一个会话,每一次的请求都是一个线程。
13、使用FileReader/FileWriter读取文件时,编码方式是使用整个项目的编码方式。
14、Tomcat的get方法编码修改:在<Connector port="8080">标签中增加URIEncoding="UTF-8"。
15、在jsp页面中引用js文件和css文件时,必须注意路径的引用。如果使用相对路径(即不是用"/"开头),那么引用时,不是以当前项目为相对路径,而是以当前jsp为相对路径。
例如:某个jspPage文件下jsp的引用js路径为:<script type="text/javascript" src="js/jquery.js"></script>,那么js实际路径
将会是:地址/项目/jspPage/js/jquery.js,将导致路径出现差错。特殊的,如果jspPage文件是在WEB-INF下,那么js的实际路径将会是以当前项目为相对路径:地址/项目/js/jquery.js。
通常建议使用绝对路径 ${pageContext.request.contextPath}/jspPage/js/jquery.js
16、关于超链接请求,如果是相对路径(即不是"/"开头),实际路径会在该地址上补上项目名:地址/项目/相对地址
17、<javaScript>的标签不能简写,即不能写成<javaScript />,必须要有标签头和尾部。<javaScript>...<javaScript/>
18、JDBC的占位符?的起始下标是从1开始,而hibernate的占位符?是从0开始(hibernate还支持名字参数例如":id")。
19、当使用Servelt返回Json格式时,写json格式的String表示,必须注意使用双引号("),不能使用单引号(')。
或是可以使用Json的jar包API:
JSONObject ob=new JSONObject();
ob.put("id", 1);
String jsonStr = ob.toString();
20、当使用Ajax请求Servlet时,Servlet不要再使用转发或重定向。Ajax请求返回Json数据的Servelt案例:
Servlet代码:
PrintWriter out = resp.getWriter();
JSONObject ob=new JSONObject();
ob.put("id", 1);
String jsonStr = ob.toString();
out.write(jsonStr);
out.flush();
jsp页面js代码:
$.post("/easyUI/myservlet",{"myjson":"hahamyjson"},function(da){
alert(da.text);
},"json");
21、当Servlet的request对象的流被关闭后,应该立即退出方法,而不应该再执行方法剩余的操作。request有字节流对象(InputStream)和字符流对象(Reader),两个流对象不能同时调用,
即只能获取其中一种对象,否则报错,且这两个流对象读取的是请求体的数据,即只能读取post请求提交的参数,不能读取get的请求参数。
22、Servlet的Filter过滤器默认拦截"请求模式",即使是直接连接到jsp页面也会进行拦截(还包括图片/js/css等资源请求都会拦截)。而struts2的interceptor拦截器也是只拦截"请求模式",但是不会对资源(图片/js/css等资源)请求进行拦截,只会在对
action类的请求时才会进行拦截。Filter的拦截模式可以在web.xml中修改,但是interceptor拦截模式是不可修改的。
23、当在jsp页面中使用EL表达式时,需要注意,EL表达式可以在jsp页面中的任何地方使用,包括jsp页面中的javaScript和css等地方都可以使用,但是
如果javaScript或css被抽出来当做独立的写在一个文本中,EL表达式是不可以使用的,即不会对${}进行转义和取值,会原样输出。
24、forward请求,是属于内部转发。原来的request请求是什么请求方式,forward请求就是什么方式。即如果request请求时get,那么使用forwar转发时也是用get。post也同理。
25、EL表达式注意事项:
(1)使用EL表达式时,如果取得对象key是不存在的,那么EL表达式是不会报错的,但是如果是通过对象获取属性时,如果属性不存在则会报错。
例如:${myuser} ,如果myuser不存在存储域中,EL表达式也不会报错。
${myusers.name},如果myusers在存储域中存在,而myusers对象没有name属性,那么EL表达式将报错。
(2)对于类型的比较,EL表达式会测试着转换成相同类型进行比较,例如"true"==true,结果是true。
(3)EL表达式只会在jsp页面进行解析,不会再css文件或js文件解析,因此,需要注意独立的css和js文件中不要使用EL。
如果非要使用EL表达式,那么就不应该把css和js独立抽取出来,而是统一写在jsp页面中。
26、默认情况下,servlet是在第一次访问时被构建,并调用init()方法,如果想在服务器启动时就构建,则应配置web.xml文件:
1)load-on-startup元素标记容器是否在启动的时候就加载这个servlet(实例化并调用其init()方法)。
2)它的值必须是一个整数,表示servlet应该被载入的顺序。当值为0或者大于0时,表示容器在应用启动时就加载并初始化这个servlet;
3)当值小于0或者没有指定时,则表示容器在该servlet被选择时才会去加载。
4)正数的值越小,该servlet的优先级越高,应用启动时就越先加载。
5)当值相同时,容器就会自己选择顺序来加载。
27、当使用servlet的HttpServletRequest对象(简称request)时,必须注意以下几点:
(1)request.getParameter("arg")方法是获取get参数的,不管是get还是post请求,都会自动的获取对应请求参数。对于get,会自动在url地址栏后边取值,对于post,会自动在请求体里面取值。
(2)request.getInputStream()和request.getReader()方法不能都使用,同个request对象只能使用其中一个。附:此方法对于get无作用。
(3)当使用post请求时,request.getParameter("arg")会和request.getInputStream()、request.getReader()互相干扰,因为getParameter()方法就是同个流读取参数的,
因此,如果先调用了getParameter()方法,那么request.getInputStream()、request.getReader()都将无法再读取到请求体数据。故,不能都使用,只能使用其中一种。
(4)当使用的是混合表单时,request.getParameter("arg")是无法获取参数的,此时就只能通过request.getInputStream()、request.getReader()来获取。
(5)request.getParameter("arg")、request.getParameterMap()、request.getParameterNames()这些方法是不会互相影响的,可以同时使用。
(6)对应请求数据时xml数据包的,用request.getInputStream()和request.getReader()方法直接读取是会出现数据不正确的情况,而应该直接把request.getInputStream()和request.getReader()
得到的流通过dom4j等jar包进行解析,从而获得正确的xml数据。
28、tomcat使用JNDI的配置(在<host>标签里增加):
<Context path="/test" reloadable="true" docBase="/test" crossContext="true" debug="0">
<Resource
name="jdbc/mysql"
type="javax.sql.DataSource"
auth="Container"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="3000"
maxWait="5000"
url="jdbc:mysql://localhost:3306/cat"
autoReconnect="true"
maxActive="50"/>
</Context>
附加:
(1)虚拟目录的配置(在<host>标签里增加):<Context path="/site" docBase="c:/site" reloadable="true" debug="0"/>
(2)虚拟主机的配置(注释掉原<host>标签):<Host name="localhost " appBase="E:\mywebapps">
(3)修改tomcat的内存,在myeclipse中配置tomcat的jdk参数:
-Xms256m -Xmx512m -XX:PermSize=32m -XX:MaxPermSize=128m
29、当请求路径为 "url?name=cat&age=",此时的请求参数有两个:一个是name,值为cat;另一个是age,值为空字符串""(注意不是null)。
如果参数是特殊字符,如\,在处理方法中获取参数时,会自动转义,变为\\。
30、关于servlet的Filter拦截器,不仅仅只拦截网页的请求,还会拦截网页下的资源请求(如图片,js文件等),因为浏览器在请求网页时,如果网页包含其他资源,
那么会一个个的去请求(相同的资源只请求一次),导致服务器多次受到请求处理,因此也会多次触发拦截器的请求。
附加:拦截器的拦截方法参数有ServletRequest和ServletResponse,可以转换为HttpServletRequest和HttpServletResponse。
request.getServletPath();只包含请求路径,不包含项目名。 /index.jsp
request.getRequestURI();包含项目名和请求路径。/test/index.jsp
request.getRequestURL();详细的url请求路径。http://localhost:8083/test/index.jsp
31、web项目的web.xml文件的配置需注意,不管是过滤器还是servlet处理器,在配置url-pattern时,都尽量使用后缀路径,例如*.action。
原因:因为浏览器在请求网页时,如果网页包含其他资源,那么会一个个的去请求(相同的资源只请求一次),
例如:请求/test/as/abc.action ,服务器转发到index.jsp页面,此页面包含second.js和pic.jpg,
那么会分为三次请求:/test/as/abc.action
/test/as/second.js
/test/as/pic.jpg
当配置的路径为url-pattern为/*时,那么三次请求都将会拦截处理。如果配置为 *.action,那么只会拦截/test/as/abc.action进行处理,效率大大改善。
因此,应尽量避免使用/*配置,而使用后缀方式配置。
附加:
(1)url-pattern配置是区分大小写的,例如 *.ACTION与 *.action是完全不同的。
(2)过滤器的执行顺序是按web.xml的 <filter-mapping>配置顺序进行执行的,特殊的,如果<filter-mapping>配置的是拦截<servlet-name>,将低于<url-pattern>,即会在<url-pattern>执行后才执行<servlet-name>而不管配置的顺序。
(3)servlet的配置时有最长匹配机制的,且/*优先*.action配置。注意,过滤器的配置是没有最长匹配机制的。
(4)如果两个servlet配置的url-pattern是一样的,那么后者会覆盖前者。注意,在任务情况下都不会让两个servlet都执行。
(5)不同的web服务器,解析web.xml的机制与要求会有差别,例如resin不允许<filter-mapping>配置在<filter>之前,而tomcat而允许,通常最好按正常像顺序配置,并且开发的web服务器与发布用的web服务区尽量保持一致。
32、使用HttpServletRequest类的对象request.getParameter("key");获取参数时,
如果参数key存在,即使客户端只有key而没有任何的请求值,该方法返回空的字符串""。
如果参数key不存在,则该方法会返回null。
33、前端的html页面,只要form表单中的input有指定name属性名,即使没有设置value属性值,在提交表单时,同样会作为请求参数进行请求,对应的value为""。
当请求参数写在url请求路径时,有key而没有value值,也同样会作为请求参数进行请求,对应的value也为""。例如www.baidu.com?mykey&mykey2=key2val,此处有两个请求参数,mykey=""和mykey2="key2val"
34、如果想自己定制HttpServletRequest或HtppServletResponse 的某些功能,建议使用HttpServletRequestWrapper/HttpServletResponseWrapper,
这两个类是专门的包装类,默认使用都是使用原HttpServletRequest/HtppServletResponse 的方法,可以直接重载某个方法来进行特殊功能定制,最后
通过Filter过滤器的doFilter()方法传入包装后的类对象。
35、在Filter过滤器中,使用chain.doFilter()时,如果放行后的资源下一个处理是Servlet,且该Servet的处理方法最终使用req.getRequestDispatcher("/menu.jsp").forward(req, resp);进行转发,在执行完forward(req,resp)方法时,就把转发的menu.jsp页面写入到resp流中,而不是等全部Servlet和Filter过滤器执行完才写入。因此,在chain.doFilter()方法调用完后,当前过滤器的doFilter还没执行完就已经在resp写入相应的页面。
注意:如果Servlet的处理方法不是使用forward转发,而是使用sendRedirect重定向,那么并不会把页面写入到resp流中,而是写入特定的头数据,通知浏览器重新请求一次该页面。