一、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、 <! > 这种注释依旧会执行,不想被执行,就使用 <% %> 进行注释。