java学习笔记————本质篇

<textarea readonly="readonly" name="code" class="java">

1.HTML:超文本标记语言!不是一种编程语言,是一种描述性的标记语言,用于描述超文本中内容的显示方式。比如字体、颜色、大小等。 // 显示数据  JSP也是最终响应回 一个HTML格式页面来显示数据!


2.CSS:层叠样式表!作用:定义网页的显示效果。简单一句话:CSS将网页内容和显示样式进行分离,提高了显示功能。
外联:<link href=“”/>引入的方式
ID选择器:#ID{ xxxx  }
类选择器:.class { xxxx }
后代选择器: .class ul(子) { xxxxx }
并集选择器: h1, h3, p, ul { xxxxx }
子元素选择器: h1 > strong { xxxxx }
属性选择器: h1[id][class] { xxxxx }
伪类顺序:(LoVe HAte原则)  a:link > a:visited > a:hover > a:active
字体属性的继承性(子-->父)   eg:在<body>中同一设置字体属性
优先级: 行内样式 > ID选择器 > class选择器 > 标签选择器 > *(通配符)选择器 > 继承的样式 > 默认样式


块级标签:独占一行或多行  <div>    <h1> <p> <ul> <ol> <li>  ===>互转 display:inline
行级标签:不占独立区域 多个行标签 可以共用一行 <span>   <strong> <a> <u> <s> <b> <i> <em> <del> <ins>      ===>互转 display:block


3.JavaScript:JavaScript是弱变量类型的语言. 弱变量类型:定义变量的时候变量,没有具体的类型.当变量被赋值的时候.变量才会有具体的数据类型.// JS都会由事件触发.
JS不是面向对象的 是基于对象. JS中的函数就是对象.
JavaScript中5种原始数据类型:
Undefined、Null、Boolean、Number 和 String
全等和非全等(===   !==)


4.Xml:是指可扩展标记语言(eXtensible——Markup——Language),它是一种标记语言,很类似HTML。 //  它被设计的宗旨是 传输数据,而非显示数据。
   应用场景(作用):1.保存数据;2.作为配置文件使用
4.a)DOM解析:需要读取整个XML文档
API:
NodeList nodeList = document.getElementsByTagName(String node);
Element element=(Element) nodeList.item(0);//可能涉及到强转
Element element = document.createElement(String element);
element.setTextContent(String content)
element.getTextContent()
element.setAttribute(String name,String value)
element.getAttribute(String name)


熟练dom解析xml的7种操作:
//1、得到某个具体节点的内容
//2、遍历所有节点
//3、修改某个元素节点的主体内容
//4、向指定元素节点中增加子元素节点
//5、向指定元素节点中增加同级节点
//6、删除指定节点
//7、操作XML文件属性






4.b)SAX解析:边读取边解析        // SAX 是事件驱动的 XML 处理方法  =====   基于事件驱动






dom4j工具类解析xml  // DOM4J解析XML是一级一级的解析   根 > 子 > 孙 > ...
用SAXReader对象的read()方法读取xml文件,得到的是dom4j的document对象(不是w3c)   ======>  new SAXReader().read("/.../abc.xml");   // Tips: 此处是文件
document  <==> String   互转:    document.asXML()  ==> String /    String.parseText(xmlString) ==> document


dom4j保存Document对象: // XMLWriter对象的write()方法(写入到本地磁盘中)
OutputFormat format=OutputFormat.createPrettyPrint()    // 格式化后的xml    // OutputFormat format = OutputFormat.createCompactFormat(); // 无格式化的
format.setEncoding("utf-8");
new XMLWriter(  new FileOutputStream("src/first.xml"),  format )
writer.write(document);  // 此document为 上文中用SAXReader对象解析本xml得到的 ---中途做了CRUD操作,完了再写回源文件
常用API:
Element getRootElement()Document的方法,用来获取根元素;
List elements()Element的方法,用来获取所有子元素;
String attributeValue(String name)Element的方法,用来获取指定名字的属性值;
Element element(String name)Element的方法,用来获取第一个指定名字的子元素;
Element elementText(String name)Element的方法,用来获取第一个指定名字的子元素的文本内容
int indexOf(Node node)Branch的方法,查找指定节点,在当前Branch的子节点集合中的下标位置。




XPath:是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。   // 导入jaxen 的jar包
selectNodes("xpath表达式")用来查找多个匹配xpath表达式的元素
selectSingleNode("/book/author") 用来查找一个匹配xpath表达式的元素




Schema约束: XML文档的约束,.xsd文件,用来替代DTD.




5.HTTP:即超文本传输协议。这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。(Hypertext Transport Protocol)
HTTP协议:(客户端)浏览器与服务器之间的通讯协议!协议不过就是一种格式!
http协议是建立在TCP协议基础上。http协议也是基于请求与响应的模型,http协议默认的端口是80.


/** 笔试题:GET与POST请求区别?
1. get只能传递1kb以下数据,POST可以传递大数据。
2. get请求如果有请求参数,那么,浏览器上会显示请求参数
post请求不会,所以post请求会更安全。
3. 如果是get请求,有请求参数,请求参数是在http请求行的资源路径上。
如果是post请求,有请求参数,请求参数是在请求正文中。——————————>并且有请求参数,才会有请求正文。
*/


1.请求协议:(发送给服务器看的,告知服务器:我的信息,我可以支持哪些技术,让服务器根据这些信息判断,并返回我支持展示的页面内容)
//  浏览器发送给服务器的内容就这个格式的,如果不是这个格式服务器将无法解读!
//  Tips:在HTTP协议中,请求有很多种请求方法,其中最为常用的就是GET和POST
请求行;
请求头信息;//Referer请求头是比较有用的一个请求头,它可以用来做统计工作,也可以用来做防盗链。
//Referer : 请求来自哪个页面,例如你在百度上点击链接到了这里,那么Referer:http://www.baidu.com;如果你是在浏览器的地址栏中直接输入的地址,那么就没有Referer这个请求头了;  ====> 就是说:从那个页面跳转到的本站
空行;
请求体      // 只能放POST请求参数 ——————> POST请求 + 且有请求参数POST请求是可以有请求体的,而GET请求不能有请求体
------> GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码;


//Content-Type请求头: application/x-www-form-urlencoded表单的数据类型,说明会使用url格式编码数据;
// url编码的数据都是以“%”为前缀,后面跟随两位的16进制,例如“中国”这两个字使用UTF-8的url编码用为“%E4%B8%AD%E5%9B%BD”;
   // URL编码 : URLEncoder.encode(String s, String enc)      //使用指定的编码机制将字符串转换为 application/x-www-form-urlencoded 格式。
   // URL解码 : URLDecoder.decode(String s, String enc)  //使用指定的编码机制对 application/x-www-form-urlencoded 字符串解码。
%EF%BC%9F ===== utf-8发现:直接地址栏输入中文,可能会在前面 添加此编码输入中国,发现前面多了3个url编码,经decode发现 值为utf-8
%EF%BC%9F%E4%B8%AD%E5%9B%BD


2.响应协议:(发送给浏览器看的)


响应首行;
响应头信息;
// 响应头:
Last-Modified:最后的修改时间;
// 请求头:
If-Modified-Since:把上次请求的index.html的最后修改时间还给服务器;
// 状态码:
304,比较If-Modified-Since的时间与文件真实的最后修改时间一样时,服务器会响应304,而且不会有响正文,表示浏览器缓存的就是最新版本!




//告诉浏览器不要缓存的响应头:
Expires: -1;
Cache-Control: no-cache;
Pragma: no-cache;


// response.setContentType("text/html;charset=utf-8"),   这个方法即规定了编码用utf-8,  同时还设置了content-type响应头,告诉浏览器用utf-8来解码.
// response.setHeader(“content-type”, “text/html;charset=utf-8”)
// response.setHeader("Refresh","5; URL=http://www.baidu.com")


空行;
响应体     // response对象的响应流 ————————> 对于http响应正文,它是真正被浏览器解析并显示在浏览器上的。   JSP————>HTML




HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文
1、状态行格式如下:
HTTP-Version Status-Code Reason-Phrase CRLF
其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。


状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求


常见状态代码、状态描述、说明:
200 OK      //客户端请求成功
400 Bad Request  //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden  //服务器收到请求,但是拒绝提供服务
404 Not Found  //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable  //服务器当前不能处理客户端的请求,一段时间后可能恢复正常


eg:HTTP/1.1 200 OK (CRLF)






6.1.Servlet:是一个资源,是一个java类,是运行在服务器上的。 sun的定义:它就是一个javax.servlet.Servlet接口。
作用:处理请求
接收请求数据;处理请求;完成响应


HttpServlet对Servlet接口的service()进行了重写 ==> 细分为doPost() 和 doGet() 两种请求


生命周期:1.创建servlet对象,常驻内存(我们一般会在web.xml中配置预加载,tomcat启动时就加载一个servlet对象到内存中   load-on-startup配置  1...> 10)
2.执行init(ServletConfig)方法,初始化配置文件等 //参数注入吧。。。 传递服务器创建的 ServletConfig对象   封装有context(全局)/init(局部)-param  初始化参数信息
  //配置在web.xml中的
3.执行servce()方法处理请求,每次都新开启一个线程(多线程,不安全)
4.tomcat正常关闭时,执行destroy()方法,销毁servlet对象
//通过查看HttpServlet类的service()方法,可以看到 请求方式除了GET 和 POST ,至少还有5种:DELETE、HEAD、OPTIONS、PUT、TRACE


在web.xml中配置servlet访问路径: 同一个servlet可以 有多个 映射存在(多个访问路径)


缺省: 没有对应的servlet<url-pattern>配置的页面,全部由缺省的servlet来处理其请求。(如:html页面)


访问服务端资源(servlet)的方式:
1.浏览器
2.form表单
3.<a href="#">访问资源</a>
4.js代码  location.href="#"


站外资源:http://www.baidu.com
站内资源:工程名+url-pattern值       (站内站外都使用绝对路径,不要用相对路径就是了)


静态:html
动态:jsp/servlet  asp  php         使用java来完成动态的web资源的开发




6.2.ServletConfig:ServletConfig它是Servlet的一个配置对象,是javax.servlet.包下的一个接口。
1.ServletConfig是由谁创建的?他是怎样传递到Servlet中的?
//ServletConfig对象是由服务器创建的,它是通过Servlet的init方法传递到Servlet中。


2.ServletConfig对象,它的作用是什么
a) 获取Servlet名称 getServletName()
b) 获取Servlet初始化参数 getInitParamete()  getInitParameterNames()
c) 获取ServletContext对象。 getServletContext()


3.我们如何获取一个ServletConfig对象?
// getServletConfig()   ======> this.getServletConfig();
// 通过查看 父类GenericServlet的源码,我们知道 GenericServlet 实现了ServletConfig接口,Servlet接口 -----重写init(ServletConfig)传入还保存了ServletConfig对象 ,
                                                    // 还另外给我们提供了一个无参init() , 有参init( ...调用了无参init())
// 它已经将服务器传递的ServletConfig保存了,并且对外提供了一个公共方法用于获取ServletConfig




6.3.ServletContext:web级域对象,是Servlet存在的环境,实现同一个web应用内的资源共享。//资源:Servlet                //它也是javax.servlet包下的一个接口。
1.一个web应用对应一个ServletContext,在web服务器启动时由服务器创建,通过它可以实现servlet之间的资源共享 =====> 域对象 // 同一个web应用中
   // 在服务器关闭时销毁
2.要想获取一个ServletContext可以通过ServletConfig来获取,方法是 getServletContext();
======> this.getServletConfig().getServletContext();  ==可以简化为==> this.getServletContext(); //原因自然是:GenericServlet底层做了封装
getRealPath()
//  主要使用getRealPath()方法:它的作用是获取工程中资源文件的绝对磁盘路径。
//  getRealPath("/")这代表的是一个绝对路径,它指向的是当前工程在tomcat下的绝对磁盘路径






7.request:开发中通过request对象来获取http请求信息及客户机信息 是Servlet.service方法的一个参数
在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中!!!我们利用request来操作http请求信息
// TomCat 默认通过HTTP协议的编码方式————ISO-8859-1对请求头、行、(体)进行编码,然后将编码后的请求信息 全部封装到———request对象中!!!


request的功能可以分为以下几种:
封装了请求头数据;
request.getHeader(String name)
request.getContextPath()        // 返回上下文路径,即工程路径,例如:/OneServlet
request.getServletPath()// 返回Servlet访问路径,url-pattern例如:/oneServlet


request获取请求参数的API:
String getParameter(String name):通过指定名称获取参数值;
String[] getParameterValues(String name):当多个参数名称相同时,可以使用该方法来获取;
Map getParameterMap():获取所有参数封装到Map中,其中key为参数名,value为参数值,因为一个参数名称可能有多个值,所以参数值是String[],而不是String。
Enumeration getParameterNames():获取所有参数的名字;


Getparameter: 浏览器端数据  -------- 参数// 从request对象中提取封装在它自身的参数信息
GetAttribute:  服务器端数据  -------- 属性  // request域共享数据




封装了请求正文数据,如果是GET请求,那么就没有正文;


request是一个域对象,可以把它当成Map来添加获取数据;
// request可以在一个请求中共享数据。   eg: 请求转发和请求包含
// 一个请求会创建一个request对象,如果在一个请求中经历了多个Servlet,那么多个Servlet就可以使用request来共享数据


request提供了请求转发和请求包含功能。  //表示:由多个Servlet共同来处理一个请求


request.getRequestDispatcher("/BServlet").forward(request, response); // 在AServlet中,把请求转发到BServlet:     tips:留(请求)头不留(请求)体


// 请求转发大多是应用在Servlet中,转发目标大多是JSP页面;   利用request域共享(传递)数据










request.getRequestDispatcher("/BServlet").include(request, response); // 在AServlet中,把请求包含到BServlet:   tips:AB共同完成响应头和响应体
 // 请求包含大多是应用在JSP页面中,完成多页面的合并;


7.2问题:请求参数乱码问题,它如何产生的,怎样解决?  // 服务端————的乱码问题
乱码产生的最根本的原因是在编码与解码时使用的是不同的编码表。
分析一下关于请求参数乱码问题:
简单说,就是浏览器使用了utf-8对汉字进行了编码,服务器使用了iso8859-1对象信息进行了解码。就出现了乱码。


解决乱码方案:
将得到的信息再以iso8859-1进行编码,使用utf-8进行解码就可以。




Get请求解决乱码问题: // reqeust.setCharacterEncoding(encoding) 仅对POST有效!  对GET是无效的!!!   编码内部处理是很复杂的,并不像表面上看的这么简单,
1. 修改conf/server.xml编码//这仅仅是我们去掉了中间复杂传输转换过程,有待深入研究!!!
<Connector port="80" protocol="HTTP/1.1"
  connectionTimeout="20000"
  redirectPort="8443" URIEncoding="utf-8"/>// 经测试,发现:仅修改此配置,对GET有效,但对POST却无效!! POST还需加 ————>
//   reqeust.setCharacterEncoding("utf-8")
2. New String() 进行编码(最多)
new String( name.getBytes("iso-8859-1"), "utf-8" );对get/post请求方式均有效. //前提:没有修改TomCat中conf/server.xml编码  ————否则,GET乱码
// 配置文件 和 new String() ————GET只能二选一     |对POST是无所谓的!


3. 通过js来对请求参数进行编码(了解) ——————> jsp页面的标签
<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
//  contentType:  1.告诉浏览器提交请求的编码方式
 2.解析页面的编码方式
// pageEncoding:1.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> //


如果我们的请求方式是post,我们也可以直接通过reqeust.setCharacterEncoding("utf-8")来处理请求参数乱码。
reqeust.setCharacterEncoding("utf-8")// 设置请求对象解码的编码为utf-8
//——————> 可能内部根据我们 传参encoding ,做了new String("编码",解码)


/** ***** GET和POST方式如何解决乱码:
* POST:
* 解决办法:
* request.setCharacterEncoding(“UTF-8”);
* GET:
* 解决办法:
* String name = new String(request.getParameter(“name”).getBytes(“ISO-8859-1”),”UTF-8”);
*/










8.response:response对象是用来对客户端进行响应的 是Servlet.service方法的一个参数,
在客户端发出每个请求时,服务器都会创建一个response对象,用来操作http响应信息。


response对象的功能分为以下四种:
设置响应头信息;
response.setHeader(“content-type”, “text/html;charset=utf-8”)
response.setHeader("Refresh","5; URL=http://www.it.cn")
发送状态码;
response.setStatus(200)


设置响应正文;(重点)    // 两个响应流对象     不能同时使用这两个流!!!
// PrintWriter out = response.getWriter():获取字符流;    eg: 响应文本  有缓冲区  默认8kb    response.flushBuffer()
// ServletOutputStream out = response.getOutputStream():  获取字节流;eg:下载


//  解决输出乱码问题: response.setContentType("text/html;charset=utf-8"),
//          这个方法即规定了编码用utf-8,同时还设置了content-type响应头,告诉浏览器用utf-8来解码.


 new String( name.getByte("iso-8859-1"), "utf-8" );对get/post请求方式均有效.


重定向;(重点)
//  response.sendRedirect("/day10/TwoRedirect") 方法会设置响应头为302,以及设置Location响应头






/** 请求转发与重定向比较(重点掌握)
请求转发是一个请求,而重定向是两个请求;
请求转发后浏览器地址栏不会有变化,而重定向会有变化,因为重定向是两个请求;
请求转发的目标只能是本应用中的资源,重定向的目标可以是其他应用;
请求转发对AServlet和BServlet的请求方法是相同的,即要么都是GET,要么都是POST,因为请求转发是一个请求;
重定向的第二个请求一定是GET;*/










9.jsp:JSP是JavaWeb服务器端的动态资源。它与html页面的作用是相同的,显示数据和获取数据。  (Java Server Pages)  // JSP 最终是响应回 HTML页面  来显示数据的!!!
jsp是一种特殊的Servlet,当JSP页面首次被访问时,容器(Tomcat)会先把JSP编译成Servlet,然后再去执行Servlet。所以JSP其实就是一个Servlet!//  Sun公司推出的jsp技术


1.Jsp原理:
1. 当浏览器向服务器发送请求访问demo1.jsp页面
2. tomcat的web.xml文件中配置了一个JspServlet,它会对所有后缀名是*.jsp的路径进行处理
3. 会将demo1.jsp翻译成demo1_jsp.java文件,这个文件存储在tomcat/work目录
4. 会将demo1_jsp.java文件编译成demo1_jsp.class文件,服务器会将其加载运行
5. 在jsp页面生成的java文件中就会通过 流 将jsp页面的html代码写回到浏览器端,所以我们在浏览器上就看到了jsp中的html代码显示的效果。




注意:要知道<%  %>和<%! %>在jsp“真身”中的位置:
在_jspService()方法中间以 java代码原型存在


JSP脚本:JSP脚本就是Java代码片段,它分为三种:// 明确一点:所有的这些都是 在_jspService()方法内_jspService()内定义了9个:我们俗称的9大内置对象
<%...%>:Java语句;// 方法中能放什么,它就能放什么。
<%=…%>:Java表达式;// 等同于resopnse.getWriter().print()。写到这里的东西,都是用来输出的!
<%!...%>:Java定义 类的成员变量;// 类能包含什么,它就可以包含什么。    声明成员变量的标签 ,注意: 声明标签中 没有9大内置对象!


JSP注释:<%-- jsp注释 不会保留 --%><!--html注释 会被保留-->




Jsp与servlet区别:
Jsp它的主要作用是用于显示数据。
Servlet它的主要作用是用于处理请求完成业务逻辑操作。






2.九大内置对象: // 来历 _jspService()方法内给我们声明了9个:我们俗称的9大内置对象直接在<% java代码 %>中使用
1. application  类型是 ServletContext
2. session      类型是 HttpSession
3. request      类型是 HttpServletRequest
4. pageContext  类型是 PageContext
5. response     类型是 HttpServletResponse
6. config  类型是 ServletConfig
7. page    类型是 Object
8. out      类型是 JspWriter
9. exception    类型是 Throwable




3.四大域对象: // 也是 EL 的内置对象
1.pageContext:它代表的是page域,但是jsp中page它的类型是Object,所以操作page域我们使用的是pageContext对象,page域就是指当前页面范围
2.request : 它是代表整个请求链
3.session: 整个会话
4.application:整个web应用


servlet中有三个域对象:
HttpServletRequest  整个请求链
HttpSession         整个会话
ServletContext      整个web应用。


对于域对象它们都具有以下方法<% java代码 %>
setAttribute(String name,Object value)
getAttribute(String name)
removeAttribute(String name)


4.pageContext对象作用:—————————————— java代码 操作 域/对象     jsp中写java脚本,已被淘汰————————被EL替代
1.获取其它八个内置对象 // 我们在开发中可以将pageContext对象  作为参数  传递到java类中,在java类中就可以  根据需求来  获取想要的web对象。
2.操作page域及其它域    // ~.setAttribute("pname", "pvalue")    /  ~.getAttribute("rname",PageContext.REQUEST_SCOPE)   /  pageContext.findAttribute("rname")
 // 快速查找: 在 page < request < session < application 范围依次查找,如果没有查找到返回null.
实际开发中用法: ${pageContext.request.contextPath} ==》pageContext.getRequest.getContextPath() ——————> 获取当前工程名


out对象:将信息输出到页面上
out对象它是一个JspWriter,它是一个字符输出流,它的作用就是将信息输出到页面上。
out对象与response.getWriter()区别?   //response.getWriter() 输出优先级别 > out


out缓冲区 ————> response缓冲区 ————> 页面  //  真正操作响应正文的其实是response  //  在jsp页面上要想显示信息,建议只使用out.


Exception:
它就是一个异常对象,描述的是当前页面产生的异常信息,它只有在 page指令 设置为 isErrorPage 时才会存在。








5.jsp指令:
1. page指令:这个指令用于描述页面的一些特性   <%@page language="java" import="java.util.*" pageEncoding="UTF-8" isErrorPage="true" %>
/** page指令中重要属性
import: 用于在jsp页面上使用java类时导入包
encoding: 用于指示jsp页面翻译后的java文件的编码,其实也就是当前jsp页面编码
contentType: 用于指示jsp页面生成的servlet中response获取输出流输出信息的编码
简单说,就是用于设置response.setContentType();


encoding 与contentType属性的关系:
它们互相依赖,只要设置一个,另一个就参考对方值。


language:它代表的是jsp页面上脚本中可以使用的语言


extends:它的作用是指示jsp生成的java类它的父类


session:它的值是true/false,如果是true,代表在jsp页面中可以直接使用session,否则不可以使用。


isElIgnored:它的值是true/false 指示的是jsp页面上是否可以使用el表达式,如果是true,就不能使用el表达式,否则就可以使用.


errorPage 用于设置错误页面,jsp页面如果出现问题,可以直接跳转到errorPage指定的页面


isErrorPage值可以取true/false指示当前页面是一个错误页面,也就是说,取true时可以在当前页面中直接使用jsp内置对象exception,


在开发中,我们一般很少使用 errorPage与isErrorPage,我们一般会使用全局错误页面处理方案:
我们可以在web.xml文件中配置错误页面。




autoFlush与buffer
它是 jsp页面生成的 java文件中out对象默认缓存区大小及是否自动刷新。*/


2. include指令:静态包含。在jsp页面中静态包含一个文件,这个文件可以是任意文件,同时由jsp解析包含文件内容. <%@include file="demo2.jsp"  %>


包含操作有什么作用?
使用包含,可以对页面进行布局。// 将两个页面 合并成一个页面


静态包含的注意事项:
1. file属性的值不能是变量
2. file属性值不可以携带参数




3. taglib指令:导入标签库, 如:jstl标签库<%@taglib  uri="http://java.sun.com/jsp/jstl/core" prefix="c"  %>




6.Jsp标签: // 业务逻辑处理   —————— Service层
Jsp中标签也叫jsp action(动作标签),用于在jsp页面中提供业务逻辑处理,避免在jsp页面中书写脚本。
我们现在所说的jsp标签,是jsp页面内置的,可以直接使用。<jsp:标签名称 属性=值 >




<jsp:forward>用于请求转发,它与RequestDispatcher接口中的forward方法一样,唯一不同的就是在jsp页面中使用。 // 避免在jsp页面写<% java代码 %>    在 web.xml
// 的struts核心配置  中开启<dispatcher>FORWARD</dispatcher>
<jsp:param> 用于页面传递数据,简单说,就是用于生成参数。


<jsp:include>这个标签的作用与jsp中include指令功能是一样的,都是包含操作,只不过我们叫include标签为动态包含。


Jsp中静态包含(include指令)与动态包含(include标签)区别?
1. 静态包含包含的是内容,而动态包含包含的是结果。
2. 静态包含不可以传递参数 ,而动态包含可以传递参数




7.EL表达式:它是jsp内置的一种表达式语言,从jsp2.0开如,就不让再使用java脚本,而是使用el表达式来替换jsp中java脚本。(expression Language)
主要作用是:代替jsp页面上的<%=%>,向浏览器输出数据.  eg:${1+2}向浏览器输出3.


格式:  ${表达式}


/** 为什么使用el表达式?
主要目的是为了替换jsp页面上的脚本,使jsp更加简单,安全。
EL主要作用:
1. 获取数据(主要是域中数据)
2. 执行运算
3. 获取web常用对象
4. 调用java方法(EL函数)*/


jsp2.0规范    —————— servlet版本是servlet2.4 —————— javaEE1.4


1.El表达式获取数据: // 使用el表达式获取时,如果没有查找到结果, 返回的 不是null, 而是一个 "".
1. page域 ----------------------${pageScope.name}
2. request域 ----------------------${requestScope.name}
3. session域 ----------------------${sessionScope.name}
4. application域----------------------${applicationScope.name}


EL获取域中数据可以省略范围 ${requestScope.rname}   ---------  ${rname}  page > reqeust > session > application 依次查找


在el中使用"."与[]可以实现同样的效果: ${xxxScope.对象.属性}   =    ${xxxScope["对象"]["属性"]}  //——————全都是用名称去找,不要混淆去用getXXX()方法.
问题:  .与[]有什么区别? // <%= request.getXXX().getXXX()%> 这里才用java代码
注意: 如果名称中不包含特殊符号,那么.与[]一样,但是如果名称中包含了特殊符号,那么我们就只能使用[].




/** 2. EL执行运算:
在el表达式中可以使用运算符来进行操作
1.算术运算符 + - * /(div)  %(mod) ——————取余
对于算术运算符注意+,它永远执行的就是加法运算。


2.关系运算符  >(gt) >=(ge) <(lt) <=(le) == (eq) !=(ne)
执行关系运算它得到的结果就是boolean


3.逻辑运算符
&&(and)  ||(or)  !(not)
执行逻辑运算得到的结果也是boolean


4.三目运算符
(表达式1)?(表达式2):(表达式3)
它与java中的三元运算符一样。


5.empty
i. 如果是一个普通对象,它判断对象是否为null,如果为null返回true.否则返回false.
ii. 如果是一个容器(数组或集合),它不仅判断对象是否为null,还判断是否有元素。*/


/** 3. EL十一大内置对象:// 我们在el中使用pageContext一般使用:${pageContext.request.contextPath}


pageScope  requestScope  sessionScope  applicationScope


pageContext 它与jsp页面上内置对象pageContext一样。


获取 http请求信息 的6个内置对象:
param: 获取一个Map<String,String>  key就是请求参数名称,value是值
paramValues: 获取一个Map<String,String[]>它与request.getParameterMap()结果一样。


header: 获取一个Map<String,String>它封装的是所有的http请求头信息
headerValues: 获取一个Map<String,String[]>它封装的是所有的http请求头信息


initParam 获取一个Map<String,String>它封装了所有的全局初始化参数


cookie: 获取一个Map<String,Cookie> 它封装了所有的http请求的中cookie信息,key就是cookie的名称,value就是这个cookie对象。


*/




4.El函数:Jstl标签库,在jstl标签库中有已经定义好的一些EL函数。在jsp页面上要使用EL函数必须导入jstl标签库。
     本质是:调用了一个java类的方法。 //   <%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>


注意:如果在开发中,我们使用的不是myeclipse,那么我们在使用el函数时,必须导入jstl的jar包。
因为我们使用的是myeclipse,它会默认导入javaee5.0的库,在这个库中包含了jstl标签库的jar文件,所以不用导入了。








8.JSTL标签库:






8.2.javaWeb设计模式:
jsp设计模式: jsp+javaBean       /       jsp+servlet+JavaBean            // Sun公司在推出jsp后,提供的两种jsp开发模式
// <Jsp:userBean id="" class="" /><Jsp:get/setProperty   property=""   name=""/>
javaBean介绍: 一个javaBean它应该是具有无参数构造,并且属性private,对外提供get/set方法让其访问,一般javaBean是可序列化,也就是说,它要实现序列化接口。


在javaweb开发中,javaBean的主要功能是什么?
javaBean可以分为两种,一种是用户界面的UI 的javaBean , javaweb中使用的不是这一种。
另外一种它没有用户界面,主要负责处理数据封装,jsp中通常使用的是这一种, 我们在实际开发中,所使用的javaBean主要是用于 将数据进行封装操作。


Beanutils: 我们可以使用beanutils工具来完成请求参数封装。 // 底层是使用java内省机制,而内省它的实现是依赖于java反射。
它是apache开发的一套用于 操作javaBean的API, 通过这套API,可以简化我们操作javaBean代码的编写。
API:
Beanutils.populate(user , request.getParameterMap())  // 参数1:javaBean对象参数2:所有的请求参数的map集合




Web开发的三层架构与mvc区别?// 先架构,再选模式
三层架构它是一个分层式的体系架构设计,它可适用于任何一个项目,MVC它只是一个设计模式,它是根据项目的具体需求来决定是否适用于该项目。
在开发,首要对项目进行架构,在架构以后,我们要根据具体的需求,来选择设计模式。例如mvc  工厂模式等。


MVC设计模式: MVC全名是model  view  controller
它是一种软件设计典范,用一种业务逻辑,数据,界面分离的方式来组织代码,将业务逻辑聚集到一个部件中,方便程序的重用,提高我们的开发效率。
M:model 即模型层,维护数据提供数据的访问 javaBean // 业务处理: service / dao / POJO
V:view 即视图层 数据的显示  jsp// 显示数据:html / jsp 
C:controller 控制层,用于业务处理。Servlet// 接收请求 + 响应结果 :servlet / filter

eg: struts2框架 、 SpringMVC ...

// 注意:Model并不是单纯的指POJO.  Model是指业务逻辑处理——————service/dao/POJO/甚至action也可以算model








8.3.i18n国际化:




10.Cookie:Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。
客户端会保存Cookie,并会标注出Cookie的来源//哪个服务器的Cookie
当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了


Cookie是服务器送给浏览器的小纸条!保存在客户端的!
当客户端再次发出请求时,会把这个服务器的cookie归还给服务器!服务器通过cookie来识别客户端状态! // 根据服务器,来区别发送cookie




Cookie的覆盖:如果服务器端发送重复的Cookie那么会覆盖原有的Cookie


Cookie添加与获取:客户端访问AServlet,AServlet在响应中添加Cookie,浏览器会自动保存Cookie。然后客户端访问BServlet,这时浏览器会自动在请求中带上Cookie
Cookie cookie = new Cookie("id", id);
response.addCookie(cookie);//响应cookie 到浏览器端  保存在浏览器端!


Cookie的生命: Cookie在客户端的有效时间
cookie.setMaxAge(-1) // 表示只在浏览器 内存中 存活。  一旦关闭浏览器窗口,那么cookie就会消失。
cookie.setMaxAge(0)  // 它表示cookie被作废!       作删除操作
cookie.setMaxAge(60*60)  // 表示cookie对象可存活1小时     当生命大于0时,浏览器会把Cookie保存到硬盘上


Cookie中根本不能保存中文: 除非先编码  再解码






11.Session:我们可以把一个会话内需要共享的数据保存到HttSession对象中!session底层是依赖Cookie的!!!     // javax.servlet.http.HttpSession接口表示一个会话


获取HttpSession对象:
request.getSesssion()  // 如果当前会话已经有了session对象那么直接返回,  如果当前会话还不存在会话,那么创建session并返回;
request.getSession(boolean)   // 当参数为true时,与requeset.getSession()相同。  如果参数为false,那么如果当前会话中存在session则返回,不存在返回null;


HttpSession是域对象:  // 下面三个是 Servlet中 可以使用的 域对象  而JSP中可以多使用一个域对象 pageContext
ServletContext:一个项目只有一个对象    //一个应用只创建一个ServletContext对象,所以在ServletContext中的数据可以在整个应用中共享,
//  只要不重启服务器,那么ServletContext中的数据就可以共享
HttpSession: 一个会话只有一个对象 //一个会话创建一个HttpSession对象,同一会话中的多个请求中可以共享session中的数据
HttpServletRequest:一个请求只有一个对象    //一个请求创建一个request对象,所以在同一个请求中可以共享request


API:
setAttribute(String name, Object value)
getAttribute(String name)
removeAttribute(String name)
getAttributeNames()




void setMaxInactiveInterval(int interval):设置session允许的最大不活动时间(秒),如果设置为1秒,那么只要session在1秒内不被使用,那么session就会被移除;


void invalidate():让session失效!调用这个方法会让session失效,当session失效后,客户端再次请求,
服务器会给客户端创建一个新的session,并在响应中给客户端新session的sessionId;




String getId():获取sessionId,其实它就是一个UUID,32位长的字符串;
int getMaxInactiveInterval():获取session可以的最大不活动时间(秒),默认为30分钟。当session在30分钟内没有使用,那么Tomcat会在session池中移除这个session;
long getCreationTime():返回session的创建时间,返回值为当前时间的毫秒值;
long getLastAccessedTime():返回session的最后活动时间,返回值为当前时间的毫秒值;




boolean isNew():查看session是否为新。当客户端第一次请求时,服务器为客户端创建session,
但这时服务器还没有响应客户端,也就是还没有把sessionId响应给客户端时,这时session的状态为新。




session的实现原理:
session底层是依赖Cookie的!// 服务端 session 与 sessionID绑定   客户端通过响应回的cookie("sessionID",sessionID)  在下一次请求时,通过发送此cookie,让服务端识别
1:首次访问服务器,创建一个session对象,存放到session池中。再把session的id保存到cookie中发送给浏览器。  //cookie("sessionID",sessionID)
2:浏览器保存的sessionId。session则保存在服务器中
3:当客户端再次访问服务器,客户端会归还cookie,即sessionId
4:服务器再通过sessionId知道对应的session 对象,进行操作.
5:保存sessionId 的cookie 是内存cookie,浏览器关闭,cookie 没了。 // cookie.setMaxAge(-1)


session与浏览器:
session保存在服务器,而sessionId通过Cookie发送给客户端,但这个Cookie的生命只能是-1,即只在浏览器内存中存在.
当用户再次打开浏览器访问服务器时,就不会有sessionId发送给服务器,那么服务器会认为你没有session,
所以服务器会创建一个session,并在响应中把sessionId保存到Cookie中发送给客户端。     
你可能会说,那原来的session对象会怎样?
当一个session长时间没人使用的话,服务器会把session删除了!
这个时长在Tomcat中配置是30分钟,可以在${CATALANA}/conf/web.xml找到这个配置,当然你也可以在自己的web.xml中覆盖这个配置!






















































9.获取资源相关方法:
1.获取真实路径:
servletContext.getRealPath("/WEB-INF/b.txt")         ====> String realPath


2.获取资源流: // 即把资源以输入流的方式获取
servletContext.getResourceAsStream("/WEB-INF/b.txt") ====> InputStream is


3.获取指定目录下所有资源路径:
servletContext.getResourcePaths("/WEB-INF");====> Set<String> set


4.获取类路径下资源:  // 获取类路径资源,类路径对一个JavaWeb项目而言,就是/WEB-INF/classes(java代码会加载到此)  和 /WEB-INF/lib/每个jar包!
1.Class类 的getResourceAsStream(String path):
路径以“/”开头,到  classpath(classes路径)下  去加载
路径不以“/”开头,到当前Class对应的  .class文件所在目录  下去加载      例如在cn.it.servlet.MyServlet中执行,
=====>即到 /classes/cn/it/servlet/下去加载资源;
2.ClassLoader类 的getResourceAsStream(String path):
ClassLoader获取资源时,不能以"/"开头


















11.JavaWeb的三大组件:
1.Servlet
2.
3.


12.JavaWeb的四大域对象:   // 所有域对象都有存取数据的功能     域对象内部都有一个Map
1.PageContext //jsp
2.ServletRequest客户端向服务器发送请求作出了响应之后
3.HttpSession 服务器端第一次调用getSession() session过期了、invalidate()、非正常关闭服务器 (正常关闭服务器HttpSession序列化到硬盘)
4.ServletContext服务器启动的时候创建ServletContext对象.服务器正常关闭的时候
















17.Mysql数据库:数据库就是一个文件系统,但是这个文件访问需要通过标准SQL语句.


1.关系型的数据库:
保存的是实体之间关系.


常见的关系型数据库: MYSQL、SQLServer、Oracle、DB2、SyBase、SQLite




2.MYSQL内部存储结构:
一个软件对应一个数据库,在数据库内部可以存在多张表:一个实体类对应一张表.表中可以有多条记录的.
一般情况下:一个类的实例对应一条记录.


3.SQL:结构化查询语言.(Structured Query Language)
特性:
非过程性语言:一条语句的执行,就会有一个结果.不需要依赖其他语句.


/** SQL的分类:
* DDL :Data Definition Language.数据定义语言.  // 无事务
* create 、alter、drop ...


* :Data Manipulation Language.数据处理语言. //事务
* update 、 insert 、 delete...


* DCL :Data Control Language.数据控制语言.
* if 、grant...


* DQL :Data Query Language.数据查询语言.
* select




SQL对数据库 进行操作:(CRUD)// 属于DDL语句


create database 数据库名
drop database 数据库名;
show databases;
alter database 数据库名 character set 字符集 collate 校对规则;
use 数据库名;
select database();






SQL语句对数据库中 表 进行操作:(CRUD)  // 属于DDL语句-


create table 表名 (字段名 字段类型(长度) 约束,字段名 字段类型(长度) 约束..)character set 字符集 collate 校对规则;// char:固定长度varchar:可变长度
// long = BIGINT       boolean = BIT        byte = TINYINT     short = SMALLINT
// File = BLOB/TEXT   BLOB :存放一个二进制文件.  TEXT:存放一个文件文件.        在Oracle数据库中用BLOB和CLOB
show tables;  desc 表名;
drop table 表名;// 删除整个表      truncate table 表名: 删除整个表,创建一个新的表    DDL 无事务
// delete 是一条记录一条记录的删除DML 有事务回滚*/


SQL对数据库中表中的记录进行操作:(CRUD)// 属于DML语句(insert,update,delete)
/*有事务*/
insert into 表名 (字段名1,字段名2,字段名3...) values (值1,值2,值3...);
insert into 表名 values (值1,值2,值3...);// 字符串或者日期类型   单引号引起来


update 表名 set 字段名 = 值,字段名=值 [where 条件];


delete from 表名 [where 条件];
truncate table 和delete  from 区别  逐条删/整表删


select 表达式 from 表;like:模糊查询. 占位符:_和%    is null  / is not null   and , or ,not         in:一组值
order by 列名 asc/desc;group by 列名;
count(*) sum(math) avg(math)  max(math) min(math)
where => having group by product having sum(price) > 2000;  //where后使用聚合函数  where => having


*   select *|列名 from 表名 where 条件 group by 列名 having 分组条件过滤 order by 列名;
// 列:group by有哪些列,select下才能写哪些列 (除此,还可以写count()、sum()...聚合函数)
//  分组:group by后 再加 分组条件 ,用having   也是前后对应 ,后面写啥,前面才能写啥


SQL语句的多表操作:


笛卡尔积查询:select * from A,B;
内连接:inner join.// 交集
隐式内连接:select * from A,B where 条件;
显式内连接: select * from A inner join B on 条件;//inner 可以省略
外连接:outer join
左外连接:// 左边表的全部以及两个表的交集        select * from A left  outer join B on 条件;    A:A表数据会全部显示  ==> 全量表
右外连接:// 右边表的全部以及两个表的交集select * from A right outer join B on 条件;  B:B表数据会全部显示  ==> 全量表


子查询:指的是一条语句的查询结果需要依赖另一条语句的查询结果.// any:任意一个.  all:所有.






18.JDBC:Java语言连接数据库!是一种用于执行SQL语句的Java的API.可以为多种关系型数据库提供统一的访问.(Java DataBase Connectivity    Java数据库连接). 是一个总的数据库连接概念!! !
JDBC就是SUN提供规范,厂商提供实现!我们就使用其API来操作数据库!


由Java语言编写
功能:主要就是使用Java语言连接到数据库.
使用:只要与数据库交互
驱动:java连接数据库,必须使用数据库的驱动
JDBC规范:SUN提供接口,数据库厂商提供实现!===> 即:提供各自数据库的 API


JDBC的API:
反射: Class.forName("...")
连接对象:Connection  <——— DriverManager
1.创建执行SQL语句的对象: prepareStatement(sql) / ...
2.进行事务的管理: commit() / rollback() / setAutoCommit()
执行SQL的对象:Statement
executeQuery() / executeUpdate() / execute()
结果集:ResultSet
//在ResultSet内部维护了一个指向表格数据行的游标Cursor,初始化时候,游标在第一行之前的位置.调用ResultSet中next()方法.可以使游标指向具体的数据行,进而调用方法获得该行的数据
next()  /   getInt(..)  /   getString(..)   / getObject(..)
滚动结果集:  MYSQL数据库结果集可以滚动.   创建时设置参数即可: createStatement(int resultSetType,int resultSetConcurrency);   // 默认是不可
释放资源: close() // 晚创建,早释放!!!


JDBCUtils:解析jdbc.properties文件 , 获取连接 , 关资源//原始JDBC,是手动创建连接,销毁连接!—————从连接池获取连接———> C3P0、DBCP(获取连接,归还连接,创建交给连接池管理)
SQL注入的漏洞:PreparedStatement对象预编译sql
配置文件: jdbc.properties文件


1.2数据库连接池:就是一个装有很多连接的一个容器.使用连接的时候,直接可以从连接池中获取.用完以后归还给连接池.    // 提升程序的性能.对程序进行优化


DBCP:数据库连接池。 (DataBase connection pool)
是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。单独使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar
由于建立数据库连接是一个非常耗时耗资源的行为,
所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。
API;  BasicDataSource: 用于手动配置DBCP连接池.
    BasicDataSourceFactory: 使用配置文件的方式配置连接池.  // 半自动解析
配置文件: dbcp.properties文件




C3P0:是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。
----- C3P0包内部自动识别"c3p0-config.xml"文件,并自动解析,这也是一种规范(C3P0规范)  在java中我们可以见到很多规范!!!   ————>这也是C3P0好用的一个体现
  当然,我们也是可以手动赋值的,ComboPooledDataSource类中就提供了所有的setXXX()方法


API: ComboPooledDataSource      (连接池类)  //重写了 conn.close()  归还连接     
// 这个类就是一个连接池容器,为我们封装了很多连接,并提供了getConnection()      我们直接从此对象中获取连接
使用C3P0连接池改造JDBC的工具类:
配置文件: c3p0-config.xml// 自动解析




Tomcat内置JNDI连接池: Java命名和目录接口,将一个对象与一个名称进行绑定,通过名称查找到指定的对象.






Service的事务:事务要加在业务层. 因为在DAO中不是开启事务的最好的地方.
一个业务层中需要调用多个DAO中的方法的时候,那么每个DAO中的Connection都不是同一个对象.
不是同一个对象的话,开启的事务就不会在同一个事务中.






1.3事务:指的是逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败!


MYSQL中事务管理:  MYSQL数据库事务是自动提交.执行一条SQL后,事务就会被提交.


1.MYSQL命令: // 用 Mysql数据库 自身的命令 !!!      ——————>直接
使用MYSQL中命令进行事务的管理:
* start transaction;--开启事务.
* 执行操作
* commit; --提交事务.
* rollback; --回滚事务.


修改参数:
查看MYSQL中的与commit相关参数,通过修改参数的方式进行事务的管理.
SHOW VARIABLES LIKE '%commit%';
set autocommit = 0;  --0:OFF1:ON(默认)




JDBC中事务管理: // 用 java代码 操作数据库的方式!!! ——————>间接
1.API: // 用 Connection 对象操作
setAutoCommit(boolean autoCommit);  true:自动  /  false:手动 ————>等同于  start transaction(mysql命令) 开启了一个事务
commin()  / rollback()


2.事务管理的保存点: 类似于游戏中的存档.
setSavepoint()    /   rollback(savepoint)




3.事务的特性:(面试)
原子性:(Atomicity)
原子性:强调事务的不可分割.
一致性:(Consistency)
一致性:事务在执行的前后,数据的完整性保持一致.
隔离性:(Isolation)// 安全问题!!!      并发
隔离性:多个事务并发执行的时候,一个事务的执行不应该受到其他的事务的干扰.
持久性:(Durability)
持久性:事务如果结束了.数据就永久的保存到数据库.


4.不考虑事务的隔离性.引发一些安全性问题:  // 都是在一个事务内的问题    我们的解决思路就是:限制你在本次事务内的读取,必须新开事务才能获取到更新数据!!!
3类读问题:
脏读 : 一个事务读到了另一个事务未提交的数据. //那就让他 只能读取 已提交 的数据
不可重复读 :   一个事务读到了另一个事务已经提交的update的数据,导致在一个事务中多次的查询结果不一致.  //那就让他 可以重复读取 在提交前后读取的数据不变
//不可重复读:可解释为————当B提交update事务后,A 就不能再读取!!! 若A非要再读取,就会导致~~~  so,我们命名为:不可(以)重复读!!!
虚读/幻读 :一个事务读到了另一个事务已经提交的insert的数据,导致在一个事务中多次查询的结果不一致.  //那就让他 可以串行化读取----必须等待对方
//提交事务后,才会执行这边的事务


解决读问题: 数据库中提供了 事务的隔离级别!!!
// 此处隔离级别的设定,自然是针对查询者B而言
* read uncommitted:未提交读.  脏读、不可重复读、虚读 都是有可能发生.// A不提交   B也能查到 数据被修改了
//并发访问
1.此时只要A执行了SQL语句,无论是update、还是insert,且无论是否提交了事务,B每次都能查询到被A更新的数据!!!
// 当A 执行sql语句前 B读到1,当A 执行了sql 但未提交前   B读到2 , 当A提交后 B读到2  A 还没有提交 B就获取了数据更新!!!




* read committed:已提交读.  避免脏读.但是 不可重复读、虚读 是有可能发生.  (开发用) // A必须提交   B才能读到
// 并发访问
1.避免脏读: // 当A update未提交前 B读到1 , 当A提交后 B读到2只有A提交了事务,B才能获取到新的数据!


1.不可重复读: //  当A update未提交前 B读到1 , 当A提交后 B读到2     导致B在同一个事务中,两次查询的结果不同
2.虚读: //当A insert未提交前 B读到1 , 当A提交后 B读到1,2   导致B在同一个事务中,两次查询的结果不同




* repeatable read:可重复读.  避免脏读、不可重复读.但是 虚读 是有可能发生.// A update就算提交   B也读不到 除非重开事务
// 并发访问
1.避免了脏读、不可重复读:
// 当A update未提交前 B读到1 ,  当A提交后 B仍然读到1


1.虚读: //当A insert未提交前 B读到1 ,  当A提交后 B读到1,2导致B在同一个事务中,两次查询的结果不同




* serializable:串行化的.  避免脏读、不可重复读、虚读的发生.// A  insert不提交   B查询只能一直等待    不可并发访问!!!
// 直接不让 并发访问!!!
// 只能排队 一个一个来
1.避免了脏读、不可重复读、虚读:
// 当A update未提交前 B等待A提交,  当A提交后 B读到更换后的数据
// 当A insert未提交前 B等待A提交,  当A提交后 B读到更新后的数据


serializable:是串行的.一个事务没有结束.另一个事务不会执行的.(不存在事务的并发访问情况.)
//  当A 执行了insert命令,但未提交前, B的select事务   必须一直等待A 提交事务之后, B的访问事务才会执行!!!
  serializable的一方  没有并发访问————需等待!!!
  增删改——————可并发执行——————无需等待!!!


//  且若B 执行了DML指令   A也是要等待B提交事务之后,才会执行B的sql(事务)!
 非 serializable的一方 并发访问的 可直接执行select操作!!!
增删改————不并发  , 需等待!!!


* 安全性:serializable > repeatable read > read committed> read uncommitted
* 效率性:read uncommitted > read committed > repeatable read > serializable


***** MYSQL数据库默认隔离级别:repeatable read .Oracle数据库默认的隔离级别:read committed


* 查看当前数据库的隔离级别:
* select @@tx_isolation;
* 设置事务的隔离级别:
* set session transaction isolation level 隔离级别;






2类写问题:  // 都叫:丢失更新
--- A修改了name,未提交前, B又修改了money,未提交.     A提交后,B再提交或者回滚的时候,都会将之前事务修改的字段的值覆盖掉 .


解决丢失更新:
* 悲观锁:假设丢失更新是一定存在.使用了数据库中的一种锁机制.(排它锁)
* 乐观锁:假设丢失更新不一定存在.使用是时间戳或者版本号解决方案.




3.元数据:在JDBC的程序中获得数据库,表,表中的字段的信息.
1.为什么要学习元数据?
编写一些通用性较高的代码,编写一些框架.


2.元数据的分类:
数据库元数据:DatabaseMetaData// 通过Connection中的方法获得:  conn.getMetaData();
API:(API即功能)
* 获得连接基本信息: getDriverName()  /  getURL()  /   getUserName()
* 获得数据库中表的信息: getTables()


参数元数据: ParameterMetaData // 通过PreparedStatement中方法获得:    stmt.getParameterMetaData();
API:
* 用来获得SQL语句中的参数的个数,参数类型. getParameterCount() /  getParameterTypeName(i) ————>// MYSQL数据库对参数元数据获得类型名称支持的不好!!!
  ————>// 这可以帮我们很好的理解,java中动态注入参数的方法args[]


结果集元数据:ResultSetMetaData  // 通过ResultSet中的方法获得:          rs.getMetaData();
API:
* 获得列的个数,列的类型,列的名称:getColumnCount() / getColumnName(i) / getColumnTypeName(i)


4.DBUtils:Apache组织提供的一个对JDBC进行简单封装的开源工具类库,简化JDBC应用程序的开发.//commons-dbutils-1.4.jar
1.核心类:
DbUtils
API:  commitAndCloseQuietly(conn) / rollbackAndCloseQuietly(conn)
QueryRunner
构造:  new QueryRunner() // 使用没有传入DataSource的构造方法:(带有事务的操作:需要手动操作)
new QueryRunner(DataSource)   // 使用传入DataSource的构造方法:    (不带有事务的操作:每条SQL————独立事务)


API: update(增删改)  /  query(查)


2.ResultSetHandler的实现类:


ArrayHandler / ArrayListHandler  ————> 将一/多条记录封装到一个装有Object数组的List集合中Object[] / List<Object[]>


BeanHandler  / BeanListHandler————> 将一/多条记录封装到一个装有JavaBean的List集合中Account  / List<Account>


MapHandler   / MapListHandler————> 将一/多条记录封装到一个装有Map集合的List集合中Map<String, Object> / List<Map<String, Object>>


ColumnListHandler:将表的某列的数据封装到一个List集合中.


ScalarHandler:单值封装.


KeyedHandler:将多条记录封装到一个装有Map集合的Map集合.Map集合的key可以指定的.




5.JDBC案例:客户管理系统:Servlet + JSP + JavaBean + JDBC(/DBCP/C3P0)
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());


2.表单重复提交问题:不停点击刷新.重复提交数到数据库中.
* 表单重复提交的问题:// 可以使用重定向方式进行解决??? 不行!!!


/** ******************** 根本解决表单重复提交:
* 令牌机制:
* 在保存页面上生成一个令牌:随机的字符串.
* 将令牌保存到session中:
* 将令牌放入到表单的隐藏字段中:
* 当点击提交的时候:
* 表单中令牌和session中令牌在servlet中都可以获得到.
* 比对两个令牌是否一致:
* 如果一致:提交.
* 如果不一致:跳转到一个错误页面.
* 将session中令牌清空.*/


3.分页查询:主要解决页面的数据加载的过多,导致页面访问速度过慢.    //开发中 逻辑+物理 结合使用
// Mysql: select * from 表 where 条件 ... limit startNum,endNum;          Oracle : 使用SQL语句嵌套.         SQL Server : 使用top关键字.
/* 分页:—————— 前五后四
开始记录数: startNum = (pageNo - 1)*pageSize;     // pageNo:当前页数     pageSize:每页显示记录数
结束记录数: endNum = pageNo*pageSize + 1;
*/


* 逻辑分页: 一次性将数据库中所有记录全部查询处理.查出来以后存放到一个List集合中.使用List集合中方法subList()对List集合进行截取.
* 优点:减少与数据库交互次数.
* 缺点:数据量非常大.查询时间比较长.


   * 物理分页: 不是一次性将所有数据全部查询出来.查询第一页:发送一条查询10条的SQL语句.查询下一页数据:又发送一条查询后10条的SQL.
* 优点:数据量非常小.查询时间比较短.
* 缺点:与数据库交互次数变多.


4.监听器:监听器就是一个实现了特定接口的Java类.这个Java类用来监听另一个Java类的方法调用或者属性改变.当被监听的对象发生上述的事件后.监听器某个方法就会立即执行.
事件源 :被监听的对象.(汽车)
监听器 :监听的对象.(报警器)
绑定监听器: 在事件源绑定监听器.(汽车上安装报警器)
事件 :就是事件源的改变.事件源一旦发生变化.事件就会传递给监听器对象.监听器的相应的方法就会执行.(踢了汽车一脚,报警).
***** 事件封装了事件源的改变. // 作用: 在监听器对象 中获得 事件源对象.


4.1.Servlet的监听器:监听器,过滤器都属于Servlet技术中的高级部分.
Servlet的规范中提供了8个监听器:
一类 :监听三个域对象的创建和销毁的监听器.(ServletContext,HttpSession,ServletRequest)// ServletContextListener ...
二类 :监听三个域对象的属性变更的监听器.(属性添加,属性移除,属性替换)// ServletContextAttributeListener ...
三类 :监听HttpSession对象中的JavaBean的状态的改变.(绑定,解除绑定,钝化,活化)// HttpSessionBindingListenerHttpSessionActivationListener


与传统的监听器的不同:
* 事件源 :ServletContext,HttpSession,ServletRequest.
* 监听器 :Servlet规范中提供的一组监听器的接口.ServletContextListener,HttpSessionListener,ServletRequestListener...
* 将事件源与监听器进行绑定:——————进行配置:web.xml中完成配置即可.


//一类: 一二类 ——————>web.xml中配置
ServletContextListener监听器作用: 加载框架的配置文件 —————> Spring框架
HttpSessionListener的作用: 进行session扫描    —————> 记录网站的在线人数!
...
问题:
* 访问一个Servlet会不会创建session对象.
不会的!
* 访问一个HTML页面会不会创建session对象
不会的!
* 访问一个JSP页面会不会创建session对象. // jsp ————显示数据
// 会的!!!        ———————— 四大域对象     内置的!!!  _service()方法默认声明九大内置对象


问题: // 只要发送了请求,就会...
* 访问一个Servlet会不会创建request对象.
会!
* 访问一个JSP会不会创建request对象
会!
* 访问一个HTML会不会创建request对象// 向服务端请求了页面  只要发送请求,就会...
会!


//三类: ————————>这类监听器不需要进行配置:* 需要让JavaBean自己感知在session中状态.
Session的钝化实质是对于session的优化手段!!!
* 将长时间不使用的session使其序列化.    // 在context.xml中,可手动配置Session的序列化














4.2.在线踢人案例
将List< Map<"QQ",session("QQ",QQ)> >存放到ServletContext范围     Map:每个用户    key:用户名   value:此用户的session      从List中add() / remove()即可


/** 在线踢人案例的BUG分析及解决:
1:用户重复登录问题:
重写User类的hashCode和equals方法
* 只要ID相同认为是同一个对象.


2:用同一个浏览器,先后使用不同的账号进行登录:
第二次登录用户,将第一个登录的用户踢出.
* 第一个用户的session保存的其他的信息还是存在.


解决办法:
* 当用户登录的时候,将之前的session销毁.


3:使用不同浏览器,先后使用同一个账号进行登录:
第二个登录的用户将第一个登录的用户从map集合中踢出了!
* 第一个登录的用户没有在Map集合中,而且session没有销毁.导致这个用户不能被踢.


解决办法:
* 当用户登录的时候,先去判断用户是否已经在列表中.
* 如果在列表中:已经登录过.将登录过的用户的session取出,进行销毁.*/






19.过滤器:Filter.对客户端向服务器发送的请求进行过滤. // 参数:request + response + chain =====》 void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
   Filter是Servlet中最为实用的技术.Filter和Listener都属于Servlet中的高级部分.
核心方法:doFilter(ServletRequest request, ServletResponse response,FilterChain chain)


1.功能:
* 过滤敏感词汇.
* 进行URL级别权限控制.
* 统一网站的字符集编码.
* 进行响应的压缩.


2.FilterChain对象:过滤器链.
过滤器链指的是:一组过滤器对某些WEB资源进行过滤.那么这组过滤器称为是过滤器链.
执行顺序: 按照<filter-mapping>的排序执行


3.Filter的生命周期:——————同Servlet
* 创建:
* 服务器启动的时候创建Filter的对象.
* 销毁:
* 服务器关闭的时候或者是项目移除!
* 服务器启动的时候,服务器创建一个Filter的对象.过滤器中init方法就会执行了.  // init(FilterConfig)
 当过滤器过滤到要进行拦截的资源的路径的时候,doFilter方法就会执行.
 当服务器关闭的时候.销毁过滤器对象.destroy方法就会执行.


4.FilterConfig:过滤器的配置对象.
实现 Filter
API:
getFilterName()
getInitParameter("username")  ——————web.xml中所配置的初始参数
getInitParameterNames()
******* getServletContext()————————————————获得ServletContext对象.


过滤器相关的配置: 在web.xml中配置:
.....
<url-pattern>标签的配置:
三种配置方式:
* 完全路径匹配 :以 / 开始.    如: /aa   /bb   /aa/bb
* 目录匹配    :以 / 开始. 需要以 * 号结束.    如: / * /aa/ *  /aa/bb/*
* 扩展名匹配 :不能以 / 开始. 需要以 * 号开始. 如:*.jsp*.do*.action


* <servlet-name>:过滤名称为某个值的Servlet.如:<servlet-name>ServletDemo1</servlet-name>


* <dispatcher>:默认情况下只会去过滤从客户端向服务器发送的请求.//默认过滤 request<!-- 一般配置在 struts2 核心过滤器中 -->
* REQUEST :默认值.过滤的请求.
* FORWARD :过滤的是转发 如: <dispatcher>FORWARD</dispatcher>   // <jsp:forward>标签想使用,必须配置此项!!!
* INCLUDE :过滤的是包含
* ERROR :过滤的是错误页面跳转.(全局错误页面的跳转)




/** 统一网站的字符集编码的过滤器:
doFilter()方法中:
// 获得初始化参数:字符集:
String encoding  = filterConfig.getInitParameter("encoding");
request.setCharacterEncoding(encoding);  // 设置参数的编码   ——————> 可能内部根据我们 传参encoding ,做了new String("编码",解码)
response.setContentType("text/html;charset="+encoding);
chain.doFilter(request, response);
*/




/** 禁用网站的所有动态页面的缓存:// 有些网站不能出现缓存:网银系统.网站中数据是经常变化.(向页面中输出当前的时间).
doFilter()方法中:
// 禁用浏览器的缓存:
HttpServletResponse resp = (HttpServletResponse) response;  //强转为 HttpServletResponse 和...
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
resp.setDateHeader("Expires", -1);
// 放行:
chain.doFilter(request, resp);




response.setDateHeader("Expires", 1000L*60*60*24*30);//设置缓存 --有效期  ---时间-Long类型
response.setDateHeader("Expires",-1);  // -1 --- 会话结束 - 即销毁
*/


分IP统计网站访问次数的过滤器:——————filterConfig.getServletContext()// filterConfig.getServletContext.setAttribute("map",map.put(request.getRemoteAddr(),1));


自动登录的过滤器:
/** * 判断Session中是否已经存在用户的登录信息:
* * 已经存在:
* * 放行.
* * 不存在:
* * 从request中获得所有Cookie的信息.
* * 查找指定名称Cookie:
* * 没有查询到:
* * 直接放行.
* * 查询到:
* * 获得Cookie中的用户名和密码:
* * 根据用户名和密码去数据库进行查询:
* * 查询到用户:
* * 将用户的信息保存到session中
* * 放行.
* * 没有查找到用户:
* * Cookie中用户名和密码有可能被篡改.
* * 放行.
*/




URL级别的权限控制的过滤器:// 实际开发中,通常将一些非常重要的资源(Servlet,JSP...)放入到特殊的路径中.必须有特殊身份用户(管理员)才可以访问到.
/** * 获得用户的访问路径:
* * 根据路径去Map中进行查找:
* * 如果路径匹配了:
* * 获得能够访问这个路径的匹配身份.
* * 获得用户的登录的身份信息.
* * 比对匹配的身份与登录的身份是否一致:
* * 如果身份一致:
* * 放行:
* * 如果身份不一致:
* * 权限不足:
 */




网站通用的字符集编码过滤器:
前台页面向后台提交数据: * 无论是GET还是POST提交中文的时候都会出现乱码的问题. ***** 编写的过滤器解决中文乱码的问题:(GET和POST的乱码的解决).
// request.setCharacterEncoding(“UTF-8”);只能影响请求行、头、体中的编码方式,对URL链接编码方式无效!!!——————> 即对GET请求无效!!!


/** 通用的字符集编码过滤器的实现的步骤:
* 发现GET和POST提交的时候都会调用request.getParameter方法:
* 是否增强request中的getParameter方法:
* 增强一个类的某些方法有几种办法:
* 三种办法:
* 继承:
* 条件:能够控制这个类的构造.
* 装饰者模式:
* 条件:
* 增强的类和被增强的类实现相同的接口.
* 增强的类中需要获得到被增强的类引用.
* 动态代理:
HttpServletRequest:接口
  | |
实现类1 自定义增强类
* 获得实现类1的引用.
* 缺点:接口中的方法特别多.
* 动态代理:
* 条件:
* 类需要实现接口.对实现了接口的类产生代理.
*/
/** ***** GET和POST方式如何解决乱码:
* POST:
* 解决办法:
* request.setCharacterEncoding(“UTF-8”);
* GET:
* 解决办法:
* String name = new String(request.getParameter(“name”).getBytes(“ISO-8859-1”),”UTF-8”);
*/






20.文件上传和下载:
1.文件上传: // 将本地文件写到服务器上.
文件上传的三要素:
* 表单的提交的方式必须是POST方式:
* GET方式有大小的限制的.POST方式没有大小的限制.
* 表单中需要有文件上传项:
* 在表单中需要有<input type=”file” name=“”/>.而且文件上传项必须有name的属性.
* 表单的enctype属性:必须设置为multipart/form-data


文件上传的技术:
1.JSPSmartUpload:jspSmartUpload组件是应用JSP进行B/S程序开发过程中经常使用的上传下载组件, // 上传 + 下载
 它使用简单,方便。现在我又为其加上了下载中文名字的文件的支持,真个是如虎添翼,必将赢得更多开发者的青睐。


2.FileUpload :FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能,与常见的SmartUpload齐名.


3.Servlet3.0 :提供了文件上传的功能.


4.Struts2 :提供了文件上传和下载的功能.  // 上传 + 下载


2.FileUpload:
  /** 使用FileUpload组件完成文件上传:
* * 创建一个磁盘文件项工厂:
* * 创建一个核心解析类:
* * 使用核心解析类解析request请求.返回一个List集合.封装的一个FileItem的对象.
* * 遍历List集合获得到表单中的每个部分(FileItem).
* * 判断FileItem是否是文件上传项:
* * 文件上传项:完成文件上传.
* * 普通项:获得普通项名称和值.
*/
核心API:
/** ServletFileUpload: // 核心解析类:
ServletFileUpload.isMultipartContent(request)  ———— 判断表单的enctype的属性是否是multipart/form-data.    T/F
new ServletFileUpload(diskFileItemFactory)  ———— 创建核心解析类
servletFileUpload.setHeaderEncoding("UTF-8");  ———— 处理中文文件名的上传的乱码问题:
servletFileUpload.setSizeMax(5 * 1024 * 1024); ————设置所有文件上传的总大小  setFileMax()————单个文件大小
setProgressListener()  ————* 设置监听器:作用监听上传的进度.
List<FileItem> list = servletFileUpload.parseRequest(request);  ——————  解析request请求
*/
/** DiskFileItemFactory:  // 磁盘文件项工厂
DiskFileItemFactory() /DiskFileItemFactory(int sizeThreshold, java.io.File repository)
//* int sizeThreshold:FileUpload组件的缓冲区大小.默认是10kb.* File repository:文件上传过程中产生临时文件存放的路径.
get/setSizeThreshold(5 * 1024 * 1024)  // ../设置FileUpload的组件的文件上传的缓冲区大小.
get/setRepository(new File(temp)) // ../设置临时文件存放的路径.
*/
/** FileItem:  // 文件项
fileItem.isFormField()   // 判断是否是文件上传项:
fileItem.getFieldName();fileItem.getString("UTF-8");  // 普通项 的名称 / 值
fileItem.getName();//  获得文件上传项的文件的名称.
fileItem.getInputStream();————要上传的文件封装到输入流中  //获得文件上传项的文件的内容.
fileItem.delete()// * 删除文件上传中的临时文件.*/


/** 通过JS控制多文件的上传:
"<div>文件上传:<input type='file' name='upload'/><input type='button' value='删除' οnclick='del(this)'></div>
$("#div").html() = "";  //一次性将div内容清空,删除所有


问题:
问题一:IE6浏览器兼容的问题:if(fileName.indexOf("\\") != -1){说明浏览器的版本比较低..}
问题二:上传文件的文件名的重名的问题:UUID.randomUUID().toString().replace("-", "")+"_"+fileName;
问题三:一个目录下存放的文件过多的问题.   目录分离
/** 目录分离算法分析:
* 获得文件的唯一文件名:
* 获得到唯一文件名的hashCode().
* 哈希值是一个int类型的值.int类型是4个字节.每个字节8位.(32位).   ————> 0x:十六进制0xf 可直接写 15
* 哈希值&0xf;得到一个值.用这个值作为一级路径.
* 哈希值右移4位&0xf;得到一个值.用这个值作为二级路径.*/




3.文件下载两种形式: // 本质:就是将文件编码成 浏览器不能解析的类型, 就会提示下载!!! Content-Disposition:代表文件需要以下载的形式打开.
//attachment:附件
/** 一种:超链接下载. 对于下载的资料.将资源写到<a href=”资料路径”>下载</a>.
* 前提:如果浏览器支持这个格式的文件.可以在浏览器中打开.如果浏览器不支持这个格式的文件.提示下载.


二种:手动编写代码的方式进行下载.* 无论浏览器是否支持该格式的文件:提示下载.
* 设置两个头和一个流:
* Content-Type:代表的是文件的MIME类型.// Content-Type: application/x-www-form-urlencoded 表单的数据类型,说明会使用url格式编码数据
* Content-Disposition:代表文件需要以下载的形式打开.// attachment;filename=${name}
* InputStream:代表的文件的输入流.
* 因为输出流是固定的: response.getOutputStream();


树形结构的遍历:  创建一个队列:Queue<File> queue = new LinkedList<File>();入队:queue.offer(root);出队:queue.poll();
*/








21.1.AJAX: AJAX = 异步 JavaScript 和 XML(标准通用标记语言的子集)// 现在多使用 JSON 代替了 XML
/** AJAX完成的是页面的局部刷新的效果!!!异步加载
即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。*/


软件的结构: C/S结构 :Client / ServerB/S结构:Browser /Server


1.核心对象:XMLHttpRequest(JS中的对象)//JS中有一个XMLHttpRequest.逐渐重视JS.    减轻服务器压力.RIA(Rich Internet Application).可以使用户体验得到增强.
属性:
onreadystatechange:用于指定XMLHttpRequest对象状态改变时的事件处理函数// 监听request变化,触发js函数
/** readyState:XMLHttpRequest对象的处理状态//4
0 :XMLHttpRequest对象还没有完成初始化
1 :XMLHttpRequest对象开始发送请求
2 :XMLHttpRequest对象的请求发送完成
3 :XMLHttpRequest对象开始读取服务器的响应
4 :XMLHttpRequest对象读取服务器响应完成
*/
responseText : 用于获取服务器的响应文本----------------  servlet查询到的list结果集 封装到了 此对象中
----------------  在想要显示内容的 任意div块 中调用即可获取到数据
responseXML : 用于获取服务器的响应的XML文档
status : 服务器返回的状态码 // 只有服务器的响应已经完成时,才会有该状态码 200
statusText : 服务器返回的状态文本信息// 只有当服务器的响应已经完成时,才会有该状态文本信息


API:
open :打开链接.//  open(请求方式,请求路径,true);
send :发送数据//  send(数据);
setRequestHeader:设置请求的头信息.//  setRequestHeader(“头”,”值”);


/** XMLHttpRequest的对象的创建:
IE浏览器创建XMLHttpRequest的时候:
* 将对象封装到浏览器的ActiveXObject组件中.
Firefox浏览器创建XMLHttpRequest的时候:
* 直接创建. */


/** * AJAX的代码的编写:GET请求    // GET方式需要向后台传递参数:* 需要在路径的后面拼接这些参数.不要将参数写到send方法中.
* 1.创建异步的XMLHttpRequest对象.// createXMLHttpRequest();
* 2.设置监听:监听对象的状态的变化,触发一个函数.// xhr.onreadystatechange = function(){}
* 3.打开链接:
xhr.open("GET","${pageContext.request.contextPath}/AjaxServletDemo1?id=2&name=张三&time="+new Date().getTime(),true );
//  每次URL路径都不同   ----  处理浏览器缓存问题  ---- 及时更新页面数据
* 4.发送数据:    //  xhr.send(null); */
POST请求     // xhr.send("id=3&name=李四"); * POST请求传递参数:需要将参数写到send方法中.
// xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); //设置进行URL编码


Servlet端:  响应文本 ——————response.getWriter().println(xxx);


/** 应用: AJAX异步校验用户名是否存在: date = 1 / 2  ====占用/可以使用
使用AJAX完成二级联动的效果:
1.将XML文档中的<province name=””>标签中的name属性的值获得到,添加到第一个下拉列表中:
2.判断选中哪个<province>节点,遍历其子节点获得<city>标签中的值,写入到第二个下拉列表中.
*/


21.2.XStream:将对象,集合转成XML格式. //  xpp3_min-1.1.4c.jar* xstream-1.4.4.jar
API:
XStream xStream = new XStream();
xStream.alias();
xStream.useAttributeFor();
xStream.addImplicitCollection();
String xml = xStream.toXML();


/** 集合————>xml:
XStream xStream = new XStream();————————————// new Province(1, "河北省", cities1); Province对象中封装了 ID、name、list<city>
// 不使用类的全路径作为标签名称:—————————————— 添加标签


xStream.alias("province", Province.class);
xStream.alias("city", City.class);


// 使用类的属性作为标签的属性而不是子标签形式:   —————————————— 给标签添加属性 id、name
xStream.useAttributeFor(Province.class, "id");
xStream.useAttributeFor(Province.class, "name");


xStream.useAttributeFor(City.class, "id");
xStream.useAttributeFor(City.class, "name");


// 使用去掉属性中集合的属性作为其子标签:—————————————— 将<province> 作为子标签 (需要去掉 Province类中包含的list<city>属性 )
xStream.addImplicitCollection(Province.class, "cities");


String xml = xStream.toXML(provinces);
System.out.println(xml);*/


/** 对象————>xml:
// 不使用类的全路径作为标签名称:使用类作为标签名称:——————>不能带包名 :xxx.class=原始对象=不含包名带包名:province1 = cn.it.Xstream. Province
xStream.alias("province", Province.class);
xStream.alias("city", City.class);


// 使用类的属性作为标签的属性而不是子标签形式:
xStream.useAttributeFor(Province.class, "id");
xStream.useAttributeFor(Province.class, "name");


xStream.useAttributeFor(City.class, "id");
xStream.useAttributeFor(City.class, "name");


// 使用去掉属性中集合的属性作为其子标签:
xStream.addImplicitCollection(Province.class, "cities");
String xml = xStream.toXML(province1);
System.out.println(xml);、、*/








21.3.JSON:是一种轻量级的数据交换格式。 (JavaScript Object Notation)


格式: [{“id”:1,”name”:”吉林省”},{“id”:2,”name”:”辽宁省”}][{'province':'辽宁省'},{'province':'吉林省'},{'province':'浙江省'}]


语法; 一段JSON的字符串,本身就是JS中支持的一种数据的格式.// JSON 语法是 JavaScript 对象表示语法的子集。
JSON的格式在JS中当做数组使用.
解析成数组: var arr = eval("("+data+")");
获取数组中的值: arr[i].province arr[i].id / name


JSONLIB的使用: JSONLIB是一个工具类:将数组、List , 对象、MAP集合转换成JSON的串.


API:
* JSONObject : 主要用于将 对象和MAP集合  转成JSON的.
* JSONArray : 主要用于将 数组和List集合 转成JSON的.


JSONObject.fromObject(object/map)
JSONArray.fromObject(arr/list)


eg: JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setExcludes(new String[]{"currentPage","pageSize","detachedCriteria","decidedzones"});// 尽可能多的去掉不需要序列化的字段
JSONObject json = JSONObject.fromObject(javaBean , jsonConfig);






22.java基础加强:
1.JDK中提供的三个注解:
@Override : 标识子类重写父类/接口的方法.
@SuppressWarnings:用来压制警告.
@Deprecated : 用来描述方法过时


自定义注解 :@interface Anno1{..属性...}// 同 定义类/接口 : class / interface  HelloWorld{...}
* @interface Anno1{
int sum() default 1;// 变量类型  变量名称()  ————设置了 default值,@Anno1(写sum="xx",覆盖默认值1.不写默认sum=1 )
String value();//如果注解中只有一个属性,属性名为value.那么这个value可以省略.@Anno3(value = "aaa") == @Anno3(“aaa”)
}


泛型的基本术语:
* 以ArrayList<E>为例:
* <> :念为 typeof
* E :称为类型参数变量
* ArrayList<Integer>中   Integer: 称为实际类型参数.
* ArrayList<Integer>   : 整个称为 参数化类型


通过反射获得参数化类型从而获得实际类型参数:
* Class:
Class c = this.getClass();// 获得到子类的Class的对象.     获得的是:继承此类的子类的Class对象   //谁继承它,就代表谁
c.getGenericInterfaces/Superclass();// 获得带有泛型的接口/父类.       -------  参数化类型 BaseDao<Book> ————— 得到一个 带有泛型的父类
* ParameterizedType:
pType.getActualTypeArguments();// 获得带有泛型的父类.       -------  实际类型参数   Book —————从 参数化类型中 获取到 实际类型参数 :Book


******************  Type:  类型
// 代表 java中 所有类型 的公共父类接口   ———————— 参数化类型、数组类型、变量类型、原始类型、未处理类型
Type is the common superinterface for all types in the Java programming language.
———————— These include raw types, parameterized types,array types, type variables and primitive types.


ParameterizedType:参数化类型 ———————— (ParameterizedType)Type  : 将this.getClass().getGenericSuperclass()/getGenericInterfaces() 获取的Type 强转为 参数化类型
// interface ParameterizedType extends Type// 将用 子类的class对象 获取的 父类/父接口 的Type 强转为 ParameterizedType(参数化类型)类型
// 然后可 调用 ParameterizedType接口 的API,获取到 父类中的所有 泛型数组
ParameterizedType:参数化类型,通过字面意思理解:带有参数的类型————————即 如果这个类型(Type)带有泛型,我们就可以强转为ParameterizedType(Type)
只要Type类型 中带有 <泛型> ,就可以向下强转为  参数化类型: (ParameterizedType)Type




******* API:  再通过参数化类型  获取到具体的Class类型 <具体的泛型类型>
Type[] getGenericInterfaces()     // ParameterizedType.getGenericInterfaces()  : 获取到 父类中的所有 泛型 (泛型数组) --->泛型[]


****************** 1.Type、Class、ParameterizedType三者的关系?
Class<T> implements java.lang.reflect.Type,   //  Type 在 反射包下  ————> 我们可知,获取具体的Class类型,自然是通过反射获取到的
interface ParameterizedType extends Type






2.Servlet3.0:
新增特性:
* 1.支持注解开发. ———————— @WebServlet(urlPatterns="/servletDemo1")  @WebFilter  @WebListener   // EE6.0    Tomcat7以上可以不存在web.xml.


* 2.支持文件上传. ———————— @MultipartConfig // 需要在Servlet上添加一个注解: @MultipartConfig
Part part = request.getPart("upload");// 获得文件上传项: Part部分.类似于FileUpload组件中的FileItem.
InputStream is = part.getInputStream(); // 获得文件内容的输入流


* 3.支持异步请求.    ———————— @WebServlet(urlPatterns="/servletDemo3",asyncSupported=true)// 需要在@WebServlet中使用一个属性:asyncSupported=true
AsyncContext asyncContext = request.startAsync(req, resp);// 开启一个异步的请求的对象.


3.动态代理:
* 1.继承


* 2.装饰者模式
* 1.被增强的类和增强类需要实现相同的接口.
* 2.在增强的类中获得被增强的类的引用.


* public class BigBirdWrapper implements Bird{
private Bird bird;
public BigBirdWrapper(Bird bird){   //有参构造,参数: 被增强的类的引用
this.bird = bird;
}
public void fly(){
System.out.println(“飞飞 ...”);// 增强代码.//bird.fly();
}
}
Bird bird = new BigBirdWrapper(new BigBird());
bird.fly(); // 最终都是用 多态实现的    实际运行调用子类的方法




* 3.动态代理:(*****最为灵活的一种增强的方式)被增强类必须实现接口.JDK动态代理可以对 实现了接口的类 产生代理.


必须 implements InvocationHandler 接口,
* 1.创建代理对象
* 2.重写invoke()方法// 真正的执行是靠invoke(),我们只需在invoke()中重写需要增强的method即可!!!


相关API:
* Proxy: // 代理类
Proxy.newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h);// 创建代理对象
* ClassLoader : 接口的类加载器.
* Class[] : 类实现的 所有接口的Class的对象.
* InvocationHandler: 真正的处理对象.
eg:Waiter waiterProxy = (Waiter) Proxy.newProxyInstance( waiter.getClass().getClassLoader(),  waiter.getClass().getInterfaces(),  this );


Object invoke(Object proxy, Method method, Object[] args);
* proxy :代理对象.
* method :指代的方法本身(正在执行的方法)     // method.getName() 、 method.invoke()
* args :方法的参数列表


4.类的加载器:将编译后的class文件加载到内存.(加载到JVM)
类的加载器分类:
引导类加载器: jre/lib/rt.jar(JDK中常用的类) // String—————————null
扩展类加载器: jre/lib/ext/ *.jar(JDK的扩展的类) // DNSNameService—————————sun.misc.Launcher$ExtClassLoader
应用类加载器: 类路径下的class的.(自定义的类)// Demo—————————sun.misc.Launcher$AppClassLoader




















25.HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版。(全称:Hyper Text Transfer Protocol over Secure Socket Layer)
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
这个系统的最初研发由网景公司(Netscape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。
















90.1.webservice:即web服务,是一种跨平台的远程调用技术,实现客户/服务器模式的应用。
webservice基于 soap协议 传输数据。
soap:soap=http+xml
wsdl:说明书
uddi:目录
webservice就是发布一个服务接口,供其它计算机调用,可以实现的技术有好多,socket、http、soap方式、hessian等,在实际应用时根据具体的需求和场景去选择应用技术。






90.2.CXF框架:apache的开源项目,是一个webservice开发框架。它支持多种协议,比如:SOAP1.1,1,2、XML/HTTP、RESTful HTTP 或者 CORBA
Cxf是基于SOA总线结构,依靠spring完成模块的集成,实现SOA方式。
灵活的部署:可以运行在Tomcat,Jboss,Jetty(内置),weblogic等web容器上面。




安装: 解压apache-cxf-3.0.5目录
配置:
CXF_HOME=cxf的目录
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar




/** server端:   //jar包


Dao层:
创建applicationContext-dao.xml文件配置dao接口,由spring容器统一管理     配置daoBean






service层: // 与jaxws编程不同的是将   @WebService注解  加在  SEI接口  上边


在service接口实现类中注入dao


创建applicationContext-service.xml,配置service






cxf和spring整合发布服务:


创建applicationContext-cxf.xml,配置发布webservice服务


使用jaxwx 发布服务
jaxws: server标签就相当于JaxWsServerFactoryBean编程方式
address: webservice地址
serviceClass:   SEI




web.xml配置:   //web容器中加载spring容器


加载spring容器


配置cxf的servlet,所有cxf的服务请求由servlet进行解析 // 直接用Apache提供的CXFServlet    ----- org.apache.cxf.transport.servlet.CXFServlet




部署tomcat启动:


http://ip:port/工程名/ws/                           <!-- web.xml中Servlet配置的 url-pattern  -->


*/






client端:


wsdl2java工具: wsdl2java -d . http://127.0.0.1:12345/area // 使用wsdl2java工具生成客户端调用代码    功能同wsimport


















100.oracle:oracle是甲骨文公司的一个大型数据库产品,一般在大型项目中应用较多。 比如:银行、大型企业系统等。和oracle数据库类似的数据库还有db2
Oracle数据库:是一个文件系统,是物理概念。
安装: // SCOTT HR 解锁






实例:一个实例其实是指一系列的后台进程和内存结构// Oracle可以有多个实例,大部份情况就一个实例。   也就是说oracle就是 一整个 大的数据库(实例)    ===> 就一个数据库
// 实例 = 数据库
// 实例下面有   N个用户  +  N个表空间


用户: 每个 数据库实例 下面可以有 许多用户   // 多个实例可以有相同的用户名的用户
// oracle 中用户的概念相当于mysql中的database的概念


表空间: 实例下面可以有多个表空间,表空间是对物理数据文件的逻辑映射。  // 用户都有自已的默认表空间
// 表空间是逻辑概念,一个表空间对应着一个或者多个物理存储文件(.dbf,.ora)




用户和表空间的关系:
一个用户有一个默认的表空间,
一个表空间可以为多个用户作为默认表空间,
用户和用户之间的数据是隔离,数据不会混。


Oracle数据库源:
driver:     oracle.jdbc.OracleDriver
url:        jdbc:oracle:thin:@localhost:1521:orcl
username:   zhangsan
password:   zhangsan


// oracle 中用户的概念相当于mysql中的database的概念


//别名 = 表列名


/* Oracle的基本命令:


使用指定用户登陆连接到oracle,
Sqlplus username/password [as sysdba 管理员才需要]


显示当前用户
Show user;


退出用户
Exit;


切换用户
Conn username/password [as sysdba 管理员才需要]


查看当前用户可以访问的表有哪些
Select * from tab;




查询某张表的数据
Select * from dept;


查看表结构
Desc dept;


// 不同的用户的表是隔离的,但是权限大的用户可以访问其它用户的表。跨用户访问。
Select * from scott.demp;






1.Oracle的简单查询:


--简单查询
select * from emp;


select empno , ename from emp;


select empno as 员工编号, ename as 员工姓名 from emp;    // as 别名


select empno 员工编号, ename 员工姓名 from emp;// 可省略


--字符串连接查询 // 使用distinct可以消除重复的行,如果查询多列的必须保证多列都重复才能去掉重复


select '员工名为'||ename||'的工作是'||job||'的部门是'||deptno from emp;// 记录去重, 必需所有列都一样才算重复    ||: 相当于java程序的 + 连接字符串
select distinct job from emp;


select distinct ename, deptno , job from emp;


--四则运算
select ename 姓名, sal * 12 年薪 from emp;








2.Oracle限定查询A:


--限定查询
select * from emp where sal > 1500;


--为空和非空判断,金为null 或不为null
select * from emp where comm is null;
select * from emp where comm is not null;


--多个条件 并且and ,查询工资大于1500并且有奖金的
select * from emp where sal > 1500 and comm is not null;


--多个条件 或者,查询工资小于1500或者comm为空
select * from emp where sal < 1500 or comm is null;


--not 取反
select * from emp where not(sal <= 1500 or comm is null);




-- 区间
select * from emp where sal >= 1500 and  sal <= 3000;
select * from emp where sal between 1500 and 3000;


--时期  // to_date()
select * from emp where hiredate between to_date('1981-1-1','yyyy-MM-dd')
and to_date('1981-12-30','yyyy-MM-dd')


--sql语句不区分大小写,但字段的值区分  // 字段的值区分 大小写!!!


select * from emp where ename = 'SMITH';   // sql语句不区分大小写,但是 它的值 是区分大小写的!!!  smith != SMITH






3.Oracle限定查询B:


--范围查询  // in     not in


select * from emp where empno = 7369 or empno = 7499 or empno = 7521


select * from emp where empno in (7369, 7499, 7521)


select * from emp where empno not in (7369, 7499, 7521)


--模糊查询 // like    _:匹配一个长度       %:N位


select * from emp where ename like '_M%'


select * from emp where ename like '%M%'


select * from emp where ename like '%M__'


select * from emp where ename like '%'


--不等于 !=  <>   // 都是不等    两种写法而已


select * from emp where empno != 7369;


select * from emp where empno <> 7369;






4.Oracle排序. // asc:升序     desc:降序        默认:asc(可省略)


--排序 order by 列名 asc 升序(从小到大) / desc(降序从大到小)


select * from emp order by sal asc, hiredate desc




5.Oracle单行函数.


--尾表 // 虚拟表


select 1 from dual;




--单行函数
--小写变大小写
select upper('smith') from dual;


--大写变小写
select lower('SMITH') from dual;


--首字母大写
select initcap('smith') from dual;


--截取
select substr('hello',1,3) from dual;      // 索引 从1开始


--替换
select replace('hello','l','x') from dual;


--计算字符长度
select length('hello') from dual;


--连接字符串
select concat('hello','world') from dual;


select 'hello'||'world' from dual;        // 建议用 ||   跨平台


--数值函数  取整四舍五入
select round(12.48) from dual;
select round(12.48, 1) from dual;         // 保留几位小数


--去除小数
select trunc(231.123) from dual;
select trunc(123.123,2) from dual; // 保留几位小数


--取模  // 取余
select mod(10, 3) from dual;




6.Oracle日期函数.




--日期函数
select sysdate from dual;




--计算两个日期之间的天数 // 日期1 - 日期2


--员工进入公司的周数


select ename ,trunc((sysdate - hiredate) / 7) from emp;


--计算两个日期之间的月数 // months_between('当前时间','要计算的时间')      ====  两个日期之间的月数


select months_between(sysdate,to_date('2016-1-1','yyyy-MM-dd')) from dual;




--员工进入公司的月数
select ename, trunc(months_between(sysdate,hiredate)) from emp;




--加月   // add_months()


select add_months(sysdate, 12) from dual;




--下一个星期几 // next_day()下一个星期X的 当前时间    ==> 以当前时间为基准,查询下一个星期X 的此时此刻的时间


select next_day(sysdate, '星期一') from dual;




--计算当前月最后一天 // last_day(sysdate)


select last_day(sysdate) from dual;






7.Oracle的转换函数.


--转换函数


--to_char 把日期转成字符串     // to_char 把日期转成字符串


select ename ,  to_char(hiredate, 'yyyy') 年 ,
   to_char(hiredate, 'mm') 月,//fmmm:去掉0(2016-1-1)  mm:2016-01-01
   to_char(hiredate, 'dd') 日,
   to_char(hiredate, 'hh') 小时,//hh24:24进制      hh:12进制
to_char(hiredate, 'mi') 分,
to_char(hiredate, 'ss') 秒
from emp;


select ename , to_char(hiredate, 'fmyyyy-mm-dd hh24:mi:ss') from emp;      //fm:去掉0(2016-01-01 ==> 2016-1-1)hh24:24进制      hh:12进制




--给数字添加分割符


select ename , to_char(sal, '99,999') from emp;    // 1,234


select ename , to_char(sal, '$99,999') from emp;   // $1,234


select ename , to_char(sal, 'l99,999') from emp;   // ¥1,234


--把字符串转成数值    // to_number('数字字符')


select to_number('10') + to_number('10') from dual;


--把字符串转成日期  // to_date


select to_date('1986-08-21 12:30:21','yyyy-mm-dd hh24:mi:ss') from dual;




8.Oracle通用函数.


--通用函数


--为空处理nvl //   nvl('字段',0)    为空处理


select * from emp;
select ename , sal * 12 + comm from emp;--任何数和null相加等于null
select ename , sal * 12 + nvl(comm, 0) 年薪  from emp;




--decode分支判断   decode() ====>switch


select * from emp;
select decode(3, 1, '我是1', 2, '我是2','其它') from dual;
// select switch(x, if(x=1), {'我是1'}, if(x=2), {'我是2'},else{'其它'}) from dual;


select ename , decode(job,
'CLERK', '业务员','SALESMAN',
'销售员','MANAGER','经理','ANALYST','分析师','PRESIDENT','总裁')  job from emp;




-- case when end  case  when  end====>  if...else if()......else


select ename,
  (case
when job = 'CLERK' then
 '业务员'
when job = 'SALESMAN' then
 '销售员'
when job = 'MANAGER' then
 '经理'
when job = 'ANALYST' then
 '分析师'
when job = 'PRESIDENT' then
 'PRESIDENT'
else
 '无业'
  end) cjob
 from emp;




9.Oracle多表联合查询上.


--多表联合查询


--查询员工的编号 姓名 部门编号和 部门名称


 select * from emp , dept;//  笛卡尔积emp*dept
 select e.empno, e.ename, d.deptno, d.dname from emp e , dept d     where e.deptno = d.deptno// 员工的部门编号 = X部门编号---对上号


--查询员工的上级领导
select e1.ename, e1.empno, e2.ename, e2.empno from emp e1, emp e2 where e1.MGR = e2.empno;// 员工的上级编号 = X员工编号---对上号




10.Oracle多表联合查询下.


--查询员工的上级和部门
select e.empno , e.ename, e1.empno, e1.ename , d.deptno , d.dname from emp e , emp e1, dept d
 where e.mgr = e1.empno and e.deptno = d.deptno;




--查询员工的编号 名称 部门名称 和 上级领导以及领导的工资等级
 select e.empno,
e.ename,
d.dname,
decode(s.grade,
1,
'一级',
2,
'二级',
3,
'三级',
4,
'四级',
5,
'五级')emp_grade,// 这里 加一个  列名:emp_grade        否则,显示:decode(s.grade,1,'一级',....
e1.ename,
decode(s2.grade,
1,
'一级',
2,
'二级',
3,
'三级',
4,
'四级',
5,
'五级')mgr_grade    // 这里 加一个  列名:mgr_grade否则,显示:decode(s.grade,1,'一级',....
from emp e, emp e1, dept d, salgrade s, salgrade s2
  where e.deptno = d.deptno
and e.mgr = e1.empno
and e.sal between s.losal and s.hisal// 员工的工资等级 在 xx 范围内
and e1.sal between s2.losal and s2.hisal;// 领导的工资等级 在 yy 范围内






11.Oracle外连接上.// 在两张表关联的时候,在非全量表的关联字段后面加上(+) 就可以做外连接查询


作用:
不会因为另一张表的数据的关联而被筛选掉




1.非全量: 有残缺映射的对象     (映射 = 关联)    数据关联 可能为空// 反正就是在 有残缺映射 的对象后加(+)   记住这个就OK了!!!
2.全量:    被映射对象-----------------> 掌握主动权的 即为全量




--外连接查询
--就是在做查询的时候在非全量表的字段后加上(+)


--查询所有部门的员工
 select * from dept d , emp e where d.deptno = e.deptno;// 若 emp_孔明 没映射到 dept(无部门状态) ,孔明就不会被查询到(少了一个员工)




--全量表在左边就是左接连 // (可能有残缺)映射对象  : emp ==>  非全量
// 被映射对象:   dept ==>  全量------------------> 掌握主动权的 即为全量


 select * from dept d , emp e where d.deptno = e.deptno(+);    //全量d , 非全量e  where 全量d = 非全量e(+)
//规范:where 前后 表的顺序对应


--全量表在右边就是右接连
 select * from emp e , dept d where e.deptno(+) = d.deptno;//非全量e , 全量d  where 非全量e(+) = 全量d




12.Oracle外连接下.


--查询员工编号 姓名 上级领导姓名 和 编号


select e.empno, e.ename, e1.empno, e1.ename from emp e , emp e1 where e.mgr = e1.empno(+);// 在 有残缺映射的 对象后面加(+)




*/


/* 分页:
开始记录数: startNum = (pageNo - 1)*pageSize;     // pageNo:当前页数     pageSize:每页显示记录数
结束记录数: endNum = pageNo*pageSize + 1;
*/








100.自带工具类:
IOUtils.toString(InputStream ) ==> String text   //commons-io-1.4.jar
BeanUtils.populate(javaBean, map); //commons-beanutils-1.8.3.jar
StringUtils.isNotBlank(String s);==> 可以过滤 ""、" "和null即 != null 和 "" 和 ""(可以过滤空格)
StringUtils.isNotEmpty(String s);==> 可以过滤 ""、null   即 != null 和 "" 
StringUtils.isBlank(String s);==> "" / null / "  "(空格)
StringUtils.isEmpty(String s);==> "" / null


101.重要的类及其方法:
Class:
public ClassLoader getClassLoader()
public InputStream getResourceAsStream(String name)


Class<? extends BaseAction> clazz = this.getClass();//在父类构造方法中传入该参数,则子类继承父类时,   this就代表:子类,获得的是:继承此类的子类的Class对象


getSimpleName() // 返回源代码中给出的底层类的简称。 即:cn.it.basedao.domain.User   -----> User


DateFormat:
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");// 日期格式化
df.parseObject();
df.format();


value !=null && value.trim().length()>0




Method[] methods = clazz.getMethods();// 获得类中的所有的方法.




FileUtils工具的copyInputStreamToFile




102.自己总结的java辞典:
1.API:即功能.(源码:一堆jar包)   // 方法  作用  功能


2.HTML页面:就是一个文本
 JSP页面:  是一个Servlet程序// 执行完业务逻辑(一般也就动态获取值——显示数据用)  最终都会向页面 out.write(..)回HTML格式的文本


3.持久化:就是一个IO操作而已  // 从内存————>磁盘










103.对比:
service(ServletRequest req, ServletResponse res);
doFilter(ServletRequest request, ServletResponse response,FilterChain chain);//放行:chain.doFilter(request, response);可过滤所有资源  之前拦截
intercept(ActionInvocation invocation)//放行:invocation.invoke();struts2框架 仅针对action    之前 + 之后




StrutsStatics
ActionContext 此处规定 :  contextMap  =  ActionContext  + ValueStack
1.重要属性:
// ActionContext ——————— _values :request 、 session 、 application 、 parameters 、 attr
// ValueStack  ——————— _root  :action


contextMap是动作访问的数据中心,本质是一个ActionContext类,这个类有一个Map.可以操作 _root 和 _values
class ActionContext{
private Map<String, Object> context;// 此 context —————— contextMap = _root(action)  +   _values(request、session、application、parameters、attr)
}




/** 查看源码,观察到 明明是 valueStack 包含 ObjectStack 和 ContextMap , 为啥这里又说 context(ContextMap) 包含 root(valueStack) + http对象(ContextMap)???


关于这点,是几个继承造成的!!!


OgnlValueStack implements ValueStack


OgnlValueStack 两个属性 root(ObjectStack) context(:ContextMap)


而 其中的一个属性 context(ContextMap) 它本身也包含这两个属性  _root(ObjectStack)  _values(ContextMap)
 且struts把 root 赋值给了 _root


所以 其实我们这里的 context  =  _root(root) +  _values*/


2.其子类 //   继承了两个类的API    可以操作_root 和 _values


ServletActionContext extends ActionContext implements StrutsStatics
1.http相关API———— 从 StrutsStatics接口 继承而来
getPageContext()、 get/setRequest() 、get/setResponse()、get/setServletContext()
2.ActionContext相关API———————— 从 ActionContext 继承而来
getContext()
3.自定义的API
getActionContext(HttpServletRequest) 、getValueStack(HttpServletRequest req);// 获取给定的 request 的 Action上下文/值栈
getActionMapping()
4.有参构造:
private ServletActionContext(Map context) {
super(context);
}








104.容易忘的小知识:
Content-Disposition:代表文件需要以下载的形式打开.// attachment;filename=${filename}attachment:附件


<mime-mapping>// 可以在 tomcat的web.xml中 找到setContentType("application/octet-stream") ———————— 告诉浏览器,文件类型为二进制的  ,  浏览器就就肯定会以下载的方式打开
        <extension>bin</extension> // extension:扩展名MIME:多用途因特网(Internet)邮件扩展
        <mime-type>application/octet-stream</mime-type>// octet:八位字节bin:二进制
    </mime-mapping>


Context : 上下文


content 内容




response.setContentType("...");// 告诉浏览器, 我给你响应回来的是什么类型的文件  图片/html/json/二进制/... 官方学名:给响应数据,指定MIME类型




JDK动态代理:实现一个接口实质:父类调用子类  ——————多态


cglib代理:没有实现接口的类,只能使用cglib代理!




// JDBC 仅 连接数据库 + 发送SQL到数据库端
// 执行SQL —————— 数据库





105.java中的标准与实现:// 标准一般由 掌握话语权(有专利权)的公司/联盟/组织 提供  ,  实现由下面各个厂商去具体实现


标准(接口) 实现 联盟
JDBC mysql-jdbc.jarSUN
AOP AspectJAOP联盟
Tcp/ip HTTP<——————SOAP W3C// 均为通信协议————————通信:传输数据











106.java基础小知识:
1.又读又写: 字节流 eg:copy文件 中间过程为:字节——————>字节 但是如果用字符流:字节——>字符——>字节 效率肯定下降!!!
 只读/写: 字符流 字节读/写到页面就OK! 不用转换为字节! 非要用字符流拷贝,也只能拷贝 纯文本!

2.装饰着模式:
1.A类 和 B类 实现相同的接口;
2.B类的构造中获得 A类的引用;
3.B类重写接口的方法中传入 A类对象需要增强的方法,  然后再其上/下面写需要增强的内容!




107.扩展小常识:
1. FIFO:先入先出(first in,first out)
FILO:先进后出 (first-in,last-out)

2.POJO——————hashMap
每一个pojo对象都可以映射成一个map






/**
掌控自己的思维!我们的大脑就是一台高级计算机!思维就是运行在大脑上的程序!
我们需要不断的学习,不断的完善、升级大脑上的程序!修复负面思维————BUG!
*/


</textarea>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值