JAVA WEB整合开发王者归来 -- 读书笔记 by CZF 完整版

JAVA WEB整合开发王者归来

-- 读书笔记

 目录

第1章 概述. 1

第2章 搭建web开发环境. 1

第3章 Servlet技术. 1

第4章 深入JSP技术. 7

第5章 会话跟踪. 12

第6章 过滤器Filter16

第7章 监听器 Listener18

第8章 JSTL标签库. 19

第9章 自定义标签. 23

第10章 资源国际化. 25

第11章 数据库概述. 26

第12章 JDBC 详解. 26

第13章 XML概述. 31

第14章 Struts1.x概述. 33

第15章 Struts1.x高级应用. 35

第16章 Struts2.x概述. 39

第17章 Struts2.x高级应用. 42

第18章 Struts2.x 标签. 44

第19章 Struts2.x 拦截器与文件上传. 51

第20章 Hibernate入门. 54

第21章 从宏观上把握Hibernate57

第22章 Hibernate实体映射. 57

第23章 Hibernate实体关系映射. 60

第24章 Hibernate查询语言HQL61

第25章 Hibernate高级查询. 63

第26章 Spring概述. 63

第27章 Spring的Core模块. 66

第28章 Spring的AOP模块. 66

第29章 Spring的DAO模块. 66

第30章 Spring的ORM模块. 66

第31章 Spring的Web模块. 67

第32章 Spring的MVC模块. 67

第33章 Spring开发实例(SSH、SSJ). 67

第34章 EJB3概述. 67

第35章 JPA规范. 68

第36章 WebService框架Xfire68

第37章 版本管理工具SVN68

第38章 日志工具commons-logging与log4j68

第39章 报表图形引擎JfreeChart68

第40章 PDF组件iText68



第1章 概述

1.  Java Servlet 是改进的 CGI(Common GatewayInterface) 公共网关接口

2.  Java 服务器:Apache的Tomcat、IBM的WebSphere、BEA的WebLogic、RedHat的JBoss

第2章 搭建web开发环境

3.  WAR(WebArchive)就是zip文件,EAR(EJBArchive)类似

第3章 Servlet技术

4.  Get方式缺点地址显示在浏览器地址栏,长度不得超过256字符

5.  Post Get 最常用其他PUT、HEAD、TRACE、DELETE、OPTIONS基本不用

6.  编写Servlet直接继承HttpServlet并覆盖doPost()  和doGet() 方法即可

7.  执行doGet前会先执行getLastModified()如果返回值与上次相同则,浏览器采用缓存,若返回-1,则认为总是最新的。

8.  Tomcat 调试时,是热部署的,后台代码修改后可不用重新部署

9.  Servlet 配置:

可以用注解@WebServlet配置Servlet映射,如:

@WebServlet("/ThreadSafetyServlet")

publicclassThreadSafetyServletextendsHttpServlet

或在web.xml中加入以下代码:

<servlet>

      <servlet-name>FirstServlet</servlet-name>

      <servlet-class>com.bit.FirstServlet</servlet-class>

   </servlet>

   <servlet-mapping>

      <servlet-name>FirstServlet</servlet-name>

      <url-pattern>/FirstServlet</url-pattern>

</servlet-mapping>

10. servlet的url-pattern匹配规则

匹配顺序:

1.精确匹配:<url-pattern>中配置的项必须与url完全精确匹配。

2. 路径匹配(以“/”字符开头,并以“/*”结尾的字符串用于路径匹配):先最长路径匹配,再最短路径匹配

3.扩展名匹配:以“*.”开头的字符串被用于扩展名匹配

<servlet-mapping>

<servlet-name>MyServlet</servlet-name>

<url-pattern>*.jsp</url-pattern>

</servlet-mapping>

4 缺省匹配:匹配所有以上没有匹配的

<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

路径匹配和扩展名匹配无法同时设置:匹配方法只有三种,要么是路径匹配(以“/”字符开头,并以“/*”结尾),要么是扩展名匹配(以“*.”开头),要么是精确匹配,三种匹配方法不能进行组合,不要想当然使用通配符或正则规则。

  如<url-pattern>/user/*.action</url-pattern>是非法的

  另外注意:<url-pattern>/aa/*/bb</url-pattern>是精确匹配,合法,这里的*不是通配的含义

11. PrintWriterout=response.getWriter();//只能写字符型数据

在客户端写二进制数据需要使用response(HttpServletResponse)的getOutPutStream().方法,返回ServletOutputStream对象

12. jsp文件开头path,basePath作用:

String path =request.getContextPath();
// 获得项目完全路径(假设你的项目叫MyApp,那么获得到的地址就是http://localhost:8080/MyApp/):

String basePath =request.getScheme() + "://" + request.getServerName() + ":"+ request.getServerPort() + path+"/";

<basehref=" <%=basePath%>"><!-- base需要放到head中 -->
// 设置了<base>后,jsp中的相对路径,相对于的就是base中的路径,而不再是浏览器地址的请求路径啦~~~,可解决因forward产生的路径问题

13. Servlet配置初始化参数init-param (仅此Servlet内可访问)

<servlet>

<servlet-name>InitParamServlet</servlet-name>

<servlet-class>com.czf.WebProject2.InitParamServlet</servlet-class>

<init-param>

   <param-name>helloween</param-name>

   <param-value>password</param-value>

</servlet>

可通过getInitParameter(“helloween”)获取参数值或getInitParameterNames()返回所有参数名称。也可通过ServletConfig访问:ServletConfigconfig=getServletConfig();

Enumeration<String>params=config.getInitParameterNames();

14. Java Web 应用程序下 WEB-INF 文件夹不能通过浏览器直接获取下面的文件。

15. doPost中返回 WEB-INF 文件夹的资源:

request.getRequestDispatcher("/WEB-INF/notice.html" ).forward( request,response);//Forward转向

16. context-param上下文参数所有Servlet可访问:

ServletContextcontext=this.getServletConfig().getServletContext();

String pValue=context.getInitParameter("upload folder");

Enumeration<String>paramNames=context.getInitParameterNames();

17. 资源注射@Resource

Web.xml 配置:

<env-entry>

   <env-entry-name>hello</env-entry-name>

   <env-entry-type>java.lang.String</env-entry-type>

<env-entry-value>Hello,Welcome to czf's World!!!</env-entry-value>

</env-entry>

env-entry-type元素的值必须是如下之一:

java.lang.String      java.lang.Boolean     java.lang.Byte

java.lang.Character   java.lang.Short    java.lang.Integer

java.lang.Long     java.lang.Float    java.lang.Double

使用方法private@Resource(name="hello") String hello;

18. JNDI(Java Naming and Directory Interface,Java命名和目录接口。它是一个为Java应用程序提供命名服务的应用程序接口,为我们提供了查找和访问各种命名和目录服务的通用统一的接口.通过JNDI统一接口我们可以来访问各种不同类型的服务.如我们可以通过JNDI API来访问DNS。

JNDI在满足了数据源配置,JNDI避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。示例xml配置如下:

<datasources>

<local-tx-datasource>

<jndi-name>MySqlDS</jndi-name>

<connection-url>jdbc:mysql://localhost:3306/lw</connection-url>

<driver-class>com.mysql.jdbc.Driver</driver-class>

<user-name>root</user-name>

<password>rootpassword</password>

</local-tx-datasource>

</datasources>

使用方法:Context ctx=new InitialContext(); 

 Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用数据源  

  DataSource ds=(Datasource)datasourceRef; 

  conn=ds.getConnection();  

  ......  /* 使用conn进行数据库SQL操作 */ 

  c.close();  

19. tomcat服务器配置字符集为utf-8-彻底解决中文乱码问题:服务器/conf目录/server.xml文件,将相关语句改为:

<Connector port="8008" protocol ="HTTP/1.1"  connectionTimeout = "20000" redirectPort = "8443"  URIEncoding= "UTF-8"/>

20. optgroup可分组option:不可被选中

<selectname="area">

                <optgrouplabel="北京市">

                   <optionvalue="北京市海淀区">海淀区</option>

                   <optionvalue="北京市朝阳区">朝阳区</option>

                </optgroup>

                <optgrouplabel="山东省">

                   <optionvalue="山东省济南市">济南市</option>                              </optgroup>

            </select>

21. DateFormat format= newSimpDateFormat(“yyyy-MM-dd”);

Date birthday=format.parse(“……”)解析日期。format.format(birthday) 格式化日期

22. String[]interest=request.getParameterValues(“interest”);获取前台传递的数组

23. 上传文件时<form >标签需要将enctype属性设置为mutipart/form-data用二进制传递数据。否则enctype默认为application/x-www-form-urlencoded,默认采用ASCII码向服务器传递数据,传文件会失败。

24. @SuppressWarnings(“unchecked”)//消除警告

25. 带进度条的上传工作原理,后台将传输信息放入Session,前台用Ajax技术新开一个单独线程读取Session获取上传进度信息。

26. 保存对象到 Session后,保存的是引用,修改对象字段,Session中的值会变。多Servlet可共享修改Session中的对象。

27. 禁止浏览器缓存

      response.setHeader("Cache-Control", "no-store");

      response.setHeader("Pragma","no-cache");

response.setDateHeader("Expires", 0);

28. 不使用框架的Ajax

         varreq= createRequest();

         req.open("Get", "servlet/ProgressUploadServlet");

         req.onreadystatechange= function() {

            callback(req);

         };

         req.send();

      function createRequest() {

         if (window.XMLHttpRequest) {

            return new XMLHttpRequest();

         } else {

            try {

                return new ActiveXObject("Msxml2.XMLHTTP");

            } catch (e) {

                return new ActiveObject("Microsoft.XMLHTTP");

            }

         }

         return null;

      }

      function callback(req) {

         if (req.readyState== 4) {

            if (req.status== 200){

                debug("status.jsp返回值:" + req.responseText);

            }else{//发生错误.}

         }

      }

29. Servlet生命周期CGI程序,用户每一次请求都开辟单独进程。而Servlet中每个Servlet只有一个实例,多客户端请求使用多个线程执行service()方法。Init与destroy方法均只执行一次。

30. Servlet不是线程安全的,尽量不要给Servlet定义属性。可使用 synchronized ( name ) { }语句块可以解决问题,但是会造成线程等待

31. 可在web.xml中设置<web-app>的metadata-complete属性为true 来关掉服务器启动时例行的注解检查(注解影响服务器启动速度,服务器会检查WEB-INF/class下和WEB-INF/lib 下所有类是否使用了注解)

32. 带@PostContruct和@PreDestroy注解的Servlet生命周期

加载ServletàServlet构造函数à @PostContruct修饰的方法àinit方法à service方法à destroy方法à @PreDestroy修饰的方法à服务器卸载Servlet

33. MVC模式简介:MVC是一种架构型模式,是用来指导我们改善应用程序的架构,使得应用的模型和视图相分离,从而达到更好的开发和维护效率。MVC模式的这三个部分的职责非常明确,而且相互分离,每个部分都可以独立的改变而不影响其他部分,大大提高了应用的灵活性和重用性。

在MVC模式中,应用程序被划分成模型(Model)、视图(View)和控制器(Controller)三个部分。其中,模型部分包含了应用程序的业务逻辑和业务数据;视图部分封装了应用程序的输出形式(页面、界面);而控制器部分负责协调模型和视图,根据用户请求来选择要调用哪个模型来处理业务,以及最终由哪个视图为用户做出应答。

34. Forward转向(在服务器转向,对客户端不透明,地址栏地址不会改变):

RequestDispatcher dispatcher= request.getRequestDispatcher(“/servlet/LifeCycleServlet”);

Dispatcher.forward(request,response);

Forward支持跳转到另一个Servlet、jsp页面、文件(WEB-INF下的也可以)。

35. Redirect转向:在客户端实现,客户端请求2次,第一次获取网址,第二次访问真实地址。

使用:response.sendRedirect(request.getContextPath()+“/download/setup.exe”);

sendRedirect参数中的中文必须编码:

String filename="/attachment/"+URLEncoder.encode("企业QQ.exe", "UTF-8");

response.sendRedirect(request.getContextPath() +filename);

36. Jspimport:<jsp:directive.pageimport="java.text.SimpleDateFormat"/>

37. HttpServletResponse状态码

1**:信息码。请求已接收,正在处理2**:正确状态码。如200:一切正常

3**:重定向。301永久重定向302临时重定向

4**:请求错误。 401没有权限404资源不存在405访问方式错误(get,post)

5**:服务器错误。500程序异常终止

38. Servlet自动刷新:

response.setHeader("Refresh","3;URL=http://localhost:8080/servlet/example.htm");

时间单位为,若URL为本页面地址,即可自动刷新

第4章 深入JSP技术

39. JSP(Java ServerPage)为了简化Servlet的工作而出现,也是一种Servlet,html与java代码并存,需要编译。Servlet先编译后部署,Jsp先部署,后编译。

40. Jsp中的java代码(Jsp脚本)<%  %>,jsp中输出变量值<%= a  %>也可用<% out.println(a); %>

41. Jsp工作原理:客户端第一次请求greeting.jsp时,Tomcat先将greeting.jsp 转化为java源代码greeting_jsp.java,存放在tomcat工作目录,并将.java文件编译为.class文件,若jsp文件没有改动,后续请求无需重新编译。

42.Jsp 初始化与销毁方法:<%!

   publicvoid _jspInit(){   }

   publicvoid _jspDestroy(){   }

%>

43. Jsp注释:<%-- 此处是注释  --%>

Html注释:<!-- 此处是注释   -->

44. Jsp 申明方法与全局变量需放在<%!  %>之间

45. Jsp导入包<%@pageimport="com.helloweenvsfei.util.ip.IPSeeker"%>

46. Jsp中 java代码可与 html交叉使用:

   <%    if (isValidIp(ip)) {  %>

   <table>  <tr>        <td>ip=<%=ip%></td>      </tr></table>

   <% }%>

47. Jsp 中的return语句会忽略后面的所有语句(包括Java代码和HTML代码),直接返回页面,结束输出。

48. Jsp指令格式<%@ %>例如page指令

<%@pagelanguage="java"contentType="text/html;charset=utf-8"%>

page 指令中除了 import属性可多次出现,其他属性只能出现一次,但是可以写在多个指令里面:

<%@pageimport="java.util.*" %>import可引入多个类,逗号隔开

page指令其他属性:

属性

取值

描述

session

true false

默认true,是否内置Session对象

autoFlush

true false

是否运行缓存。默认true

buffer

none 或数字kb

缓存大小。autoFlush为true时有效

contentType

有效文档类型

HTML格式为 text/html

纯文本text/plain

JPG图像image/jpeg 等

49. include 指令:<%@includefile="head.jsp"%>用于实现Jsp页面的区块化,可使用 if语句动态引入某个文件。

50. include指令与include行为区别

include行为:<jsp:includepage=”relativeURI” />

include 指令先包含,后编译;include行为先运行再包含,将执行结果包含当前页。include 行为使用 request.getResponseDispatcher(“relativeURI”) .forward (request,response);来执行被包含的文件

51. 标签库指令 taglib:uri 库地址prefix前缀

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

52. Java Bean (POJO,PlainOrdinary Java Object普通Java对象)就是普通Java类,只有私有变量与getter和setter方法。JavaBean行为:

<jsp:useBean id="person"class="com.helloweenvsfei.jspweb.bean.Person" scope=”page” ></jsp:useBean><%--useBean行为中id为变量名称,scope为变量作用范围,默认page,还可以为request、session、application范围依次增大--%>

<jsp:setPropertyproperty="*"name="person"/><%-- 设置person所有属性,*表示所有属性。自动从request中取得属性值--%>

<jsp:getPropertyproperty="name"name="person"/><%-- 输出属性值--%>

53. <jsp:plugin/>行为嵌入 Applet

<jsp:plugincode="Graph.class"codebase="applets/GraphLayout/"type="applet"width="500"height="400">

         <jsp:params>               

                   <jsp:paramname="center"value="joe"/>

                </jsp:params>

<jsp:fallback>您的浏览器不支持 Java Applet</jsp:fallback>

   </jsp:plugin>

54. <jsp:forward />行为:相当于Servlet中的 forward方法,地址栏地址不变

<jsp:forwardpage="useBean.jsp">

   <jsp:paramvalue="value1"name="param1"/>

</jsp:forward>

55. <jsp:directive />行为相当于 JSP指令:例如<jsp:directive.page />相当于<%@ page %>指令,<jsp:directive.include />相当于<%@ include %>指令

56. ★★★JSP隐藏对象:9个

out输出流对象:(javax.servlet.jsp.JspWriter)服务器向客户端输出字符内容。常用方法append、println、clear、flush

request请求对象:(javax.servlet.ServletRequest)封装客户端请求信息

response响应对象:(javax.servlet.ServletResponse)

config配置对象:(javax.servlet.ServletConfig)可读取web.xml中的初始化JSP参数。常用方法getInitParameter、getServletContext()

session会话对象:(javax.servlet.http.HttpSession),记录客户端访问信息,每个用户对应一个session对象。常用方法getId、getAttribute……

application应用程序对象(javax.servlet.ServletContext):整个应用程序对应一个application对象,封装了JSP所在Web应用程序的信息,例如web.xml中的全局初始化信息。常用方法getAttribute、getRealPath、getInitParameter

page页面对象:(javax.servlet.jsp.HttpJspPage)指向当前JSP页面本身,有点像类中的this指针,常用方法getClass()、hashCode()等

pageContext页面上下文对象(javax.servlet.jsp.PageContext)能够获取JSP页面中的资源,常用方法 forward(String url)、getAttribute、getOut()……

exception异常对象(java.lang.Exception)封装了JSP中抛出的异常信息。错误处理页面error.jsp需要设置<%@ pageisErrorPage=”true” %>才可使用exception。在普通页面中设置<%@ page errorPage=”error.jsp” %>如果出错就会forward到error.jsp页面

57. Jsp配置:类似Servlet配置,只是Servlet使用<servlet-class>标签,而JSP使用<jsp-file>标签:

<servlet>

      <servlet-name>FirstServlet</servlet-name>

      <servlet-file>/FirstServlet.jsp</servlet-file>

   </servlet>

   <servlet-mapping>

      <servlet-name>FirstServlet</servlet-name>

      <url-pattern>/FirstServlet</url-pattern>

</servlet-mapping>

<jsp-config><!—支持对JSP的批量配置 -->

<taglib>

<taglib-uri>taglib</taglib-uri>

<taglib-location>/WEB-INF/tlds/taglib.tld</taglib-location>

</taglib>

<jsp-propery-group>

<url-pattern>/news/*.jsp</url-pattern><!—-适用/news下所有jsp文件 -->

<el-ignored>true</el-ignored><!--是否忽略EL表达式。默认false -->

<page-encoding>UTF-8</page-encoding>

<scripting-invalid>true</scipting-invalid><!--  是否忽略jsp脚本。默认false -->

<include-prelude>/head.jspf</include-prelude>

<include-coda>/foot.jspf</include-coda>

</jsp-propery-group>

其中<include-prelude>标签指定了一个执行jsp之前执行的文件,相当于在jsp文件前面包含了该文件。<include-coda>正好相反。.jspf(Java Server Page Fragment)

58. EL表达式:${} 包含的代码,可以写在Jsp的html代码中而不可以在<% %>引起的JSP脚本中。EL表达式可直接从request(先)session(后)中获取对象或属性:

${person} 相当于<%request.getAttribute(“person”) %>或者<% session.getAttribute(“person”) %>

${person.age}相当于<% person.getAge(); %>

多级属性${person.city.province}相当于<%person.getCity().getProvince() %>

EL表达式中的隐藏对象

param

${param.foo},${param[‘foo’]}

foo参数有多个值时:${param.foo[0]}

读取地址栏参数,相当于request.getParameter(“foo”)

initParam

${initParam.encoding}

读取初始化参数,相当于config.getInitParameter(“encoding”)

header

${header.host}${header [‘host’]}

${header.host[0]}

request.getHeader(“host”)

cookie

${cookie.userName}返回Cookie

$(cookie.userName.value)返回cookie值

包含所有cookie的Map

pageScope

<jsp:useBean id=”person class=”com.czf.bean.Person” scope=”page” />声明pageScope范围对象。

${pageScope.person.age}返回该对象age属性

包含page作用域内变量的Map

requestScope

……

……

sessionScope

……

……

applicationScope

……

……

pageContext

${pageContext.request.remoteAddr}相当于<% pageContext.getRequest().getRemoteAddr() %>

包含页面内所有变量的Map,包含request,response,等所有隐藏对象

EL表达式运算:

加、减、乘、除(/或者 div)、余(%或者mod)、三目运算(exp?val1:val2)

大于(>或者gt)、小于(<或者lt)、等于(==或者eq )、不等于(!=、nq)、大于等于(>=、ge)、小于等于(<=  le)

逻辑且(&&或者 and)、或(||或者or )、非(!或者 not)

empty判断是否为空:

${emptyparam.paramA} <!-- 提交的参数是否为空或个数为0 -->

第5章 会话跟踪

59. 原因:HTTP协议是无状态协议,一旦数据交换完毕,连接会关闭,因此需要会话跟踪。常用会话跟踪技术:客户端Cookie、服务器端Session

60. 浏览器地址栏输入:javascript:alert(document.cookie)可显示cookie

61. request.getCookies()获取所有客户端提交的Cookie(返回Cookie[])

response.addCookie(Cookie cookie)向客户端设置Cookie

62. Cookie不可跨域名性:Cookie由浏览器管理,域名不同,Cookie不能相互操作

63. Cookie只支持ASCII,保存中文必须编码,否则报错:引入java.net.*;包

Cookie cookie = new Cookie(URLEncoder.encode("姓名", "UTF-8"), URLEncoder.encode("刘京华", "UTF-8"));

String cookieName = URLDecoder.decode(cookie.getName(), "UTF-8");

对应js里面的encodeURIComponentdecodeURIComponent两个函数,可以js加码,java解码,或者java加码,js解码。

64. escape/unescape:不编码+/@-*._输出ASCII表示法(%XX)或者Unicode(%uXXXX)

encodeURI/decodeURI不编码+/@-*._'(),?:&=$#输出ASCII表示法(%XX)

encodeURIComponent/decodeURIComponent:不编码-*._'()输出(%XX)

document.write(escape("+/@-*._'(),?:&=$# 陈志福"));

document.write(encodeURI("+/@-*._'(),?:&=$#陈志福"));  

document.write(encodeURIComponent("+/@-*._'(),?:&=$# 陈志福"));

+/@-*._%27%28%29%2C%3F%3A%26%3D%24%23%20%u9648%u5FD7%u798F
+/@-*._'(),?:&=$#%20%E9%99%88%E5%BF%97%E7%A6%8F
%2B%2F%40-*._'()%2C%3F%3A%26%3D%24%23%20%E9%99%88%E5%BF%97%E7%A6%8F

65. BASE64编码:保存二进制图片

<jsp:directive.pageimport="sun.misc.BASE64Encoder" />

<jsp:directive.pageimport="java.io.*"/>

<% Filefile = new File(this.getServletContext().getRealPath("cookie.gif"));

   byte[] binary = newbyte[(int) file.length()];// 二进制数组

InputStream ins = this.getServletContext().getResourceAsStream(file.getName());

   ins.read(binary);ins.close(); 

   Stringcontent = BASE64Encoder.class.newInstance().encode(binary).replaceAll("\r\n", "");

Cookie cookie = new Cookie("file", content); //包含二进制数据的 Cookie

response.addCookie(cookie);%>

读取图片<imgsrc="base64_decode.jsp"/>

base64_decode.jsp返回图片

<% out.clear();// 清除输出

   for (Cookie cookie :request.getCookies()) {

      if (cookie.getName().equals("file")) {

byte[] binary = BASE64Decoder.class.newInstance().decodeBuffer(cookie.getValue().replace(" ", ""));// Cookie 中取二进制数据

response.setHeader("Content-Type", "image/gif");// 设内容类型为 gif 图片

   response.setHeader("Content-Disposition", "inline;filename=cookie.gif");

   response.setHeader("Connection", "close");       

   response.setContentLength(binary.length); // 设置长度      

ServletOutputStreamsos =response.getOutputStream();// 输出到客户端

sos.write(binary); sos.flush(); sos.close(); return;  }  }%>

66. CookiemaxAge属性:maxAge失效时间,单位s,-1表示关闭浏览器失效,0表示删除该Cookie

Cookie path属性:该Cookie的使用路径,必须以“/”结尾。“/sessionWeb/”表示只有contextPath为“/sessionWeb”的程序可以访问该cookie。“/”表示本域名下所有contextPath都可以访问该cookie

Cookiedomain属性:可以访问该cookie的域名。若需要www.alfred.com和image.alfred.com都需要访问某Cookie,则其domain属性可设置成“alfred.com”,前面不能有点号“.”

Cookie secure属性:不对Cookie内容加密,设置为true,则浏览器只会在HTTPS和SSL等安全协议中传输此类COOKIE

67. jsfunction中可通过arguments动态获取多参数

   function setCookie(name, value){

         varexpires= (arguments.length>2) ? arguments[2] : null;

}

68. Java取MD5:<jsp:directive.pageimport="java.security.MessageDigest"/>

byte[] strBytes = str.getBytes();

MessageDigest md5 = MessageDigest.getInstance("MD5");

mdTemp.update(strBytes);

StringBuildersb = newStringBuilder();

for (byteb :md5.digest()) {

sb.append(String.format("%02x", b)); //x表示以十六进制,02 两位前面补

}

return sb.toString();

69. Session存储在服务器内存,因此Session信息应精简。只有访问JSP/Servlet等程序时才会创建Session,访问html/image等静态资源不会创建Session

70. Session失效时间设置(Tomcat默认30分钟):

1.web容器中设置(以tomcat为例)
在tomcat-7.0\conf\web.xml中设置,以下是tomcat7.0中默认配置:

<session-config>

<session-timeout>30</session-timeout><!--时间单位为分钟-->

</session-config>

tomcat默认为30分钟超时,可以根据需要修改,负数或0为不限制session失效时间

2.在工程的web.xml中设置代码同上

3.通过java代码设置
session.setMaxInactiveInterval(30*60);//以秒为单位,即在没有活动30分钟后,session将失效

三种方式优先等级1 < 2 < 3

71. 监听器监听Session失效:

publicclassOnlineUserListenerimplementsHttpSessionListener{

publicvoidsessionCreated(HttpSessionEvent event){

HttpSession session=event.getSession();

         Stringid=session.getId()+session.getCreationTime();

SummerConstant.UserMap.put(id,Boolean.TRUE);//添加用户

   }

publicvoidsessionDestroyed(HttpSessionEvent event){

HttpSession session=event.getSession();

         Stringid=session.getId()+session.getCreationTime();

synchronized(this){

SummerConstant.USERNum--;//用户数减-

SummerConstant.UserMap.remove(id);//从用户组中移除掉,用户组为一个map

       }

   }

 }

把这个监听器在web.xml中声明就可以了

<listener>

<listener-class>com.demo.OnlineUserListener</listener-class>

</listener>

72. session.invalidate()直接使Session失效。

URL地址重写:Session要求浏览器支持Cookie,用一个JSESSIONID的Cookie识别是否是同一用户,若浏览器不支持Cookie则需要URL地址重写(将SessionID写入地址)。

<ahref="<%=response.encodeURL("index.jsp?c=1&wd=Java")%>">Homepage</a>

该方法会自动判断客户端是否支持cookie(看请求是否携带了Cookie),若支持url不变,否则带上JSESSIONID

<a href = "index.jsp;jsessionid=9E63……E404?c=1&amp;wd=Java">Homepage</a>

response.sendRedirect(response.encodeRedirectURL("index.jsp?c=1"));也类似

73. 禁止在Session中使用Cookie(JSESSIONID)作为识别标示(其他Cookie仍可以使用):在/META-INF/context.xml 加入

<Context path="/sessionWeb" cookies="false"></Context>

或修改全局tomcat中conf/context.xml:<Contextcookies="false"></Context>

74. ★★★会话跟踪COOKIE与SESSION比较

 

COOKIE

SESSION

存取方式

只能保存ASCII,中文或二进制数据需要编码

可以保存Java对象

隐私安全

在客户端,有泄漏信息风险,敏感信息需加密

Session在服务器,可以保存隐私数据

有效期

长期(永久有效)

不能实现永久有效

服务器负担

不占服务器资源,Google,Baidu等并发量极高的网站采用

并发大时,消耗大量内存

浏览器支持

1.必须浏览器支持

2.maxAge设为-1,则只在本浏览器窗口及子窗口有效,设为大于0的值,所有浏览器窗口有效

1.需浏览器支持COOKIE,如果不支持可用URL地址重写

2.只在本浏览器窗口及子窗口有效

跨域名

domain设置为alfred.com则以"alfred.com"结尾的域名都可访问

不支持

第6章 过滤器Filter

75. Servlet两个高级特性:过滤器Filter、监听器Listener

76. Filter处理过程如图6.1所示、FilterChain 滤镜链。Filter像是客户端浏览器与服务器Servlet之间的一层滤网,无论进出都会进过所有Filter

77. Filter必须实现javax.servlet.Filter接口,3个方法init(FilterConfig config);//web程序启动时调用此方法,初始化Filter,例如可读取初始化参数:config.getInitParameter("encoding");

doFilter(ServletRequestrequest,ServletResponse response,FilterChain chain)

客户请求服务器时调用,实现此方法时,必须用chain.doFilter(request,response)将请求传给下个Filter或Servlet

destroy();//web程序关闭时调用此方法,销毁资源

init()方法和destory()方法只会被调用一次

78. Filter配置:

   <filter>

      <filter-name>cacheFilter</filter-name>

      <filter-class>com.helloweenvsfei.cache.CacheFilter</filter-class>

<init-param><param-name>cache</param-name><param-value>true</param-value></init-param>  

</filter>

<filter-mapping>

      <filter-name>cacheFilter</filter-name>

      <url-pattern>*.jsp</url-pattern>    

      <dispatcher>REQUEST</dispatcher>

</filter-mapping>

<dispatcher>默认REQUEST,配置到达Servlet的方式:

REQUEST:仅当直接请求Servlet时才生效

FORWORD:forward到达该Servlet时才生效

INCLUDE:通过<jsp:include />请求到达Servlet时才生效

ERROR:JSP中通过<% page errorPage="error.jsp" %>指定错误处理页面,才生效

<url-pattern>与<dispatcher>是“且”的关系,都满足条件时,该Filter才生效

79. 多个Filter执行的顺序与<filter-mapping>定义的顺序对应。

80. Filter应用场景

权限验证(防盗链/登录验证):

字符编码:统一UTF-8编码

日志记录/异常捕获:

内容替换:继承HttpServletResponseWrapper类,覆盖getWriter()方法使过滤链后面的输出都输出到 CharArrayWriter对象中,缓存后替换输出。

数据压缩(GZiP压缩网页):文本数据压缩较好,二进制压缩效果相对差一些,图片基本无区别。减少网络流量,但增加服务器压力

数据加密:

格式转换(XML->HTML):使用xsl样式文件转换

图像处理(水印):

缓存Filter:处理Get请求,减少数据库访问

81. instanceof判断对象是否是某个类的实例

82. 获取根异常信息:Exception e

Throwable rootCause = e;

while (rootCause.getCause() != null) {

   rootCause = rootCause.getCause();

}

String message =rootCause.getMessage();

83. Java读取properties文件:Properties pp=new Properties();

pp.load(new FileInputStream(realPath));

properties文件需要Unicode编码。

84. import java.awt.*;       import java.io.*;

importjavax.imageio.ImageIO;   importjavax.swing.ImageIcon;

import com.sun.image.codec.jpeg.*;

byte[] 转 Image:

byte[] imageData;

Image image = new ImageIcon(imageData).getImage();

读取文件到 Image

String waterMarkFile;

Image waterMark = ImageIO.read(new File(waterMarkFile));

85. Filter是AOP(Aspect Orainted Programming,面向切面编程)编程思想的一种体现。

第7章 监听器 Listener

86. Listener主要用于对Session、REQUEST、context等进行监控,当它们改变时触发相应事件。

87. 使用Listener需实现相应Listener接口,例如HttpSessionListener接口等。web.xml配置:<listener><listener-class>CListener</listener-class></listener>

88. Servlet2.5中的8种Listener:

Ø  监听对象创建与销毁:

HttpSessionListener(收集在线者信息)

ServletContextListener(监听服务器启动退出,可在启动时读web.xml配置)

ServletRequestListener(监听REQUEST的创建与销毁,HTML多图片,会触发多次request事件)

Ø  监听对象的属性变化:

HttpSessionAttributeListener

ServletContextAttributeListener

ServletRequestAttributeListener

Ø  监听Session内的对象(实现这两个接口的JavaBean类自身会被监控):

HttpSessionBindingListener(当实现该接口的对象被放入Session或从session中移除时执行相应事件)

HttpSessionActivationListener(服务器关闭时,session中实现该接口的对象保存到硬盘【钝化】,服务器重启时,者从硬盘读取Session【活化】)

89. Listener应用场景:统计在线人数单态登录等。

第8章 JSTL标签库

90. JSP中推荐使用JSTL(JavaStandardTagLibrary)而不推荐 Scriptlet<%  %>因JSTL可读性可维护性好,可重复利用。

91. core标签库

<%@tagliburi="http://java.sun.com/jsp/jstl/core"prefix="c"%>

<c:out />

<c:outvalue="${ param.action }" default="No parameter" escapeXml="true"></c:out>

value属性的值不存在时,输出default属性的值,escapeXML属性为true时,对&、<、>等字符进行XML编码

<c:if ></c:if>

<c:iftest="${ param.action == 'add' }"><legend>添加操作</legend></c:if>test条件为true(boolean类型true,或者字符串true[不分大小写])时才输出里面的内容

<c:choose />

<c:when />

<c:otherwise />

实现 if else 功能:<c:choose>

<c:whentest="${ param.action }">when 标签</c:when>

<c:otherwise>otherwise 标签</c:otherwise>

</c:choose>

<c:forEach />

两种用法→

<c:forEachvar="num"begin="2"end="100"step="2" >

   <div>${ num }</div>

</c:forEach>

<c:forEachvar="item"items="${ header }"varStatus="varStatus">

      <trbgcolor="${ varStatus.index % 2 == 1 ? '#EFEFEF' : '#FFFFFF' }">   <td>${ item.key }</td>

         <td>${ item.value }</td>    </tr>

   </c:forEach>

varStatus属性:

index

当前第几个 0开始

count

已经遍历了几个对象 1开始

current

当前遍历对象

first、last

当前对象是否是第一个(最后一个)对象

begin、end、step

返回forEach的相应属性

<c:forTokens />

用法类似于<c:forEach />,items属性为字符串,被delims属性作为分隔符分割成多个字符串,然后作为遍历集合

<c:set />

<c:setvar="count"value="${ count + 1 }"scope="session"></c:set>等价于

<c:setvar="count"scope="session">${ count + 1 }</c:set>

scope 可以为 page(默认),request,session,application

targetproperty结合起来操作JavaBeantarget只能修改不能创建,如果为null会报异常。

targetvar不能同时使用

<% request.setAttribute("map", newjava.util.HashMap()); %>

<c:settarget="${ map }"property="name"value="${ param.name }"/>

   ${ map.name }

<c:remove />

<c:removevar="somemap"scope="session" />删除属性,如果va不存在不报异常

<c:catch />

捕获异常

<c:catchvar ="catchException">

   <% int x = 5/0;%></c:catch> 

<c:if test = "${catchException != null}">

 <p>The exception is :${catchException}<br />

 There is an exception: ${catchException.message}</p>

</c:if>

<c:import />导入网络资源

<c:importurl="http://www.baidu.com"charEncoding="utf-8" scope="request"></c:import>直接显示网页

<c:importvar="baidu"url="http://www.baidu.com"charEncoding="utf-8"></c:import>Baidu 的源代码为:

<c:outvalue="${ baidu }"escapeXml="true" />

<c:url />重写URL以支持COOKIE

作用类似response.encodeURL()方法

<c:urlvalue="/images/bg.gif"></c:url>

有var变量时存储到变量里

<c:redirect />

<c:redirecturl="http://www.baidu.com">

<c:paramname="cl"value="3"></c:param></c:redirect>

<c:param />

用于<c:import />或<c:redirect />标签里面,传递参数

92. fmt标签库:

<%@tagliburi="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<fmt:requestEncoding />

<fmt:requestEncodingvalue="UTF-8"/>相当于request.setCharacterEncoding方法

<fmt:setLocale />

设置本地化信息,输出应使用JSTL标签而不是EL表达式,使用JSTL时,会根据Locale信息编码,而EL不会

<fmt:timeZone />

<fmt:timeZonevalue="Asia/Shanghai">生效区域

</fmt:timeZone><!-- 只在标签内部生效-->

<fmt:setTimeZone />

设置时区,可设置生效范围

<fmt:bundle />、<fmt:message />、<fmt:param />

实现资源国际化,只在<fmt:bundle />标签内部生效

<fmt:setBundle />

实现资源国际化,可设置生效范围

<fmt:formatNumber />

显示不同地区的各种数据格式,相当于java.text.NumberFormat类的format方法

<fmt:parseNumber />

解析数字

<fmt:parseNumbervalue="1,000"parseLocale="de"></fmt:parseNumber><br/>德语里为1

<fmt:formatDate />

格式化日期,相当于Java的DateFormat的format方法

<fmt:parseDate />

解析日期

<fmt:parseDatevar="date"value="2008-12-12 08:00:00"pattern="yyyy-MM-dd HH:mm:ss"parseLocale="ja"></fmt:parseDate>

93. fn方法库:字符串查找,截取类方法,在EL表达式内使用:

<%@tagliburi="http://java.sun.com/jsp/jstl/functions"prefix="fn"%>

fn:contains

您使用<c:iftest="${ fn:contains(header['User-Agent'], 'MSIE') }">IE 浏览器</c:if>

fn:containsIgnoreCase

 

fn:endsWith

判断字符串是否以指定参数结尾

<c:iftest="${ fn:endsWith(file.name, '.jpg') }">JPG 图片</c:if>

fn:startsWith

……

fn:excapeXml

对XML、HTML编码

fn:indexOf

${ fn:indexOf('filename.txt', '.') }  输出8

fn:split

<c:setvalue="${ fn:split(header['accept'], ',') }"var="names"/>names为字符串数组

fn:join

fn:joinn(String [] array,String seperator)àString

fn:length()

返回int,相当于

★★Stringlength()方法或

String[]length属性或

Collection类的size()方法

94. sql标签库

<%@tagliburi="http://java.sun.com/jsp/jstl/sql"prefix="sql"%>

<sql:setDataSource />

<sql:setDataSourcedriver= "com.mysql.jdbc.Driver"user="root" password ="123" url="jdbc:mysql://localhost:3306/jstl? charachterEncoding=UTF-8"   var="dataSource"scope="page"/>

<sql:setDataSourcedataSource="jdbc/jstl2" var="serverDataSource"/><!-- JNDI配置 -->

<sql:query />

查询表数据相当于 Steatement的executeQuery()方法,返回值相当于Java里的ResultSet

<sql:queryvar="rs"dataSource="${ dataSource }" sql="select * from tb_corporation"></sql:query>

<c:forEachvar="row"items="${ rs.rows }"><tr><td>${ row['id'] }</td><td>${ row['name'] }</td>   </tr></c:forEach>

<sql:update />

<sql:updatevar="result"dataSource="${ dataSource }">

   insert into tb_corporation ( name, description ) values ('IBM', '国际商用机器') </sql:update>

INSERT, 影响到的数据条数:${ result } <br/>

<sql:transaction />

<sql:transactiondataSource="${ dataSource }"></sql:transaction>里面的多个<sql:update />为一个事务

95. xml标签库

<%@tagliburi="http://java.sun.com/jsp/jstl/xml"prefix="x"%>

<x:parse />

<x:parsevar="content">

<studentdescrip="Software Engineer">                    <name>Helloween</name>   <age>20</age>

</student>

</x:parse>或者:

<c:importvar="file"url="/sina.xml"charEncoding="UTF-8"/>

<x:parsevar="doc"doc="${ file }"></x:parse>

<x:out />

Desc: <x:outselect="$content/student/@descrip"/> 

Name: <x:outselect="$content/student/name"/>

<x:forEach />

<x:forEachvar="node"select="$doc/rss/channel/item"varStatus="status">   ${ status.count }.    <ahref="<x:outselect="$node/link"/>"target="_blank"><x:outselect="$node/title"/></a></x:forEach>

<x:if />

<x:ifselect="$doc/Context/@path"var="exists">属性@path存在: <x:outselect="$doc/Context/@path"/>. </x:if>

<c:iftest="${ ! exists }">属性@path不存在</c:if>

<x:choose />

<x:choose>  <x:whenselect="$doc/Context/Resource/@jndi">使用了 JNDI 属性。</x:when>

<x:otherwise>没有使用 JNDI 属性。</x:otherwise></x:choose>

<x:set />

<x:setselect="$doc/Context" var="resource"/>

@path属性为:<x:outselect="$resource/@path" />

<x:transform />

<x:transformdoc="${ data }"xslt="${ template }" result="${ outputResult }"></x:transform> XML转换为HTML

第9章 自定义标签

96. 自定义标签可实现HTML代码封装和重用(如传入对象集合,生成table)。

97. 任何一个标签库都对应一个Java类,该类必须实现Tag接口,或者继承TagSupport类,Tag接口方法执行流程如图 1Tag接口方法执行流程所示。jsp遇到标签时,通过一个tld文件查找该标签的实现类。

98.

错误!文档中没有指定样式的文字。‑1Tag接口方法执行流程


tld文件tag节点配置:

   <tag>    <name>copyright</name>

      <tagclass>com.helloweenvsfei.tags.Copyright</tagclass>

      <bodycontent>JSP</bodycontent>

      <info>Copyright tag.</info></tag>

bodycontent:三种情况:

Ø  empty:不允许标签体

Ø  JSP:允许标签体,可为JSP代码

Ø 

错误!文档中没有指定样式的文字。‑2BodyTag接口的方法执行流程


tagdependent:允许标签体存在,但标签体内的JSP代码不会被执行。

99. 带标签体的自定义标签,实现BodyTag接口,或者继承BodyTagSupport类。BodyTag接口方法执行流程如图 2BodyTag接口的方法执行流程所示:

第10章 资源国际化

100.    native2ascii.exe工具位于JDK的bin目录下,可实现Unicode转ASCII

101.    <fmt:bundle basename="messages">

         <fmt:messagekey="helloworld"></fmt:message>

                                  </fmt:bundle>

message知名文件名称:src目录下的message.properties

如果在src子目录下,可设置为com.czf.i18n.message或者com/czf/i18n/message

102.    在Java程序中可以使用Java自带的ResourceBundle获取资源:

String BUNDLE_NAME ="com.helloweenvsfei.i18n.param";//param.properties路径

ResourceBundleRESOURCE_BUNDLE = ResourceBundle         .getBundle(BUNDLE_NAME);

Stringvalue = RESOURCE_BUNDLE.getString(key);

第11章 数据库概述

103.    mysql命令行登录:数据库名databaseWeb

mysql -h localhost -u root -pdatabaseWeb之后再输入密码,或者

mysql -h localhost -uroot -padmin databaseWeb(root是用户名,admin是密码)--default-character-set=utf8参数可设置登录时的编码方式。

104.    mysql命令以;结束,可以写在多行上

show databases

显示所有数据库

selectdatabase()

显示当前使用的数据库

status

显示服务器状态

show tables

列出表

desc tb_person;

查看表定义

createdatabase dbWeb character set utf8

以 utf-8编码创建数据库

sourcec:\init.sql

或者\.c:\init.sql

执行sql文件,该命令后面不能加分号

第12章 JDBC 详解

105.    JDBC(JavaDatabaseConnectivity)是标准的Java访问数据库API.

106.    JDBC访问数据库:

Connection conn = null;  Statementstmt = null;   ResultSetrs = null;  

   try{

      // 注册 MySQL 驱动. 也可以使用下面两种方式的任一种

      DriverManager.registerDriver(newcom.mysql.jdbc.Driver());

            //Class.forName("com.mysql.jdbc.Driver").newInstance();

     

      // 获取数据库连接。三个参数分别为连接URL,用户名,密码

      conn= DriverManager.getConnection(

                      "jdbc:mysql://localhost:3306/databaseWeb",                   "root",                     "admin");  

      // 获取 Statement Statement 对象用于执行 SQL。相当于控制台。

      stmt= conn.createStatement();   

      // 使用 Statement 执行 SELECT 语句。返回结果集。

      rs= stmt.executeQuery("select * from tb_person");

while (rs.next()) {

                   int id = rs.getInt("id");// 整形类型             

                   Stringname = rs.getString("name"); // 字符串类型

                   Datebirthday = rs.getDate("birthday");// 日期类型,只有日期信息

                   TimestampcreateTime = rs.getTimestamp("create_time");// 时间戳类型,既有日期又有时间。

……

}

}catch(SQLException e){

                      e.printStackTrace();

   }finally{       // 关闭

         if(rs != null)           rs.close();

         if(stmt != null)            stmt.close();

         if(conn != null)            conn.close();

   }

107.    获取ResultSet列名:

intcolumnCount = rs.getMetaData().getColumnCount();

         String[]columns = new String[columnCount];

         for(inti=1;i<=columnCount; i++){

            columns[i-1]= rs.getMetaData().getColumnLabel(i);

         }

108.    常用中文编码方式GB2312、GBK、GB18030、UTF-8,前三种仅能表示中文,编码字符数依次增大,GB18030可编码少数民族语言。UTF-8能够编码任意语言。

109.    设置MySql编码方式:

1.命令行:ALTER DATABASE DB_NAME CHARACTER SET utf8;

ALTER TABLE TABLE_NAMECHARACTER SET utf8;

2.修改配置文件my.ini:

default-character-set=latin1改为default-character-set=utf8

110.    链接URL设置编码:

jdbc:mysql://localhost:3306/dbWeb?unicode=true&characterEncoding=UTF-8

111.    获取自动插入的id:

// 执行 INSERT 语句

         stmt.executeUpdate("insert into tb_person (name, english_name, age,sex, birthday, description) values ('Name', 'English Name', '17', '', current_date(), '') ",Statement.RETURN_GENERATED_KEYS);

         // 获取自动生成的键值

         rs = stmt.getGeneratedKeys();

         rs.next();

         System.out.println("id: " + rs.getInt(1));

112.    使用PreparedStatement(继承自Statement)

String sql = "UPDATE tb_person SETname = ?, age = ?, birthday = ? WHERE id = ? ";

Connection conn =……

PreparedStatementpreStmt =conn.prepareStatement(sql);

         preStmt.setString(1,name);

         preStmt.setInt(2,Integer.parseInt(age));

         preStmt.setDate(3, newDate());

         preStmt.setInt(4,Integer.parseInt(id));      

         int result =preStmt.executeUpdate(sql);          // 使用preStmt执行 SQL 语句

113.    Statement批处理SQL

stmt = conn.createStatement();

         for (inti = 0; i< 5;i++) {

            Stringsql = "insertinto tb_person

( name, english_name,age, sex, birthday, description) values ('Name', 'English Name " +i + "','17', '', current_date(), '') ";

            stmt.addBatch(sql);            // 批量添加

         }

         // 批量执行将每句SQL执行的结果组织成int[] 数组

         int[] result= stmt.executeBatch();

114.    PreparedStatement批处理SQL

preStmt = conn.prepareStatement("insertinto tb_person(name, english_name,age,sex,birthday,description)values(?,?,?,?,?,?)");

         for (inti= 0; i< 5; i++) {

            intindex = 1;

            preStmt.setString(index++, "Name " + i);

            preStmt.setString(index++, "English Name" + i);

            preStmt.setInt(index++, 25);

            preStmt.setString(index++, "男");

            preStmt.setDate(index++, newjava.sql.Date(System                 .currentTimeMillis()));

            preStmt.setString(index++, "");

            // 添加同一条带参数的SQL语句

            preStmt.addBatch();            //addBatch(sql);可以添加普通的完整sql语句

         }

         // 批量执行将每句SQL执行的结果组织成int[] 数组

         int[] result = preStmt.executeBatch();

115.    MySql分页:select * from person limit 21,10

从21行数据开始,选取10行

116.    DAO与JavaBean,DAO(DatabaseAccessObject)是JDBC下常用的模式,保存数据时将JavaBean的属性拆分成正确的SQL语句,并保存到数据库;读取数据时,从数据库去除数据,并通过setter设置到JavaBean中。实现分层:

JSP/Servletà   DAO/JavaBeanà  JDBC  àDatabase

117.    事务:conn为Connection对象。

            conn.setAutoCommit(false); // 将自动提交设置为false          

            stmt= conn.createStatement();         

            int result1 = stmt.executeUpdate(" UPDATE tb_currency SET currency = currency - 200WHERE account = 'A' and currency >= 200 ");

                         int result2 = stmt.executeUpdate(" UPDATE tb_currency SET currency = currency + 200WHERE account = 'B' ");

                         if(result1 == 1 && result2 == 1){

         conn.commit();              // 提交

   out.println("转帐成功,事务提交。<br/>");

            }

            else{

                conn.rollback();               // 回滚

                out.println("转帐失败,事务回滚。<br/>");

            }

118.    MySql数据库BLOB类型用于存储二进制数据,Text用于存储大文本,长度限制都为65526字节,数据过长用LONGBLOB,LONGTEXT。

119.   保存与读取二进制数据:

            PreparedStatement preStmt = conn.prepareStatement("INSERT INTO tb_attachment ( filename, filetype, size, content,ip, date ) values ( ?, ?, ?, ?, ?, ? ) ");

                preStmt.setString(1, filename);                // 文件名称

                preStmt.setString(2, fileItem.getContentType());              // 文件类型            

                preStmt.setInt(3, (int)fileItem.getSize());// 文件长度

                // 文件内容,通过流输入到数据库

                preStmt.setBinaryStream(4,fileItem.getInputStream(), (int)fileItem.getSize());              

                preStmt.executeUpdate();            

读取:

      preStmt = conn.prepareStatement("select* from tb_attachment where id = ? ");

      preStmt.setInt(1, id);

      rs = preStmt.executeQuery();     

      if(rs.next()){

         response.reset();

         response.setContentType(rs.getString("filetype"));

         response.setContentLength(rs.getInt("size"));       

         InputStream ins = null;

         OutputStreamous = null;       

         try{

            ins = rs.getBinaryStream("content");

            ous =response.getOutputStream();          

            byte[] b = newbyte[1024];

            intlen = 0;          

            while((len = ins.read(b)) != -1){

                ous.write(b, 0, len);

            }          

         }finally{

            if(ous != null) ous.close();

            if(ins != null) ins.close();

         }               }

120.    数据源Data Source(连接池DBCP、DatabaseConnectionPool):每次创建、断开数据库连接会产生较大开销,使用数据源技术时,不需要每次都创建连接,而是向数据源申请连接,可减少开销。

121.    TomcatJNDI(Java™ Naming and Directory Interface)数据源配置(Mysql驱动需放到Tomcat的lib下):context.xml中:

<Context>

   <Resourcename="jdbc/databaseWeb" auth="Container"type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"

   maxActive="100"  maxIdle="30"  maxWait="10000"username="root" password="admin"url="jdbc:mysql://localhost:3306/databaseWeb?characterEncoding=utf-8"/>

</Context>

Web程序的web.xml中配置数据源引用:

<web-app……>

   <resource-ref>

      <description>DB Connection</description>

      <res-ref-name>jdbc/databaseWeb</res-ref-name>

      <res-type>javax.sql.DataSource</res-type>

      <res-auth>Container</res-auth>

   </resource-ref>

</web-app>

使用方法方式一:

<sql:queryvar="rs"dataSource="jdbc/databaseWeb">

   select id, name, sex from tb_employee

</sql:query>

<c:forEachvar="row"items="${rs.rows}">

      ${ row['id'] }, ${ row['name'] }, ${ row['sex'] }<br/>

      </c:forEach>

使用方法二:

<%       ContextinitContext = newInitialContext();

         Context envContext = (Context)initContext.lookup("java:/comp/env");      

         DataSource ds = (DataSource)envContext.lookup("jdbc/databaseWeb");

         Connection conn = ds.getConnection();                ……

         conn.close();      %>

第13章 XML概述

122.    XML(Extensible Markup Language)两种写法:

<article>

         <title>XML概述</title>

</article>

<article>

         <property name="title" value="XML概述" />

</article>

123.    XML定义:DTD/Schema(更规范,更流行)

数据解析:DOM(DocumentObject Model)/SAX(Simple API for XML)

样式风格XSLT(eXtensibleStylesheet LanguageTransformation):将XML按照指定样式转换为HTML

124.    XML语法:声明:<?xmlversion="1.0" encoding="UTF-8"?>、XML文档有且只能有一个根元素、大小写敏感、文档中的空白不会被解析器删除、注释<!-- 这是注释 -->、转义字符(<à&lt;、>à&gt;等)、CDATA部件包含的字符不用转义<![CDATA[这里字符if(a>b){alert(a);}不用转义]]>

125.    DOM解析XML(将XML内容加载到内存,生成对应的对象模型),xml文件比较大时,该方法占用内存大,查找速度慢

      FilexmlFile = newFile("F:\\article.xml");

      DocumentBuilderFactorybuilderFactory = DocumentBuilderFactory

            .newInstance();//通过单例模式创建DocumentBuilderFactory对象

      DocumentBuilder       builder = builderFactory.newDocumentBuilder();

         Document document= builder.parse(xmlFile);       //解析文件        

         Elementroot = document.getDocumentElement();// 获得根元素

root.getNodeName();//节点名称

         NodeListnodes = root.getChildNodes();/子节点

nodes[0].getAttributes().getNamedItem("category")                          .getNodeValue();//获取属性

                   nodes[0].getTextContent());//获取节点文本

126.    SAX解析XML(优先选用:根据定义好的事件处理器,决定当前解析的部分,是否有必要记录并存储:

File xmlFile = newFile("F:\\article.xml");   

      SAXParserFactory factory =SAXParserFactory.newInstance();

         SAXParser parser = factory.newSAXParser();       

         parser.parse(xmlFile, newMySaxHandler());         //定义解析时的事件处理

MySaxHandler继承自org.xml.sax.helpers.DefaultHandler;

127.    JAXB(Java Architecturefor XML Binding):XML与Java对象互转:

JavaBean中用@XmlRootElement(name = "articles")标注XML根元素

File xmlFile= new File("F:\\test.xml");

      JAXBContextcontext;      //声明JAXBContext上下文对象

                //通过指定映射的类创建上下文

         context = JAXBContext.newInstance(Article.class);      

         Marshallerm = context.createMarshaller();         //创建java转化xml的对象Marshaller

         Articlearticle = newArticle();

         article.setAuthor("Janet");                 article.setTitle("XML");

         m.marshal(article,xmlFile);         //java对象转化到xml

                         XML转Java:

         Unmarshalleru = context.createUnmarshaller();//通过上下文创建xml转化java的对象Unmarshaller

         Articlearticle2 = (Article)u.unmarshal(xmlFile);

         System.out.println(article2.getAuthor());

         System.out.println(article2.getTitle());

第14章 Struts1.x概述

128.    传统Web应用中,Servlet,Jsp中既有数据库代码,又包括HTML、css等页面代码,还包括复杂的业务逻辑,代码耦合率高,层次混乱,维护开发成本高。

★★★Struts提供MVC架构,把传统WEB开发分成Model、View、Control三层,Model层负责业务逻辑(数据存储与处理),View层专注于数据在浏览器的显示(Html、css、jsp),Control层连接Model层与View层,从Model层获取数据传到View层。

129.    Struts 1.x是原来的Struts,Struts 2.x前身为WebWork框架。

130.    Struts完成了诸如类型转化、自动赋值、错误检查、数据验证、标签库、文件上传等一系列工作。

131.    Struts配置:(1)Web.xml配置

   <servlet>

                                           <servlet-name>action</servlet-name>

          <servlet-class>         org.apache.struts.action.ActionServlet

                                                                             </servlet-class>

                             <init-param>

                                                           <param-name>config</param-name>

                                                           <param-value>/WEB-INF/struts-config.xml</param-value><!-- 多文件可用逗号隔开,每个XML都是标准Struts配置文件 -->

                               </init-param>

      <init-param><!-- Struts配置命名空间 -->

                                                           <param-name>config/namespace1</param-name>                                                           <param-value>/WEB-INF/struts-config-namespace1.xml</param-value><!— 例如person.do 会调用struts-config.xml里配置的Action,而请求namespace1/person.do会调用struts-config-namespace1.xml里的Action -->

                               </init-param>

                               <init-param>

                                                           <param-name>debug</param-name>

                                                           <param-value>3</param-value>

                               </init-param>

                               <init-param>

                                                           <param-name>detail</param-name>

                                                           <param-value>3</param-value>

                               </init-param>

                               <load-on-startup>0</load-on-startup>

   </servlet>

   <servlet-mapping>

                               <servlet-name>action</servlet-name>

                               <url-pattern>*.do</url-pattern>

   </servlet-mapping>

(2)Struts配置文件/WEB-INF/struts-config.xml

<struts-config>

            <data-sources />

   <form-beans>

             <form-bean name="helloForm"type="com.czf.struts.form.HelloForm"/>

   </form-beans>

   <global-exceptions /><global-forwards />

   <action-mappings>

            <action attribute="helloForm"input="/form/hello.jsp"                         name="helloForm"               path="/hello"scope="request"type="com.czf.struts.action.HelloAction">

                                     <set-propertyproperty="cancellable"value="true"/>

                                     <forwardname="success"path="/form/helloSuccess.jsp"/>

                               <forwardname="fail"path="/form/helloFail.jsp"redirect="true"/>

                   </action>

   </action-mappings>

   <message-resources parameter="com.czf.struts.ApplicationResources"/><!-- 资源文件 -->

</struts-config>

HelloAction实现:

public class HelloAction extends Action {

                  public ActionForwardexecute(ActionMappingmapping, ActionForm form,      HttpServletRequestrequest,             HttpServletResponse response) {

                  HelloForm helloForm = (HelloForm) form;

                      if (helloForm.getName() == null ||

      helloForm.getName().trim().length() == 0) {

               return mapping.getInputForward();

                  }

      return mapping.findForward("success");

   }

}

132.    Struts工作流程

Ø  访问hello.jsp页面à

Ø  提交表单到/hello.doà

Ø  Struts截获*.do请求à

Ø  查找struts-config.xml找到hello.do对应的HelloForm和HelloActionà

Ø  将表单封装为HelloForm,并反射调用HelloAction的execute()à

Ø  Forward到/form/helloSuccess.jsp

133.    Struts1.x的Action线程安全的(Struts2.x中Action为线程安全,每个请求都会产生一个Action实例):Action生命周期与Servlet类似,Servlet由Tomcat容器产生并维护,而Action由Struts的ActionServlet产生并维护。每个Action都只有一个实例,在加载Struts时产生,在卸载Struts时销毁。

Ø  Action与Servlet一样,都不是线程安全的

Ø  因此,应避免Action属性,最好把Action属性都置位final

第15章 Struts1.x高级应用

134.    html标签库:主要用于生成html。property指定生成输入框、按钮等的name属性,property只能指定Form Bean中已经存在的属性。可以通过Action中指定Form Bean的属性值来操作Jsp页面的显示。

<html:form action="/tag"  enctype="multipart/form-data" >        

文件域:<html:file property="file"></html:file>    <br />

输入框:<html:text property="text"></html:text>

   提交按钮:<html:submitvalue="提交按钮" />    <br/>

         重置按钮:<html:cancelvalue="重置按钮" />    <br/>  

……   </html:form>

135.    bean 标签库:主要用于操作POJO、Cookie、Header以及Struts对象等。P428

<bean:write name="person"/><br/> <!-- property不指定时,调用toString()输出POJO本身 -->

      <bean:writename="person" property="createDate.time"/>   

      <bean:cookieid="sessionId" name="JSESSIONID"/><!-- 获取COOKIE 值“JSESSIONID存入sessionId 变量中-->

      <bean:writename="sessionId" property="value"/>……

136.    logic标签库

      <logic:present cookie="JSESSIONID"><!-- 判断COOKIE存在 -->

             <bean:cookie id="sessionId2"name="JSESSIONID"/>

             <bean:write name="sessionId2"property="value"/>

      </logic:present>

      <logic:notPresent cookie="JSESSIONID">

             Cookie“JSESSIOND”不存在。

      </logic:notPresent>     

      <logic:equal value="643BC94" cookie="JSESSIONID"></logic:equal>……

137.    nested标签库:低版本Struts中用于定义深层次属性,高版本中html标签可实现该功能。

帐号: <nested:text property="person.account"></nested:text>

138.    tiles标签库:处理网页布局。

模板页中使用<tiles:getAsString name="title"/>定义字符串变量或者<tiles:insert attribute="copyright"></tiles:insert>定义文件/Jsp变量。

使用模板页时,<tiles:insert page="/template.jsp"flush="true">

       <tiles:put name="title"value="读书频道 - 红楼梦"></tiles:put>  【填入字符串】

    <tiles:put name="copyright"value="/WEB-INF/classes/copyright.txt"></tiles:put>【填入文件内容】

</tiles:insert>

Tiles可与Struts结合使用P436.

139.    分发器DispatchAction:在实际应用中,一个Action中会有许多不同的操作,每个操作被封装成独立的方法,这些操作会以一个字段action或者method来区分:

// 根据 PersonForm 的 action 字段决定执行哪种操作

      if ("add".equals(personForm.getAction())) {

         return add(mapping, form, request, response);

      } elseif ("list".equals(personForm.getAction())) {

         return list(mapping, form, request, response);

      }

Ø  如果一个Action继承自org.apache.struts.actions.DispatchAction则自动具有分发功能

Ø        在execute方法调用returnsuper.execute(mapping, form, request, response); // 一定要执行这句代码, 父类会利用反射调用相关方法

Ø  Struts配置文件中配置该Action时,用parameter参数指定分发器使用的参数(一般使用action或者method

140.    在网站根目录下自动创建upload文件夹:

         File classes = new File(getClass().getClassLoader() .getResource("")

.getFile());// 文件夹/WEB-INF/classes      

         File uploadFolder = new File(classes.getParentFile().getParentFile(), "upload");// 文件夹/upload

         uploadFolder = new File(URLDecoder.decode(uploadFolder.getAbsolutePath

(),"utf-8"));//解决中文路径空格变成%20的错误

         uploadFolder.mkdirs();

141.    Struts文件上传:不需要解析request,直接保存FormFile中的文件数据

Ø  ActionForm中用FormFile类型(private FormFile file;)对应前端的

上传文件:<html:file property="file"></html:file>

Ø        execute方法中部分代码如下:

UploadForm uploadForm= (UploadForm) form;

      if (uploadForm.getFile() != null && uploadForm.getFile().getFileSize() > 0) {

   InputStream ins = uploadForm.getFile().getInputStream();

……读取ins,保存到File中

}

142.    Struts数据校验(1)ActionForm中的validate方法进行后台验证:

publicActionErrors validate(ActionMapping mapping,        HttpServletRequestrequest){

          ActionErrors errors = new ActionErrors();

         if (name == null || name.trim().length() == 0)

                errors.add("name", new ActionMessage("hello.error.name"));

      returnerrors;

   }//前端用<html:errors property="name" />显示错误信息

143.    Struts数据校验(2)使用Validator自动校验数据,该校验为前后台都校验。

Ø  FormBean继承Struts的ValidatorForm,且不能覆盖validate()方法à

Ø  在validation.xml中配置校验规则à

Ø  在ApplicationResources.properities中配置错误消息(国际化)à

Ø  在struts-config.xml中配置plug-in节点à

Ø  在Jsp页面使用<html:javascript formName=”myFormName”/>标签使Struts在该处生成相应JavaScript校验代码à

Ø  在<html:form />标签中定义属性onsubmit="returnvalidatemyFormName (this);"使提交页面时使用js校验数据。P442

144.    动态属性FormBean:除了继承ActionForm实现Form Bean,Struts还提供了一种配置式的动态Form Bean:DynaActionForm。这种Form Bean不需要实现具体的类,它的变量是配置在struts-config.xml中的:

<struts-config>

<form-beans>

    <form-beanname="dynaTestForm"     type="org.apache.struts.action.DynaActionForm">

            <form-property name="birthday"type="java.sql.Date"           initial="" />

            <form-property name="age"type="java.lang.Integer"            initial="18" />

            <form-property name="name"type="java.lang.String"            initial="" />

           </form-bean>

     </form-beans>

</struts-config>

Action中获取属性 DynaActionForm dynaTestForm= (DynaActionForm) form;

      String name= (String) dynaTestForm.get("name");

145.    异常处理

Ø  继承org.apache.struts.action.ExceptionHandler类,覆盖execute方法:

   if (exceptioninstanceofAccountException) {

             returnmapping.findForward("login");

      }

      returnsuper.execute(exception, config, mapping, form, request,            response);

Ø  配置struts-config.xml: key属性为对应资源文件中的键

   <global-exceptions>

          <exceptionkey="login.error" type="javax.security.auth.login. AccountException      "  handler="com.helloweenvsfei.struts.exceptionhandler.AccountExceptionHandler" />

<!--配置多个异常时,子类异常在前,父类在后 -->

   </global-exceptions>

   <global-forwards>

          <forwardname="login" path="/login.jsp"></forward> 

</global-forwards>

146.    struts-config.xml中使用通配符:P448

Ø  *代表任何不包括‘/’的任意长度(包括0)任意字符

Ø  **代表任何包括‘/’ 的任意长度(包括0)任意字符

Ø  \为转义字符,\* 代表 *, \\ 代表 \

第16章 Struts2.x概述

147.    Struts2.x起源于WebWork,与struts1.x完全不同:

Ø  Struts2代码和配置文件简洁,隐藏了细节

Ø  Struts2的Action线程安全(每个Action都会有多个实例,处理一次请求生成一个实例,各实例彼此独立,用完销毁),而Struts1非线程安全(每个Action只有一个实例,反复使用)

148.    Struts2示例

Ø  新建java Web项目,将Struts2类库复制到\WEB-INF\lib下

Ø  新建LoginAction,继承自com.opensymphony.xwork2.ActionSupport

public class LoginAction extendsActionSupport {

   privateString accountprivate String password;//Getter、Setter略

   @Override

   publicString execute() {

   if ("hello".equalsIgnoreCase(account) && "1234".equalsIgnoreCase(password)) {        returnSUCCESS;       }// SUCCESS在父类中定义为“success

      returnLOGIN;//在父类中定义为“login”字符串常量

   }}//返回值代表页面名称

Ø  Struts配置文件struts.xml位于src目录下:

<struts>

       <package name="main"extends="struts-default">

             <global-results>

                     <result name="login">/login.jsp</result>

             </global-results>

             <action name="loginPerson"class="com.czf.strut2.action.LoginAction ">

                     <result name="success">/welcome.jsp</result>

             </action>

       </package>

</struts>   

Ø  编写Jsp

<%@ page language="java"import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib uri="/struts-tags"prefix="struts"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN">

<html>

<head>

<title>My JSP 'success.jsp' starting page</title>

<struts:headtheme="xhtml"/> <!-- 定义主题自动生成<table><tr>等代码 -->

</head>

<body>

   <struts:formaction="loginPersion">

      <struts:labelvalue="登录系统"></struts:label>

      <struts:textfieldname="account"label="账号"></struts:textfield>

      <struts:passwordname="password"label="密码"></struts:password>

      <struts:submitvalue="登录"></struts:submit>

   </struts:form>

</body>

</html>

Ø  配置web.xml:Struts1使用ActionServlet作为分发器,而Struts2使用Filter作为分发器。如果有多个Filter,Struts的Filter必须放至最后。

<filter>

   <filter-name>struts2</filter-name>    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>

  </filter>

  <filter-mapping>

    <filter-name>struts2</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

149.    Struts2工作流程

 

150.    Struts2配置文件:(struts.properties在src目录下)

struts.custom.i18n.resources =com.helloweenvsfei.struts2.resources. Resources

struts.multipart.saveDir = /temp

struts.multipart.maxSize=10000000

……

151.   Action中获取网站根目录: 

      // 获取web应用根目录下 /upload 文件夹

      ServletContext context =ServletActionContext.getServletContext();

      File uploadFile = new File(context.getRealPath("upload"));

152.    Struts2的Action实现:

Ø  继承ActionSupport类(优点:可以使用Struts2的数据验证、错误显示等功能)

Ø  实现Action接口

Ø  不继承不实现:(具有public String execute() {}方法即可

153.    Action的可执行方法:execute是默认的可执行方法。其他方法只要返回String类型,没有参数,可以有throws声明,都可以成为可执行方法。执行方式如下:

Ø  URL执行:actionName!methodName.action.

Ø  将method配置为Action执行:(struts.xml中配置如下)

      <action name="logout"       class="com.helloweenvsfei.struts2.action. LoginAction"       method= "logout">

            <result name="success">/welcome.jsp</result>

      </action>

      <action name="*Person"        class="com.helloweenvsfei.struts2.action. LoginAction"method="{1}"> <!-- 使用通配符 -->

            <result name="success">/welcome.jsp</result>

      </action>

Ø  在<submit>标签中可指定调用的方法:

      <struts:submit value="执行 fieldError()" method="fieldError"/>

154.    Struts2的零配置(使用注解@Annotation):

@Namespace(value = "/test")

@Results( {

      @Result(name = "success", value = "/namespace1/success.jsp"),

      @Result(name = "redirect", value = "/namespace1/redirect.jsp", type = ServletRedirectResult.class) })

publicclass AnnotatedAction extends ActionSupport {……}

需要在web.xml中指定使用被@注解的Action的package:

   <filter>

          <filter-name>struts</filter-name>

      <filter-class>        org.apache.struts2.dispatcher.FilterDispatcher    </filter-class>

                   <init-param>

                <param-name>actionPackages</param-name>

                <param-value>com.helloweenvsfei.struts2.action</param-value>

            </init-param>       

   </filter>

使用注解配置的Action只能用URL方式(actionName!methodName.action)访问

第17章 Struts2.x高级应用

155.    数据类型转换器:P469

Ø  实现ognl.TypeConverter,一般直接继承DefaultType Converter类,并实现convertValue()方法。

public Object convertValue(Map context, Object value, Class toType) {}

value参数为request.getParameterValues(Stringname)返回的String[],

toType为要转成的类型。

Ø  配置转换器(全局):在src/xwork-conversion.properties文件中配置,key为需要转换的类型,value为转换器的类名:

java.sql.Date = com.struts2.convertor.DateTimeConvertor

java.sql.Time = com.struts2.convertor.DateTimeConvertor

java.util.Date=com.struts2.convertor.DateTimeConvertor

Ø  为Action配置转换器:在struts.xml定相应action节点定义converter属性即可

156.    Struts2中获取request、response

Ø 利用ServletActionContext的静态方法(非注入方式/非IoC方式):ServletActionContext利用ThreadLocal对象存储request等相关数据,保证各线程数据不混淆。

      HttpServletRequest request = ServletActionContext.getRequest();

      HttpServletResponse response = ServletActionContext.getResponse();

Ø  利用相关的Aware接口:(注入方式):P474.Struts在实例化一个Action对象时,如果发现它实现了相应的Aware接口,会吧相应的资源通过Aware的相应set方法注射进去。Application、request、response、session对应的Aware接口分别为:ServletRequestAware,ServletResponseAware, SessionAware, ServletContextAware

157.    Xml中CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束:表示中间的为纯文本数据,无需进行xml解析

158.    使用Validator校验数据

★★★被校验的Action要继承ActionSupport类,并且要在action配置中指定名input的jsp,因为校验失败后会自动返回input页面。

Ø  使用xml配置数据校验Validator:在Action类所在的package内添加一个XML文件,名为Action类名-validation.xml或者 Action类名-Action别名-validation.xml。如果Action中有多个方法,应使用后者,Action别名为struts.xml中为该方法配置的Action名。

<validators>     

   <field name="book.name"><!-- 检查书名,必须非空 -->

        <field-validator type="requiredstring">

            <param name="trim">true</param>

            <message>请输入书籍名称</message>

        </field-validator>

   </field>         

</validators>

Ø 使用@注解配置Validator:

@Validation()注解Action类,表示该Action需要数据校验

@validations()配置在方法上,可指定多条规则

@SkipValidation()作用在方法上,跳过校验

例如:

   @Validations(requiredStrings = {

         @RequiredStringValidator(type = ValidatorType.SIMPLE, trim = true, fieldName = "book.name", message = "请输入书籍名称. *") })

public String add() {}

将Jsp中的<struts:form >标签添加validate=”true”属性即可实现客户端js校验。不像struts1那样弹出提示框,直接在文本域上方提示错误,无需另外修改jsp.

第18章 Struts2.x 标签

159.    OGNL,Struts2标签库主要使用OGNL(Object-GraphNavigation Language)语言,它是一种操作对象属性的开源表达式语言,该语言比EL更强大。OGNL特点:

Ø  能够访问对象方法,如list.size()

Ø  能够访问静态属性和方法(在类名和方法名上加@)。如@java.lang.Math@PI、@java.lang.String@format(‘foo %s’,’bar’);

Ø  支持赋值和表达式串联,如#value=5

Ø  OGNL3个符号:#、%、$; #符号最常用,用途如下:

Ø     %符号显示声明OGNL表达式:用于表示某字符串为一个OGNL表达式。某些标签中既能够接受字符串,又能够接受OGNL表达式,这时候标有%的被当做OGNL表达式执行,没有%的被当做普通字符串。

<struts:label label=”#request.account”></struts:label>

<struts:label label=”%{#request.account}”></struts:label>

第一行将输出字符串#request.account,而第二行将输出request对象的account属性

Ø  $符号:在资源国际化文件或者struts.xml中使用OGNL表达式。

160.    Struts2标签分为控制标签、数据标签、表单UI标签,非UI标签四大类

161.    控制标签:

Ø  if、elseif、else

<!-- 利用 request 参数判断 -->

<struts:if test="#parameters.name[0]== 'Kurt'">

       Hello, Kurt.

</struts:if>

<struts:elseif test="#parameters.name[0]== 'Matt'">

       Hello, Matt.

</struts:elseif>

<struts:else>

       Hello, Other Buddies.

</struts:else>

Ø  append/merge标签P485:append用于将多个List合并成一个List,相当于Java中的list.addAll(list2)。mearge类似与append,不同的是apend先添加maleList所有元素,再添加femaleList 所有元素,而merge先添加maleList第一个元素,再添加femaleList第一个元素,再添加maleList 第二个元素……

<s:append id="myAppendList">

       <s:param value="%{maleList}" />  <!--  定义在后台的List<String>-->

       <s:param value="%{femaleList}" />

</s:append>

<s:iterator value="%{#myAppendList}">

       <s:property /><br/>  <!-- 输出合并后List的每个值-->

</s:iterator>

Ø  generator标签: 将字符串解析为List,相当于Java中的split

<s:generator val="%{'李宁, 安踏, 双星, 阿达, 耐克'}" separator=",">

     <s:iterator>

          <s:property />        <br />

     </s:iterator>

</s:generator>

Ø  iterator标签:遍历集合:

<struts:iterator value="magazineList.{?#this.price>18}">

          <struts:property value="name" /><br />

   </struts:iterator>

Ø  subset标签:过滤集合元素:maleList是action中的集合属性,decider是Action中的Filter,必须实现SubsetIteratorFilter.Decider接口

<s:subset source="maleList" decider="decider">

     <s:iterator>

          <s:property />

          <br>

     </s:iterator>

</s:subset>

Action中decider代码如下:

   private SubsetIteratorFilter.Decider decider = new SubsetIteratorFilter.Decider() {

     //返回true则将该对象置于子集合中

        publicboolean decide(Object obj) throws Exception {

            if (objinstanceof String) {

                 if (obj.equals("Other"))              returnfalse;           else               returntrue;

            }        returnfalse;

      }  };

162.    数据标签:

Ø  action/include:包含action页面,相当于jsp中的include

<s:action name="login" executeResult="true"ignoreContextParams ="false" /><!--  传递本页面的参数  -- >

<s:include value="/login.jsp" >  </s:include>

Ø  bean / param / property :bean标签引用JavaBean,param 赋值,property输出值

<struts:bean name="com.struts2.bean.Magazine" id="magazine">

     <struts:param name="name" value="%{'瑞丽杂志'}" />

     <struts:property value="name" />

</struts:bean>

Ø set :定义变量,并赋值:

<s:set name=”technologyName”value=”%{‘Java’}” />

Ø  date格式化日期输出:其nice属性默认为false,为true时,format属性失效,智能显示“20 days ago”,“in 20minutes”类似的格式

<struts:bean name="java.util.Date" id="date">

     <struts:param name="time" value="#date.time - 70L*24*60*60*1000"></struts:param>

</struts:bean>

<struts:date name="date" format="yyyy/MM-dd HH:mm:sss" /><br />

<struts:date name="date" />  <br />

<struts:date name="date" nice="true" /><br/>

2017/11-17 10:52:033
2017-11-17 10:52:33
70 days ago

Ø i18n / text标签:资源国际化。i18n指定资源文件,text指定资源索引,如果没有使用i18n标签,则使用Struts2的资源文件:Struts2中任何标签都可以用%{getText('struts.messages.error.uploading')}实现资源国际化。

   <struts:text name="struts.messages.error.uploading"/>

   <struts:i18n name="otherResources">

          <struts:text name="hello.world"></struts:text>

   </struts:i18n>

   <struts:text name="none.resource">没有资源,显示标签体内的字符串。</struts:text>

   <struts:text name="没有资源,也没有标签体内容,则显示name属性" />

   <struts:property value="%{getText('struts.messages.error.uploading')}" />

163.    表单UI标签:

Ø  form/textfield/textarea/file/checkbox/raido/label/submit  radio标签的list属性必须是Map类型,key为实际值,value为显示值。

   <struts:form action="addBook"validate="true">

        <struts:label value="form 标签"></struts:label>

        <struts:textfieldname="name" label="书名"></struts:textfield>

     <struts:passwordname="password" label="密码" tooltip="这是密码域" />

        <struts:textareaname="textarea" label="文本" tooltip="这是文本域" />

        <struts:file name="file" label="文件域" tooltip="这是文件域" />

        <struts:radio list="#{'male':'', 'female':''}" name="sex"        label="单选框" tooltip="这是单选框" />

        <struts:checkboxname="hobby" label="是否精通 Struts" value="true" />

        <struts:submit value=" 提 交 " align="center"></struts:submit>

        <struts:submit value="执行 fieldError()" method="fieldError"/>

   </struts:form>

Ø  checkboxlist 可多选的多个复选框。需要用复选框时,如果对应属性为boolean类型时,用checkbook标签,如果为集合类或者数组时则用checkboxlist标签。

<% List<String> favouriteList = newArrayList<String>();

   favouriteList.add("苹果");  favouriteList.add("橘子");

   request.setAttribute("favouriteList",favouriteList); %>

<struts:form action="login">

     <struts:checkboxlistlist="#request.favouriteList"name="favourite"label="最喜欢的水果" />

</struts:form>

Ø  select/autocompleter autocompleter标签为具有自动完成功能的下拉框,能根据所填的内容筛选下拉框的内容(中文支持不好)。使用autocompleter标签必须使用ajax主题,因为它用到了DOJO的JavaScript库。

<struts:select name="province" label="请选择省份" list="%{#request.provinceList}"/>

   <struts:autocompleter name="province" label="请选择省份" list="#request.provinceList"></struts:autocompleter>

autocompleter下拉框中的数据可以从后台动态加载:href对应的jsp读取country参数,返回JSON数据,如[[‘China’] [‘Andorra’][‘America’]]

<s:url id="dataUrl" value="/autocompleteAjaxData.jsp"/>

请选择国家:<struts:autocompleter name="country"theme="ajax" href="%{dataUrl}"   loadOnTextChange="true"loadMinimumCount="1" autoComplete="false"    showDownArrow="true"indicator="indicator"  />

   <img id="indicator" src="images/loading.gif"/>

Ø  combobox 组合框,可选择也可编辑,用一个输入框与下拉框实现。

<struts:combobox list="#request.favouriteList" name="favourite" label="最喜欢的水果" />

Ø  datetimepicker 需使用ajax主题

<struts:datetimepicker name="date"displayFormat="yyyy-MM-dd" label="请选择日期" />

Ø  doubleselected 二级联动选择框

<%    List<String> provinceList = new ArrayList<String>();

        provinceList.add("北京");  provinceList.add("上海");

   request.setAttribute("provinceList",provinceList); 

   Map<String, List<String>> cityMap= new HashMap<String,List<String>>();

      List<String> cityList = new ArrayList<String>();        // 北京市   

      cityList.add("东城区");      cityList.add("西城区");

      cityMap.put("北京", cityList);

   request.setAttribute("cityMap",cityMap); %>

<struts:form action="login">

       <struts:doubleselectname="province"list="#request.provinceList"     doubleName="city" doubleList="#request.cityMap.get(top)" label="请选择省份、市"/>

</struts:form>

Ø  optiontransferselect 标签左右各有一个列表,左边和右边的选项可以相互转移:

   <%    List<String> provinceSelected = newArrayList<String>();

      provinceSelected.add("北京");      provinceSelected.add("上海");

      List<String> provinceUnselected = newArrayList<String>();

 

      provinceUnselected.add("湖南");    provinceUnselected.add("湖北");

      request.setAttribute("provinceUnselected",provinceUnselected); %>

   <struts:form action="login">

          <struts:optiontransferselect

name="province"       list="#request.provinceSelected"

doubleName="city"       doubleList="#request.provinceUnselected"leftUpLabel="向上"        leftDownLabel="向下"

rightUpLabel="向上" rightDownLabel="向下"    

leftTitle="已经选中的省份"    rightTitle="剩余的省份"

headerKey=""headerValue="---请选择省份---"     />

   </struts:form>

Ø  optgroup 给<select>的选项分组:其list属性接受Map类型数据而不是List

   <%        request.setAttribute("cityList", newArrayList<String>() {

         {           add("北京");          add("上海");       }     });

      Map provinceMap = newHashMap();

      provinceMap.put("山东", new HashMap() {

         {           put("济南", "济南");            put("青岛", "青岛");         }       });

      provinceMap.put("河北", newHashMap<String, String>() {

         {           put("石家庄", "石家庄");            put("唐山", "唐山");         }     });

      request.setAttribute("provinceMap", provinceMap);    %>

   <struts:form action="login">

        <struts:select name="city"list="#request.cityList"label="选择城市">

            <struts:iteratorvalue="#request.provinceMap">

                 <struts:optgrouplabel="%{key}"list="%{value}"/>

            </struts:iterator>

        </struts:select>

   </struts:form>

164.    非表单UI标签

Ø debug 标签输出调试信息:<struts:debug />

Ø fielderror / actionerror / actionmessage标签显示错误信息.fielderror显示数据校验错误信息,actionerror显示Action中的错误信息,……

JSP:<struts:fielderror />

Action:  this.addFieldError("username", "请填用户名");

Ø div / submit 标签实现无刷新获取数据(head 使用ajax主题)P505。如果获取的页面不是纯HTML(含js),需要设置div、submit标签的executeScripts属性为true执行JavaScript。

   <s:url id="news" action="divNews"/><!-- 要显示页面的 URL -->

   <!-- indicator 获取数据时显示,完成后隐藏-->

   <spanid="indicator" style="background:#FFF000; padding: 4px;">    正在刷新<s:property value="#news"/> ...  </span>

   <!-- div标签 显示一个页面 每隔5秒钟刷新一次 -->

   <s:div theme="ajax" href="%{news}"showLoadingText="false"    updateFreq="5000"indicator="indicator" />

   <s:form name="newsActionForm" id="newsActionForm">   <!--查询表单 -->

          <s:textfield name="key"label="关键词" />

          <s:submit value="查询新闻" href="%{news}"formId="newsActionForm"

         theme="ajax"targets="divNewsSearch" />

   </s:form>

   <div id="divNewsSearch"></div><!-- 查询结果显示在这里 -->

Ø tabbedPanel标签页:

<s:tabbedPanel id="test"  closeButton="tab">

       <s:div id="one"label="第一个 TabItem" theme="ajax"     cssStyle= "padding:10px; ">    第一个 TabItem <br />     第一个 TabItem <br />  </s:div>

       <s:url action="divNews"id="divNewsUrl"></s:url>

       <s:div id="three"label="新闻列表" theme="ajax" href="%{#divNews Url}">   </s:div>

</s:tabbedPanel>

Ø tree / treenode 标签显示树,可显示文件结构,可动态加载数据。 P512

第19章 Struts2.x 拦截器与文件上传

165.    Struts2提供面向切面编程(AOP,Aspect Oriented Programming),拦截器是一种成熟的AOP实现

166.    ★★★拦截器(Interceptor)与过滤器(Filter)的区别:

1、拦截器是基于java反射机制的,而过滤器是基于函数回调的。 

2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。 

3、拦截器只能对Action请求起作用,而过滤器则可以对几乎所有请求起作用。 

4、拦截器可以访问Action上下文、值栈里的对象,而过滤器不能。 

5、在Action的生命周期中,拦截器可以多次调用,而过滤器只能在容器初始化时被调用一次。

167.    timer 计时拦截器,能在控制台记录action方法运行时间。

      <action name="timer"        class="com.czf.struts2.action.TimerAction">        

<interceptor-ref name="timer"></interceptor-ref> <-- 引用Struts的拦截器-->

          <result>/timerSuccess.jsp</result>

      </action>

168.    token 防重复提交拦截器,使用时要在<s:form/>标签中添加<struts:token />

   <action name="token"       class="com.czf.struts2.action.TokenAction">

          <interceptor-ref name="token"></interceptor-ref>

          <interceptor-ref name="basicStack" />

          <result>/tokenSuccess.jsp</result>

          <result name="input">/tokenInput.jsp</result>

          <result name="invalid.token">/tokenInvalid.jsp</result>

      </action>

169.    executeAndWait执行等待拦截器,在Action忙时,显示等待页面。现一般通过Ajax实现无刷新,显示进度条

170.    自定义拦截器(权限验证):自定义拦截器一般继承自AbstractInterceptor类,或者直接实现Interceptor接口。

public class AuthenticationInterceptor extends AbstractInterceptor{

   privatestatic finallong serialVersionUID= -4433771430728214868L;

   @Override       @SuppressWarnings("all")

   publicString intercept(ActionInvocation invocation)throws Exception {

        Map<String,Object> sessionValues = invocation.getInvocationContext()          .getSession();

        Stringaccount = (String) sessionValues.get("account");

        if (account== null) {       return Action.LOGIN;     }

        return invocation.invoke();//验证通过,继续执行Action

   }}

   <package name="main"extends="struts-default">

        <interceptors>

            <interceptorname="authentication"            class="czf.interceptor.AuthenticationInterceptor">         </interceptor>

        </interceptors>

        <global-results>

            <resultname="login">/login.jsp</result>

        </global-results>

     <action name="authentication"       class="czf.action.AuthenticationAction">

            <interceptor-refname="authentication"></interceptor-ref>

            <result>/authenticationSuccess.jsp</result>

        </action>

</package>

171.    Struts2上传文件: Struts2直接将上传的文件封装为Java中的File对象(Struts1.x封装为FormFile),直接在Action中定义一个File变量,然后复制文件到保存目录即可。

Ø JSP:

<struts:actionerror/>

   <struts:form action="upload" enctype="multipart/form-data"    method="post" validate="true">

        <struts:label value="上传文件"></struts:label>

        <struts:file name="picture"label="文件一"></struts:file>

        <struts:submit value=" 开始上传 " method="upload"></struts:submit>

   </struts:form>

Ø  Action:

public class UploadAction extendsActionSupport {

        privateFile picture;

     private String pictureContentType;//可选,Struts自动赋值MIME

     private String pictureFileName;//可选,Struts自动赋值文件名

     public String execute() {        return "input";    }

     public String upload() throws Exception {

      File saved = new File(ServletActionContext.getServletContext().getRealPath("upload"), pictureFileName);

          Files.copy(picture.toPath(), saved.toPath());//jdk1.7+

          return "list";

     }

}

Ø  上传文件相关设置

struts.properties文件加入下面两句:

struts.multipart.saveDir= /temp《临时保存目录,在Tomcat所在盘根目录下》

struts.multipart.maxSize=10000000《此配置需大于struts.xml中的设置》

struts.xml配置如下:

<action name="upload" class="com.struts2.action.UploadAction">

          <interceptor-ref name="fileUpload">

                <param name="allowedTypes">             image/bmp,image/png            </param>《mime类型》

                <param name="maximumSize">90480</param> 《单位Byte》

          </interceptor-ref>

          <interceptor-ref name="defaultStack" />

          <result name="input">/upload.jsp</result>

          <result name="list">/uploadList.jsp</result>

      </action>

Ø  错误信息中文化

struts.properties文件加入下面语句:

struts.custom.i18n.resources = com.helloweenvsfei.struts2.resources.Resources

Resources.properties文件如下:

Ø  上传多个文件:P529.在Action中指定File[]或List<File>类型的变量,并在JSP中使用多个同名的<struts:file />标签即可。

第20章 Hibernate入门

172.    Hibernate是一种ORM(ObjectRelational Mapping)框架,在Java对象(POJO)与关系数据库之间建立映射,以实现直接存取Java对象。类似ORM框架有JDO,TopLink,MyBatis(iBatis),OpenJPA。Hibernate是轻量级的框架,Java官方的ORM框架EJB、EJB2都是重量级框架,配置复杂,对容器依赖较大,商业上不成功。

173.    JPA,ORM,Hibernate的关系

Ø  JPA(Java Persistence API)框架是javaEE 5 的标准ORM接口。它是一种规范,一套接口,但不是实现。实现这一规范的ORM很多,其中Hibernate就是之一。JPA的目的在于规范各种ORM接口,JPA晚于Hibernate,受Hibernate影响了。

Ø  ORM,对象关系映射,它是一种解决问题的思路,是一种思想。它通过配置文件或Java注解把Java对象映射到数据库上,自动生成SQL语句并执行

Ø  Hibernate是ORM框架,它实现了JPA的规范。

174.    Hibernate示例:

Ø  新建Web Project,加入Hibernate特性,添加Annotation/MySql 等jar库

Ø  新建实体类:Cat.java:注解都用javax.persistence.*下的注解,如果某个字段不需要保存到数据库,可以用@javax.persisence.Transient配置

@Entity

@Table(name="tb_cat")

publicclass Cat {

     @Id

     @GeneratedValue(strategy= GenerationType.AUTO)

     private Integer id;

     @Column(name="name")

     private String name;

             @ManyToOne

     @JoinColumn(name="mother_id")

     private Cat mother;  

     @Temporal(value = TemporalType.TIMESTAMP)//DATETIMETIMESTEMP

     private java.util.Date createDate;

}//getter 和 setter 方法略

Ø  修改Hibernate配置文件,hibernate.cfg.xml

<hibernate-configuration>

     <session-factory>

          <property name="hbm2ddl.auto">create</property>

          <propertyname="dialect">org.hibernate.dialect.MySQLDialect </property>

          <property name="connection.password">admin</property>

          <property name="connection.username">root</property>

          <property name="connection.url">jdbc:mysql://localhost:3306/ hibernate?characterEncoding=UTF-8&useSSL=true</property>

          <property name="connection.driver_class">com.mysql.jdbc.Driver </property>

          <property name="show_sql">true</property>《控制台显示SQL语句》

          <property name="current_session_context_class">thread</property>《对于Jboss等内置Hibernate的容器配置为jta,其他容器Tomcat等设为thread

          <property name="javax.persistence.validation.mode">none </property>

          <mapping class="com.czf.hibernate.bean.Cat"/>

     </session-factory>

</hibernate-configuration>

Ø  如果使用注解配置数据库映射,MyEclipse生成的HibernateSessionFactory类中的Configuration对象应改为AnnotationConfiguration对象。如果使用XML配置数据库映射,则无需修改。

Ø  配置Log4J:Hibernate使用Log4J输出日志,src目录下log4j.properties:

log4j.rootLogger=ERROR, stdout

log4j.category.org.hibernate.tool.hbm2ddl=DEBUG, file

log4j.category.org.hibernate.SQL=DEBUG, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS}[%c]-[%p] %m%n

log4j.appender.file= org.apache.log4j.FileAppender

log4j.appender.file.File= log.txt

log4j.appender.file.layout=org.apache.log4j.PatternLayout

log4j.appender.file.layout.ConversionPattern=Hibernate: %m%n

Ø  执行Hibernate程序

      Cat mother= new Cat();

      mother.setName("Marry White");    mother.setDescription("Ther Mama Cat.");    mother.setCreateDate(newDate());

      Cat kitty= new Cat();

            kitty.setName("Kitty");     kitty.setDescription("Hello Kitty.");kitty.setMother(mother);    kitty.setCreateDate(new Date());    

Session session = HibernateSessionFactory.getSession();

      Transaction trans= session.beginTransaction();

      session.persist(mother);    session.persist(kitty);

      List<Cat> catList= session.createQuery("from Cat").list();

      trans.commit();    session.close();

      StringBuffer result= new StringBuffer();

      result.append("数据库里的所有的猫:\r\n\r\n");

      for(Cat cc : catList){

         result.append("猫:" + cc.getName() + ", 猫妈妈:" + (cc.getMother() == null ? "没有记录"              :cc.getMother().getName()) + "\r\n");

      }

      JOptionPane.showMessageDialog(null, result.toString());

第21章 从宏观上把握Hibernate

175.    Hibernate在程序中的位置:

Ø  Hibernate直接操作Java对象,底层使用JDBC实现。

Ø  使用Hibernate后,开发者可以不用关注JDBC,而更关心业务逻辑。

Ø  Hibernate是跨数据库平台的,通过配置不同sql方言(Dialect),生成不同的SQL语句。

176.    Hibernate默认配置文件为hibernate.properties或者hibernate.cfg.xml位于classpath下面。如果properties文件中配置了参数,在cfg.xml中只声明实体类配置的位置就可以了。

<hibernate-configuration>

<session-factory>

      <mapping resource="com/czf/hibernate/bean/Cat.hbm.xml"/>

</session-factory>

</hibernate-configuration>

177.    Hibernate可以进行编程式配置(运行时配置)

Ø  调用Configuration对象的addResource(“com/czf/hibernate/bean/ Cat.hbm.xml”)方法可以动态加载实体类配置

Ø  调用addClass(com.czf.hibernate.bean.Cat.class)可以直接加载实体类(推荐

Ø  调用setProperty或者addProperties方法设置一个或多个Hibernate参数

第22章 Hibernate实体映射

178.    Hibernate实体映射分为xml映射(Cat.hbm.xml等)和@注解映射(推荐:对于所有ORM框架,注解映射通用)。注解映射示例见20章,xml映射示例:

<hibernate-mapping package="com.helloweenvsfei.hibernate.bean">

     <class name="Cat" table="tb_cat">

          <id name="id" column="id">        <generator class="native"/>      </id>

          <property name="name" type="string" column="name"></property>

          <property name="description" type="text"></property>

          <property name="createDate" type="timestamp"></property>

          <many-to-one name="mother" column="mother_id"></many-to-one>

    </class>

</hibernate-mapping>

179.    主键映射:尽量选择可以为null的类型,如Integer、Long等,因为主键为null可以表示实体还没有保存到数据库的临时状态。

Ø  注解主键生成规则:@GeneratedValue,JPA通用策略生成器 。JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO. 

TABLE

使用一个特定的数据库表格来保存主键。 将当前主键的值单独保存到一个数据库的表中,主键的值每次都是从指定的表中查询来获得,这种生成主键的方式也是很常用的。这种方法生成主键的策略可以适用于任何的数据库,不必担心不同数据库不兼容造成的问题

@Id

@GeneratedValue(strategy = GenerationType.TABLE, generator="customer_gen")

@TableGenerator(name = "customer_gen",

                  table="tb_generator",

                  pkColumnName="gen_name",//该表中有这两列

                  valueColumnName="gen_value",

                  pkColumnValue="CUSTOMER_PK",

                  allocationSize=1  )

SEQUENCE

根据底层数据库的序列来生成主键,条件是数据库支持序列。(Oracle,DB2,PostgreSQL等)

IDENTITY

主键由数据库自动生成(主要是自动增长型) 。(DB2,MySQL,MS SQL Serer,Sybase)

AUTO

自动方式,根据底层数据库自动选择。

@Id// 指定该列为主键

   @Column(name = "id"

   @GeneratedValue(strategy = GenerationType.AUTO) // 主键类型, auto为数据库自增长类型 

   private Integer id;

Ø  XML主键生成规则

native

相当于GenerationType.AUTO由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。

identity

GenerationType. IDENTITY

sequence

GenerationType. SEQUENCE

increment

由Hibernate从数据库中取出主键的最大值,每次增量为1,在内存中生成主键,不依赖于底层的数据库,可以跨数据库。

只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库

hilo

hilo(hi/lo算法)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。

seqhilo

与hilo类似,通过hi/lo算法实现的主键生成机制,只是将hilo中的数据表换成了序列sequence,需要数据库中先创建sequence,适用于支持sequence的数据库,如Oracle。

uuid

(Universally Unique Identifier)uuid长度大,占用空间大,跨数据库,不用访问数据库就生成主键值,所以效率高且能保证唯一性,移植非常方便,推荐使用

guid

(Globally Unique Identifier)需要数据库支持查询uuid,生成时需要查询数据库,效率没有uuid高,推荐使用uuid

assigned

主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。

select

使用触发器生成主键,主要用于早期的数据库主键生成机制,能用到的地方非常少。

foreign

使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中。

180.    属性延迟加载@Basic(fetch = FetchType.LAZY,optional = true)

181.    临时属性映射,使用注解时用@Transient。使用xml配置时,没配置到xml中的属性都被视为临时属性。

182.    Hibernate乐观锁:

Ø  乐观锁的作用

乐观锁的主要作用是为了解决事务并发带来的问题。相对于悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销。

Ø  乐观锁的工作原理

乐观锁,大多是基于数据版本(Version)记录机制实现。为数据增加一个版本标识,一般是通过为数据库表增加一个"version"字段来实现。读取出数据时,将此版本号一同读出,而更新对象时,对此版本号加1(使用hql或者原生sql更新时,version失效)。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据,抛出异常。

Ø  使用@version或<version />指定实体类中的Version列即可

第23章 Hibernate实体关系映射

183.    单边一对多关系:一个人对应多个电子邮件,Person.java中配置一对多关系

@OneToMany(fetch = FetchType.LAZY, targetEntity = Email.class, cascade = {       CascadeType.PERSIST, CascadeType.REMOVE, CascadeType.MERGE,         CascadeType.REFRESH})

   @JoinColumns(value= { @JoinColumn(name = "person_id", referencedColumnName = "id") })

   @OrderBy(value="email desc")  

   privateList<Email> emails = new ArrayList<Email>();

184.    延时加载(默认)(fetch = FetchType.LAZY),需在session关闭前调用persoin.getEmails(),迫使Hibernate加载数据,否则会产生异常。

即时加载(fetch = FetchType.EAGER

185.    hibernate.hbm2ddl.auto的值

create

表示启动的时候先drop,再create

create-drop

也表示创建,只不过再系统关闭前执行一下drop

update

这个操作启动的时候会去检查schema是否一致,如果不一致会做scheme更新

validate

启动时验证现有schema与你配置的hibernate是否一致,如果不一致就抛出异常,并不做更新

186.    @注解配置为JPA(Java Persistence API)配置,各ORM框架通用。XML配置为Hibernate独有,比注解配置更丰富,更灵活。

187.    XML配置Person类,bag标签配置List属性,cascade可用“-”配置多个级联方式,例如“persist-save-delete”:

<hibernate-mapping package="com.helloweenvsfei.hibernate.bean">

     <class name="Person2" table="tb_person2">

          <id name="id" column="id">        <generator class="native"/>      </id>

          <property name="name" />

          <bag name="emails"cascade="all" lazy="false" where="email like '%@%' "       order-by="email">

              <key column="email_id"></key>

              <one-to-many class="com.helloweenvsfei.hibernate.bean.Email"/>

          </bag>

     </class>

</hibernate-mapping>

188.    单边一对一、多对一、多对多关系、双边的一对一、一对多、多对一、多对多关系配置见P578

第24章 Hibernate查询语言HQL

189.    HQL类似于SQL,不同的是HQL是面向对象的,可直接查询实体类及属性。HQL大小写不敏感,但是涉及到java包名,类名,属性时大小写敏感。

190.    返回类型:

Ø  返回单个对象:

Query q= session.createQuery(“ selectcount(c) from Cat c “);

Number num=(Number)q.uniqueResult();//如果返回值有多个报异常

int count=num.intValue();

Ø  返回List:

List<Cat> list=session.createQuery(“select c from Cat c “).list();

191.    同时返回多个对象:

Ø  返回Object[] 数组

List<Object[] > list=session.createQuery(“ select c.name,c.mother,c.createDate from Cat c”).list();//因select 中既有String 又有Object

Ø  返回List或者Map类型

List<List> list=session.createQuery(“select new List( c.name,c.mother,c.createDate ) from Cat c”).list();

List<Map> list=session.createQuery(“select new Map( c.name as name ,c.motheras mother, c.createDate as createDate ) from Cat c”).list();

Ø  返回Java实体对象(查询部分属性时)

List<Cat> catList= session.createQuery(“select new Cat( c.name, c.createDate ) from Cat c”).list();//调用构造函数,前提得有这个public的构造函数。

192.    HQL参数格式为 :parameter,使用Query的setParameter方法设置参数。应尽量使用setParameter传递参数,而不是将参数写到HQL语句中(Hibernate对于参数不同的相同查询有优化,即第二次后直接使用编译好的SQL语句)

193.    HQL运算符和函数:其余运算符见P610.

Ø  使用 || 或者 concat(…,…) 连接字符串

Ø  集合查询:List<Cat> list=session.createQuery(“ from Cat c where size(c.events)>5 “).list();

Ø  统计函数:count(),sum(),min(),max(),avg()等

194.    HQL分页:Query对象的setFirstResult()设置起始记录(第一条记录索引从0开始);setMaxResults()设置本页大小(本次取记录的个数)。

195.    HQL级联查询

Ø  一般跨表查询用.(点号)即可,适用于非集合属性:

List<Event>eventList=session.createQuery(“ select e from Event e where e.cat.name= ‘Ketty’ “).list();

Ø  级联查询(inner join,left join,right join等),适用于集合属性:

查询events集合属性中有“吃早饭”时间的cat:

List<Cat > list=session.createQuery(“select  c from Cat c left join c.events ewhere e.description like :description “).setParameter(“description”,”%吃早饭%”).list();

196.    Hibernate使用SQL语句查询:使用SQLQuery对象

SQLQuery sqlQuery= session.createSQLQuery(“select * from tb_cat “);

sqlQuery.addEntity(Cat.class);//设置输出类型

List<Cat> list= sqlQuery.list();

197.    命名常用查询

Ø  注解配置

在实体类上使用注解@NamedQuery配置HQL查询,使用@NamedNativeQuery配置命名的底层数据库SQL查询,使用@NamedQueries或@NamedNativeQueries设置多个命名查询:

//@NamedQuery(name= "all cat", query = " select c from Cat c ")

//@NamedNativeQuery(name= "all cat", query = "select * from tb_cat")

@NamedQueries(value = {     @NamedQuery(name = "allcat", query = " select c from Cat c "),    @NamedQuery(name = "cat bymother", query = " select c from Cat c ") })

使用时:Queryq=session.getNamedQuery(“cat by name ”).setParameter (“name”,“Kitty”);

Ø  XML配置:在实体类<class > 节点内最后用<query> 或者 <sql-query>配置

   <query name="findStudentByName"> 

        <![CDATA[from Student where name = :name]]>

      </query>

      <sql-query name="findStudentByName">

            <return alias="s" class="com.test.bean.Student">       </return> 

    <![CDATA[select {s.*} from student s where s.name = :name]]>

      </sql-query>

第25章 Hibernate高级查询

198.    Servlet + Hibernate 员工管理示例见P617.

第26章 Spring概述

199.    轻量级框架不依赖与容器就能运行的框架。Spring、Struts、Hibernate都是轻量级的框架。EJB是重量级的,只能运行在支持EJB的容器如(Jboss,Glassfish)。

200.    Spring实际是一个轻量级的容器,能够生产、管理、维护各种实例(DAO,Service)。

201.    Spring的重要思想是IOC(控制反转)与AOP(面向切面编程)。

202.    Spring主要思想是IoC(Inversion ofControl,控制反转,反向控制),或者称之为DI(Dependency Injection,依赖注入)。IoC是对传统控制流程的一种颠覆。

Ø  传统程序中,相互的依赖关系(new 产生对象)是固定在程序中的。程序的执行流程可以从代码中阅读出来,都是正向运行的。

Ø  反向控制(IoC),代码中定义接口类型对象IDao,而不用new实例化(实例化一个DaoImpl对象)。该对象将被Spring注射进来(通过反射调用getter,setter方法)。而注射的动作发生在运行时,是在ServiceImpl代码写完之后,这个方向是反向的。Service层仍然要依赖Dao层,只不过这种依赖关系并不是写在程序中,而是配置在Spring文件中,由Spring在运行时设置。

203.    Spring实例:

publicinterface IDaopublic StringsayHello(String name);}

publicclass DaoImpl implements IDao {

     public String sayHello(String name) {

          inthour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);

          if (hour < 12){         return"上午好,"+name;    }else{      return"下午好,"+name;      }

     }

}

publicinterface IService{ publicvoid service(String name);}

publicclass ServiceImpl implements IService {

     private IDao dao;

     public IDao getDao() {    returndao; }

     publicvoid setDao(IDao dao) {      this.dao = dao; }

     publicvoid service(String name) {

          System.out.println(dao.sayHello(name));

     }

}//applicationContext.xml配置文件如下:

<?xml version="1.0"encoding="UTF-8"?>

<beans……>

       <bean id="daoImpl" class="czf.spring.dao.DaoImpl">  </bean>

       <beanid="serviceImpl" class="czf.spring.service.ServiceImpl">

           <property name="dao" ref="daoImpl"></property>

       </bean>

</beans>

运行(Spring4.1):

public static voidmain(String[] args) {

     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

    IService helloService= context.getBean(ServiceImpl.class); 

    helloService.service("码云");

   }

204.    面向切面编程(AOP,Aspect Oriented Programing):在执行业务代码的前后执行另外的代码使程序能灵活、扩展性更好,可以随意地添加、删除某些功能(A|B à A|C|B。A、B、C看成切面,可将C组件插入到A组件与B组件中执行)。

 Servlet中的Filter就是面向切面编程的例子,Tomcat会在程序运行的某个时机(即Servlet执行前后),执行与Servlet、JSP等毫无关系的Filter代码。

 Spring提供非常灵活的AOP机制,Spring的另一种重要思想是AOP

205.    面向切面编程(拦截器Interceptor)实例:

定义方法执行前的拦截器:

publicclass MethodBeforeAdviceImpl implements MethodBeforeAdvice {

     publicvoid before(Method method, Object[] args, Object obj)          throws Throwable {

          System.out.println("运行前检查... ");

          System.out.println("Method:" + method.getName());

          System.out.println("Args:" + Arrays.asList(args));

          System.out.println("Object:" + obj);

     }

}//配置拦截器:

   <!-- 拦截器对象 -->

   <beanid="methodBeforeAdviceImpl"    class="com.helloweenvsfei.spring.example.MethodBeforeAdviceImpl">  </bean>

   <!-- 配置拦截器 -->

   <beanid="theAdvisor"       class="org.springframework.aop. support.NameMatchMethodPointcutAdvisor">

        <property name="advice">       

            <ref local="methodBeforeAdviceImpl"/><!-- 拦截器对象 -->

        </property>

      <property name="mappedName" value="*"></property>    <!-- 拦截所有方法-->

   </bean>

   <!-- dao 实例 -->

   <beanid="dao" class="com.helloweenvsfei.spring.example.DaoImpl">

   </bean>

   <!-- serviceImpl实例 -->

   <beanid="serviceImpl"      class="com.helloweenvsfei.spring.example.ServiceImpl">      <property name="dao"ref="dao"></property>        </bean>

<!-- service实例 -->

   <beanid="service"    class="org.springframework.aop.framework. ProxyFactoryBean">   

     <property name="interceptorNames" value="theAdvisor"></property><!--拦截器 -->     

      <property name="target">       <ref local="serviceImpl" />    </property><!-- 被拦截的对象 -->

   </bean>

206.    Spring 框架的组成如下图所示:

第27章 Spring的Core模块

207.    Core模块是Spring最核心的模块,实现加载配置文件、管理、初始化Beans等功能。(实现IoC功能,Spring 所有功能都是借助IoC实现的)

第28章 Spring的AOP模块

208.    AOP模块提供拦截器机制,允许自定义、配置方法拦截器、拦截的对象。

209.    Spring提供三种拦截器:方法前拦截器、方法返回后拦截器、异常抛出拦截器。

210.    代理模式是Spring中常用的设计模式。Spring提供代理类:ProxyFactoryBean和TransactionProxyFactoryBean(为前者子类)

第29章 Spring的DAO模块

211.    DAO模块提供JDBC支持,对JDBC进行封装,完全抛弃了JDBCAPI(无需与Connection、Statement、PreparedStatement、ResultSet等打交道),只需要继承JdbcDAOSupport类使用封装好的JdbcTemplate执行SQL语句。允许JDBC使用Spring的资源,并统一管理JDBC数据库连接和事务。

第30章 Spring的ORM模块

212.    ORM模块提供对常用ORM框架的管理。Spring支持Hibernate、MyBatis/JDO等各种ORM框架,Spring并不提供自己的ORM实现,只是对现有的ORM框架进行封装,管理。

213.    使用Spring+Hibernate时,Hibernate及其SessionFactory等只是Spring一个特殊的Bean,由Spring负责实例化与销毁。DAO层只需要继承HibernateDao Support 类,而不需要与Hibernate API 打交道(不需要开启、关闭Session等)。Hibernate配置也可以转移到Spring配置文件中。

第31章 Spring的Web模块

214.    Web模块提供对Struts、WebWork、JSF等各种Web框架的支持。Spring能够管理这些框架,并将Spring的各种资源如数据源、Beans等注射给框架。

215.    Spring整合Struts1.x有继承方式(继承Spring提供的ActionSupport类)和代理方式。继承方式较简单,但与Action代码与Spring代码发生了耦合,且Action并没有交给Spring管理,因此不能使用Spring的AOP,IOC等特性。代理方式没有这些问题。推荐使用代理方式,Spring支持Struts2.

第32章 Spring的MVC模块

216.    Web MVC模块是Spring提供的轻量级MVC实现,在Spring框架中可以使用Struts作为MVC框架,也可以使用Spring自带的MVC框架,SpringMVC与Struts等框架相比更加简洁、灵活

第33章 Spring开发实例(SSH、SSJ)

217.    IP地址库插件,查询实际地址:QQWry.data

第34章 EJB3概述

218.    Enterprise JavaBeans 3 简称EJB3,是sun的JavaEE服务器端组件模型,设计目标与核心应用是部署分布式应用程序。简单来说就是把已经编写好的程序(即:类)打包放在服务器上执行。凭借java跨平台的优势,用EJB技术部署的分布式系统可以不限于特定的平台。EJB适用于大型软件系统,比如证券系统,银行系统。EJB分类如下:

第35章 JPA规范

219.    JPA(Java Persistence API,Java持久化API)与Hibernate等框架一样,都是Java持久化解决方案,负责把数据保存金数据库,不同的是JPA只是一种标准,规范,而不是框架,JPA自己并没有具体的实现。

220.    JPA旨在规范ORM框架,使ORM框架有统一的接口,统一的用法。Hibernate、TopLink、OpenJPA都实现了JPA

第36章 WebService框架Xfire

221.    Xfire已于2007年与Celtix合并,整个成为Apache的CXF项目。

222.    java中length,length(),size()区别

1 java中的length属性是针对数组说的,获取数组的长度则用到了length这个属性.
2 java中的length()方法是针对字符串的,获取字符串的长度则用到length()方法.
3.java中的size()方法是针对泛型集合说的, 调用此方法来查看集合元素个数

第37章 版本管理工具SVN

第38章 日志工具commons-logging与log4j

223.    log4j应用最广泛。commons-logging没有日志功能,只是统一了JDK Logging(鸡肋)与Log4J的API,并把日志功能交给JDK Logging或者Log4j.

第39章 报表图形引擎JfreeChart

第40章 PDF组件iText

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值