一、String
1、final 修饰的变量不可继承。
2、String str1 ="a"; String str2= newString("a"); 两者占用的内存是不同的,前者是 str1 指向了已存在的一个 "a" (若不存在会在 heap 创建),不会占用过多的内存,是直接指向 "a" ;而后者不然,后者是在 heap 中新开辟了一部分,从而占用了更多的内存,不论 heap 是否存在了 "a" ,new 都会新开辟一段内存,用于存放,然后再由 str2 去指向。
3、StringBuilder 线程不安全,效率高, StringBuffer 线程安全,效率低。在使用 StringBuilder 的 delete 时,“包头不包尾”,实例是:
StringBuilder sb = new StringBuilder("123456789");
sb.delete(2,4);
// 输出结果为:1256789
二、线程
1、进程是一个静态概念,实际运行的是(主)线程。
2、为了更好的灵活性,线程的使用上,最好用接口,而不是去继承线程。
3、线程同步,需要对类中所有方法都考虑是否同步(加锁),这个步骤是必须的,如果过多的线程使用了同步,会降低效率。
4、wait 和 notify 一般成对使用,保证不会让一个线程一直死在 wait 。
三、Servlet
1、写 Servlet 时,首先要重写父类里面的 doGet , doPost 。super表示调用父类方法,如果重写了,最好不要这个。要在 XML(指web.xml)中对写好的 Servlet 进行配置,每个 <servlet> 对应一个映射 <servletmapping> 。
写法如下:
<servlet>
<servletname>Xxx</servletname>
<servletclass>com.xx.xx.xx</servletclass>
</servlet>
<servletmapping>
<servletname>Xxx</servletname>
<urlpatter>/Xxx.html</urlpatter>
</servletmapping>
特别要注意的是映射中的名字要和 <servlet> 一致。
2、对于 Servlet 中调用过的方法要做到用完就去关闭。
3、提交表单时,调用doPost比较多,doGet会将请求参数显示在URL中,而doPost方法不会显示请求参数。
4、目前 Servlet 只是负责 MVC 总的 Controller ,由于 JSP 的原因,View 部分就不通过它了。
5、页面导航,跳转方法有:
1)请求重定向,可以跳转到其他网站写法为:
response.sendRedirect("url");
// 实例:response.sendRedirct("http://www.google.com");
2)请求转发,当前域,不包含(只是跳转):
requset.getRequestDispatcher("url").forward(request,response);
// 实例:requset.getRequestDispatcher("http://www.google.com").forward(request,response);
3)请求包含,当前域,包含(两个页面的内容包含在一起):
request.getRequestDispatcher("url").include(request,response);
//实例:request.getRequestDispatcher("http://www.google.com").include(request,response);
6、 要注意方法中获取某个数据时,要与form 表单中的名字一致。单个参数的获取是用getParameter() 方法。
7、获取 form 中的多个参数时,使用 getParameterValues() ,这时一般多个参数各有一个 value值。
8、注意 doPost 方法中要写 doGet() ,反之也可以。请求先经过的是 service() ,然后会根据需求和所写的内容进行判读是用 doGet() 还是 doPost() ,一般不写 话是默认调用 doGet() 。两者总会用一个,如此写,方便使用。
这里给出一个实例(在 doGet 中的):
Enumeration<String> enum1 = request.getHeaderName();
while(enum1.hasMoreElements()) { //遍历寻找所需的部分
String name = enmu1.nextElement();
String value = request.getHeader(name);
System.out.println(name + " : " + value);
}
9、获取头信息的作用之一是判断浏览器,这一点比较常用,可用做判断客户所用浏览器,从而给出判断,反馈并建议使用某个浏览器(一般是建议使用 IE ,使页面服务和效果更佳)。
10、响应头信息(一般为 set 方法),可以构建 Excel 表格,可以动态生成图像,这两个用的是
response.setContentType(“name/ttype”) ,可以定时刷新。下面是实例:
// 例1(Excel表):
response.setContentType("application/vnd.msexcel");
PrintWriter out = response.getWriter();
out.println("\tQ1\tQ2\tQ3\tQ4\tTotal");
out.println("Apples\t78\t87\t99\t55\t=SUM(B2:E2)");
out.println("Oranges\t33\t54\t67\t78\t=SUM(B3:E3)");
// 例2(图片):
response.setContentType("image/jpeg");
InputStream in =this.getClass().getClassLoader().getResourceAsStream("xx.jpg");
int len = in.avaliable;
byte[] buffter = new byte[len];
in.read(buffer);
OutputStream out =response.getOutputStream();
out.write(buffer);
out.flush();
out.close();
// 例3(刷新间隔):
response.setHeader("refresh","1");
response.setContentType("text/html;charset=utf8");
PrintWriter out = response.getWrtier();
out.println("<!DOCTYPEHTML>");
out.println("<HTML>");
out.println("<HEAD><TITLE>AServlet</TITLE></HEAD>");
out.println("<BODY>");
out.print("XXXXX");
out.print(new Date().toLocaleString());
out.println("</BODY>");
out.println("</HTML>");
out.flush();
out.close();
11、cookie 是键值对,以response来响应,request来获取。
12、session 有失效性,一般关闭了浏览器就会使之失效,即为浏览器与服务器一对一关系,如果是在 cookie 里面,则不然。这里给出 session 最常用用法:登录 session ,结合了JDBC,DAO等部分的知识。其中, M->DAO , V->login.jsp , C->Servlet 。
// 例(写在 doGet 中的):
String username =request.getParameter("username");
String password =request.getParameter("password");
UserDAO dao = new UserDAOImpl();
User u = dao.login(username,password);
if(u != null) {
HttpSession session = request.session();
session.setAttribute("username",u);
request.getRequestDispatcher("xx.jsp").forword(requset,response);
} else {
request.getRequestDispatcher("error.jsp").forword(requset,response);
}
13、共享变量作用域:
ServletContext(在任何作用域,容器中有效) > HttpSession(在当前浏览器,一个会话中有效) >HttpServletRequest(只在当前的 request 请求中有效)
14、Filter 位于客户端和请求资源之间,在此起的几个常用方面:Session 管理,权限验证,日志记录,字符编码转换。注意 Filter 也要在 XML 中配置(Struts2应该有自动配置),这里可以配置过滤器有效的范围。
15、Listener 用于监听 Web 工程状态改变。范围上,和共享变量作用域的大小范围一致。也是需要在 XML 中配置的配置方法,简单的例子是:
<listener>
<listenerclass>com.xx.xx.xx.xx</listenerclass>
</listener>
16、这里给出一个使用 request和 response 的实例:
public String getCourseList() throwsException {
HttpServletRequest request =this.getRequest();
String batchNum =request.getParameter("batchNum");
String planBatch =request.getParameter("planBatch");
String course =request.getParameter("course");
String[] courses = null;
if (course != null &&!course.equals("")
&& (planBatch.equals("")|| planBatch.equals(batchNum))) {
course = course.replaceAll(" ","");
if (course.length() >= 3) {
course = course.substring(1,course.length() 1);
}
courses = course.split(",");
}
String opResult = "";
courseCodeList = iPlanInformationQueryService.
getAllCourseromCommonCode(batchNum);
if (courseCodeList == null) {
courseCodeList = new ArrayList<CommonCode>();
}
if (courseCodeList.size() > 0) {
CommonCode cc = null;
opResult += "<tablealign=\"center\" width=\"100%\"><tr>";
for (int i = 0; i < courseCodeList.size(); i++) {
cc = courseCodeList.get(i);
opResult += "<td><inputtype=\"checkbox\" id=\"course\" name=\"course\"value=\""
+ cc.getCode() + "\"";
for (int j = 0; courses != null && j < courses.length; j++) {
if (courses[j].equals(cc.getCode())) {
opResult += "checked=\"checked\"";
break;
}
}
opResult += ">";
opResult += "[" + cc.getCode() +"]" + cc.getCodeName() + " ;</td>";
if ((i + 1) % 4 == 0) {
opResult +="</tr><tr>";
}
}
opResult +="</tr></table>";
} else {
opResult = "XX";
}
HttpServletResponse response = null;
try {
response =ServletActionContext.getResponse();
response.setCharacterEncoding("UTF8");
response.setContentType("text/html");
response.setHeader("Pragma","Nocache");
response.setHeader("CacheControl","nocache");
response.setDateHeader("Expires",0);
response.getWriter().write(opResult);
} catch (Exception e1) {
e1.printStackTrace();
}
return null;
}
四、文件操作
1、Java 中的文件操作可以参看 File 的 io ,即为File.class 中查找参看。
2、一般来说,关闭文件流的语句放在final 里面,因为 final 是比执行的。
3、在写文件路径时,注意要写 \\ 因为单个的 \ 会被MyEclipse 会认为是正则表达式。
4、文件处理,多用 reader , writer ,这里涉及字符字节流的问题,需要在实际操作中注意文件大小,比如说读取和缓存的大小,不可设置的过大,会导致内存不足。
5、遍历文件夹的操作,选用递归的方式,同的方式也用于对文件夹的删除。
6、捕获了异常后,最好抛出。
7、文件的某些操作可以调用 until类中的相关方法。
8、进行文件上传时,有直接将文件转化为byte数组,存在数据库的方式,也有只是存地址而将内容存在服务器的方法。特别注意的是,写成byte数组的时候,要注意将各个部分都存入,即为文件内容,文件类型,文件名等。
9、文件下载可以仅仅使用response ,但是同时使用 request 也是可以的,需要注意在前台产生request ,例如:
// 例一:
$.ajax({
beforeSend: function(XMLHttpRequest){
XMLHttpRequest.setRequestHeader("RequestType","ajax");
//alert(str);
}
});
// 例二:
<%
Stringstr=request.getParameter("planBatchName");
%>
在后台时,就可以利用前台传过来的 request 。注意 response 在Struts2的用法是:
HttpServletResponse response = ServletActionContext.getResponse();
五、Struts2
1、每写一个action的类中的方法,要在Struts。XML中配置个<action>对,这里面写个<result>来跳转。
2、推荐的获取Web资源的方法是以ServletAPI耦合的方式,可以获取更多的资源。
3、通过实现ServletXxxAware接口的方式,可以由 Struts2 注入需要的Servlet 相关对象如:
ServletRequestAware:注入HttpServletRequest 对象
ServletContextAware:注入ServletContext 对象(比较常用)
ServletResponseAware:注入 HttpServletResponse对象
4、默认情况下,Struts2请求的 jsp 页面的超链接识别,可以应答 .action 和无拓展名;struts.action.extension 定义了当前Struts2应用可以接受的请求的扩展名,然而可以在struts.action.xml 文件中以常量配置的方式修改default.properties 所配置常量。
5、ActionSupport是默认的 Action 类:若某个 action 节点没有配置class 属性,则 ActionSupport即为待执行的 Action 类,而execute 方法即为要默认执行的 action 方法。
6、手工完成字段验证,显示错误消息,国际化等情况下,推荐继承ActionSupport 。
7、关于result:
1)是action 节点的子节点;
2)代表action 方法执行后,可能去的一个目的地;
3)一个action 节点可以配置多个 result 子节点;
4)result的 name 属性值对应着action 方法可能有的一个返回值。
5)result有两个属性,一个 name 一个 type , type 表示结果的响应类型。
6)result的 type 属性值在strutsdefault 包的 resulttype 节点的 name 属性中定义。
常用的有:
> dispatcher(默认):转发,同Servlet 中的转发;
> redirect:重定向;
> redirectAction:重定向到一个Action,特别的:通过 redirect 的响应类型也可以便捷的实现redirectAction 的功能;
<result name=""type="">
<param name="" >Xxx</param>
<param name="">/Xxx</param>
</result>
<!-- OR -->
<result name="" type="">/Xxx/Xxx.do</result>
> chain:转发到一个Action ,特别的:不能通过 type =dispatcher 的方式转发到一个 Action ,只能是:
<result name=""type="">
<param name="" >Xxx</param>
<param name="">/Xxx</param>
</result>
<!-- 不可用-->
<result name=""type="">/Xxx/Xxx.do</result>
8、要明白result 中的 name 名字和/XX.jsp的名字没关系,可以不同名。
9、通配符的作用简单理解是:一个action申明实现多个需要用的。一对多模式,所以称为通配符。映射规则为:
1)找到多个匹配,没有通配符的那个将胜出;
2)若指定动作不存在
10、在S标签中,使用<s:property />要注意,value = "xxx" ,中的内容会被解析为OGNL表达式,如果只是要普通字符串,则需要写成value = " 'xxx' " 就可以了。<s:property/>中,可以使用default 设置默认值,规则是:栈中有值(或者存在这个对象),取用栈里面的值;栈中无值(或者无该对象),采用设定的默认值。
11、ognl表达式中访问静态方法时,要注意在配置文件中配置容许访问静态方法(Struts2.1以后存在此问题),访问静态的方法属性等的例子如下:
<s:property value="@包名.类名@方法名" />
如果要访问Mat类的静态方法,可以采用如下方法:
<s:property value="@@方法名" />
12、投影(过滤)的写法很像正则,但是不太一样,具体如下(用List为例子,其中会有age属性):
<s:property value="list.{?#this.age ==1}[0]" /> //单纯过滤符合条件的
<s:property value="list.{^#this >1}.{age}" /> //过滤开头
<s:property value="list.{$#this>1}.{age}" /> //过滤结尾
<s:property value="list.{$#this >1}.{age}== null" /> //过滤结尾符合条件的
注意:这里的#是表示过滤
13、S标签中关于 # $ % {} 等的问题:
1)用#可以取出堆栈上下文中的存放的对象,通常强调从上下文取。例如:
#parameters.name[0]等价于request.getParameter("name"),
#session.name等价于session.getAttribute("name"),
#request.name等价于request.getAttribute("name");
2)用%{}可以取出存在值堆栈中的Action对象,直接调用它的方法.例如你的Action如果继承了ActionSupport .那么在页面标签中,用%{getText('key')}的方式可以拿出国际化信息;
3)%{#},这是JSP2.1最新规范中的语法,是Struts2为其解决兼容性问题而写成%{#}的,在域对象中使用%{#}。%{#}仍然用于计算表达式,只不过操作元可以是变量,例如:
%{#session.user.userName}
先定义一个变量 :
<s:setname="age" value="%{25}"/>
则 %{#age} 将输出25,也可以省略 # ,写为%{age} ,若将age加10,可这么写:%{#age+10},将输出30.不能省略 # 。也就说变量用于计算时不能省略 # 。
4)%{}强调的是从你设定的root点取,用于计算表达式,例如:
%{10+20}结果将输出30
%{"a"+"b"}结果将输出"ab"
5)ognl中的#、%和$:
1>#符号的用途一般有三种。
1)访问非根对象属性,例如示例中的#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时, 需要加#前缀。实际上,# 相当于 ActionContext. getContext();
#session.msg 表达式相当ActionContext.getContext().getSession(). getAttribute(”msg”) 。
2)用于过滤和投影(projecting)集合,如示例中的persons.{?#this.age>20}。
3)用来构造Map,例如示例中的#{’foo1′:’bar1′, ’foo2′:’bar2′}。
2>%符号
%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值。如下面的代码所示:
<!-- 构造Map -->
<s:set name=”foobar” value=”#{’foo1′:’bar1′,‘foo2′:’bar2′}” />
<p>The value of key “foo1″ is<s:property value=”#foobar['foo1']” /></p>
<p>不使用%:<s:urlvalue=”#foobar['foo1']” /></p>
<p>使用%:<s:urlvalue=”%{#foobar['foo1']}” /></p>
3>$符号
$符号主要有两个方面的用途:
1)在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在min同{max}之间。
2)在Struts2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:
<validators>
<field name=”intb”>
<fieldvalidator type=”int”>
<param name=”min”>10</param>
<param name=”max”>100</param>
<message>BActiontest校验:数字必须为min为{max}之间!</message>
</fieldvalidator>
</field>
</validators>
14、struts2和struts 比,减少了线程的拥堵问题。每次启用action,struts2 会新开一个对象。
六、Spring
1、IOC /DI(Inversion of Control——控制反转、Dependency Injection——依赖注入)主要的含义是指:依赖抽象,非具体。在程序上,就是指程序间的依赖关系由依赖具体实现,变成依赖抽象接口实现,此即为依赖抽象,非具体。
2、改变写成 static 方法的程序,可以采用通过修改配置文件,动态修改输出结果方法。
3、依赖注入的方式更多的是使用 setter 方法,也可能会使用构造方法注入的方式,接口注入的方式则不很常用。
4、Spring 的核心的功能是“松耦合”。
5、Bean 的实例化过程会使用默认的构造方法来实例化(无参的),换而言之,如果类中有含参的构造方法,就需要写一个不含参的构造方法。
6、OCP:open closeprinciple,指对扩展开放,对修改关闭。
7、set 用 iterator 遍历,同样的,map 要先用 set 获取 key ,再用 iterator 遍历。map 的遍历如下:
Set keys =map.keySet();
Iterator it =keys.iterator();
whlie(it.hasNext()) {
String key =(String)it.next();
String value =(String)map.get(key);
}
8、map 的配置写法如下:
<propertyname="map">
<map>
<entry>
<key>
<value>XXX</value>
</key>
<value>XXXXXXX</value>
</entry>
</map>
</property>
9、AOP:面向切面(Aspect)编程。Aspect:将横切多个业务对象的程序独立出来模块化,该模块可以无侵入式的集成到业务对象当中,例如:事务、日志、权限。
10、SpringMVC学习的博客:http://www.iteye.com/blogs/subjects/springmvcexplore
七、JSP
1、JSP 上写Java代码时,有 if ,for 之类的时,在页面输出时,逻辑上看起来很乱。具体情况如下:
<% for(int i = 1 ;i < 9 ; ++ i) { %>
<p>look here</p>
<% } %>
如果这样的代码多了,看起来就很杂乱。
2、使用 <%@ includefile="xx.jsp"%>(也可以是其他文件)可以优化加载速度,是静态导入。<jsp:includepage="xx.jsp"></jsp:include> 属于动态导入。前者一般用于:需要被引用文件中的内容(某参数等)时,注重共享的功能;如果不需要被引用文件中的内容,加载速度差距不大时,可以用后者,后者使用的位置更加灵活,不存在共享问题。
3、<%= xx%> 在编译成 Java 时,表达的是:out.print(xx); 所以,不可在该表达式中写不符合Java语法的表达式,比如:<%= xx;%> ,就是一种错误表示方法。
4、<%! %> 这种声明,转换过去相当于是 Java 中的成员变量或者方法,所以,不同于其他部分转译为 Java 时的位置,处于转译文件的类的开始部分,作为成员变量或者方法,其他的都在该类下的 Service 方法下。这个实际使用的比较少。特别注意:JSP 中的 <% %> 里面的内容在转译的 Java 文件的 Service 方法 当中,默认内置对象名字是 request 和 response (其他还有 session 等,都不是缩写,共9个内置对象)所以在JSP 中使用时,用这两个名字。
5、JSP 中,在 <% %> 写输出一般建议使用 out (内置),而不建议使用 response 。理由是out 加了缓存,效率更高。
6、 <! > 这种注释依旧会执行,不想被执行,就使用 <% %> 进行注释。