这是我大学二年级时自学javaweb所记下的笔记,可能有地方总结的不好但我会持续修改修正的。
XML全称eXtendsible markup language,可扩展的标记语言
其实他就是一个文件,文件的后缀为.xml
简单声明, version : 解析这个xml的时候,使用什么版本的解析器解析
encoding : 解析xml中的文字的时候,使用什么编码来翻译
standalone : no - 该文档会依赖关联其他文档 , yes-- 这是一个独立的文档
格式 :<元素名称 属性名称=“属性的值”>元素名称>
张三
18
李四
28
非法字符
严格地讲,在 XML 中仅有字符 “<“和”&” 是非法的。省略号、引号和大于号是合法的,但是把它们替换为实体引用是个好的习惯。
< <
& &
其实就是获取标签里面的数据
常用的有两种
element.element("stu") : 返回该元素下的第一个stu元素
element.elements(); 返回该元素下的所有子元素。
创建SaxReader对象
指定解析的xml
获取根元素
根据根元素获取子元素
try {
//1. 创建sax读取对象
SAXReader reader = new SAXReader(); //jdbc -- classloader
//2. 指定解析的xml源
Document document = reader.read(new File("src/xml/stus.xml"));
//3. 得到元素、
//得到根元素
Element rootElement= document.getRootElement();
//获取根元素下面的子元素 age
//rootElement.element("age")
//System.out.println(rootElement.element("stu").element("age").getText());
//获取根元素下面的所有子元素 。 stu元素
List elements = rootElement.elements();
//遍历所有的stu元素
for (Element element : elements) {
//获取stu元素下面的name元素
String name = element.element("name").getText();
String age = element.element("age").getText();
String address = element.element("address").getText();
System.out.println("name="+name+"==age+"+age+"==address="+address);
}
} catch (Exception e) {
e.printStackTrace();
}
dom4j里面支持Xpath的写法。 xpath其实是xml的路径语言,支持我们在解析xml的时候,能够快速的定位到具体的某一个元素。
添加jar包依赖
jaxen-1.1-beta-6.jar
在查找指定节点的时候,根据XPath语法规则来查找
后续代码同以前一样
//要想使用Xpath, 还得添加支持的jar
//获取的是第一个 只返回一个。
Element nameElement = (Element) rootElement.selectSingleNode("//name");
System.out.println(nameElement.getText());
System.out.println("----------------");
//获取文档里面的所有name元素
List list = rootElement.selectNodes("//name");
for (Element element : list) {
System.out.println(element.getText());
}
如下的文档, 属性的ID值是一样的。 这在生活中是不可能出现的。 并且第二个学生的姓名有好几个。 一般也很少。那么怎么规定ID的值唯一, 或者是元素只能出现一次,不能出现多次? 甚至是规定里面只能出现具体的元素名字。
张三
18
深圳
李四
李五
李六
28
北京
语法自成一派, 早起就出现的。 可读性比较差。
引入网络上的DTD
直接在XML里面嵌入DTD的约束规则
]>
张三 18
: stus 下面有一个元素 stu , 但是只有一个
stu下面有两个元素 name ,age 顺序必须name-age
stu有一个属性 文本类型, 该属性可有可无
元素的个数:
+ 一个或多个
* 零个或多个
? 零个或一个
属性的类型定义
CDATA : 属性是普通文字
ID : 属性的值必须唯一
按照顺序来
两个中只能包含一个子元素
其实就是一个xml , 使用xml的语法规则, xml解析器解析起来比较方便 , 是为了替代DTD 。
但是Schema 约束文本内容比DTD的内容还要多。 所以目前也没有真正意义上的替代DTD
约束文档:
实例文档:
zhangsan
19
lisi
29
lisi
29
一个xml如果想指定它的约束规则, 假设使用的是DTD ,那么这个xml只能指定一个DTD , 不能指定多个DTD 。 但是如果一个xml的约束是定义在schema里面,并且是多个schema,那么是可以的。简单的说: 一个xml 可以引用多个schema约束。 但是只能引用一个DTD约束。
名称空间的作用就是在 写元素的时候,可以指定该元素使用的是哪一套约束规则。 默认情况下 ,如果只有一套规则,那么都可以这么写
张三
cs
定义:服务器到客户端。
例如qq,微信等
优点:有一部分代码写在客户端, 用户体验比较好。
缺点: 服务器更新,客户端也要随着更新。 占用资源大。
bs
定义:服务器到浏览器
优点:客户端只要有浏览器就可以了。 占用资源小, 不用更新。
缺点: 用户体验不佳。
本质:就是一台配置较好的电脑
功能:接收请求,响应消息
种类: Tomcat apache
WebLogic BEA Websphere IBM
包含了一些jar,bat文件。 startup.bat
tomcat的配置文件 server.xml web.xml
tomcat运行所需要的jar文件
运行的日志文件
临时文件
这里面装载着,发布到tomcat服务器上的文件
jsp翻译成class文件存放地
使用localhost:8080 打开tomcat首页, 在左侧找到tomcat的文档入口, 点击进去后, 在左侧接着找到 Context入口,点击进入。 http://localhost:8080/docs/config/context.html
数据里面包含三部分内容:请求行,请求头,请求体
POST /examples/servlets/servlet/RequestParamExample HTTP/1.1
POST : 请求方式 ,以post去提交数据
/examples/servlets/servlet/RequestParamExample
请求的地址路径 , 就是要访问哪个地方。
HTTP/1.1 协议版本
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Referer: http://localhost:8080/examples/servlets/servlet/RequestParamExample
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 31
Connection: Keep-Alive
Cache-Control: no-cache
Accept: 客户端向服务器端表示,我能支持什么类型的数据。
Referer : 真正请求的地址路径,全路径
Accept-Language: 支持语言格式
User-Agent: 用户代理 向服务器表明,当前来访的客户端信息。
Content-Type: 提交的数据类型。经过urlencoding编码的form表单的数据
Accept-Encoding: gzip, deflate : 压缩算法 。
Host : 主机地址
Content-Length: 数据长度
Connection : Keep-Alive 保持连接
Cache-Control : 对缓存的操作
发送的数据呈现的是key=value ,如果存在多个数据,那么使用 &
firstname=zhang&lastname=sansan
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 673
Date: Fri, 17 Feb 2017 02:53:02 GMT
...这里还有很多数据...
HTTP/1.1 200 OK
协议版本
状态码
咱们这次交互到底是什么样结果的一个code.
200 : 成功,正常处理,得到数据。
403 : for bidden 拒绝
404 : Not Found
500 : 服务器异常
OK
对应前面的状态码
Server: 服务器是哪一种类型。 Tomcat
Content-Type : 服务器返回给客户端你的内容类型
Content-Length : 返回的数据长度
Date : 通讯的日期,响应的时间
1. 数据是以流的方式写过去的,不会在地址栏上面显示,现在一般提交数据到服务器的方式都是POST
2. 以流的方式写数据,所以数据没有大小限制
1. 数据是拼接在地址栏后面的,所以具有安全隐患
一般去服务器上拿东西,并且不用向服务器传输数据的时候可以选择GET方式
2. 能带的数据有限,仅有1kb左右
在http协议中,规定了请求和响应双方,客户端和服务器端。与web相关的资源有俩种分类
本质就是一个java程序,运行在服务器端,用来接收和响应客户端的http请求
更多的是配合动态资源
具体代码如下
注册
HelloServlet
com.itheima.servlet.HelloServlet
映射
HelloServlet
/a
Servlet (接口)
|
|
GenericServlet
|
|
HttpServlet (用于处理http的请求)
在创建该servlet的实例时,就执行该方法。
一个servlet只会初始化一次, init方法只会执行一次
默认情况下是 : 初次访问该servlet,才会创建实例。
只要客户端来了一个请求,那么就执行这个方法了。
该方法可以被执行很多次。 一次请求,对应一次service方法的调用
servlet销毁的时候,就会执行该方法
1. 该项目从tomcat的里面移除。
2. 正常关闭tomcat就会执行 shutdown.bat
HelloServlet04
com.itheima.servlet.HelloServlet04
2
servlet的配置,通过这个对象,可以获取servlet在配置中的一些信息
//1. 得到servlet配置对象 专门用于在配置servlet的信息
ServletConfig config = getServletConfig();
//获取到的是配置servlet里面servlet-name 的文本内容
String servletName = config.getServletName();
System.out.println("servletName="+servletName);
//2、。 可以获取具体的某一个参数。
String address = config.getInitParameter("address");
System.out.println("address="+address);
//3.获取所有的参数名称
Enumeration names = config.getInitParameterNames();
//遍历取出所有的参数名称
while (names.hasMoreElements()) {
String key = (String) names.nextElement();
String value = config.getInitParameter(key);
System.out.println("key==="+key + " value="+value);
}
1 全路径匹配
以"/"开始的后面所有进行匹配
2 路径匹配,前半段匹配
以"/"开始,以"*"结束,可以把*看做一个通配符
3 以扩展名匹配
以"*"开始,后面随便,就是把*看做一个通配符
servlet上下文
并且每个web工程都只有一个servletcontext对象。意思就是说不管在此工程的那个servlet类下,获取到的这个servletcontext都是同一个对象
获取对象
ServletContext context=getServletContext();
先来解释一波properties类
Properties类
java中提供了配置文件的操作类Properties类(java.util.Properties):
public class Properties extends Hashtable.可见Properties类继承了Hashtable,而HashTable又实现了Map接口,所以可对 Properties 对象应用 put 和 putAll 方法。但不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项。相反,应该使用 setProperty 方法。如果在“不安全”的 Properties 对象(即包含非 String 的键或值)上调用 store 或 save 方法,则该调用将失败。
Properties的常用方法:
1.setProperty(String key, String value)
调用 Hashtable 的方法 put。
2.
getProperty(String key)
用指定的键在此属性列表中搜索属性
3.
getProperty(String key, String defaultValue)
用指定的键在属性列表中搜索属性。
4.
load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
5.
load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
6.
loadFromXML(InputStream in)
将指定输入流中由 XML 文档所表示的所有属性加载到此属性表中。
7.store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
8.store(Writer writer, String comments)
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
9.storeToXML(OutputStream os, String comment)
发出一个表示此表中包含的所有属性的 XML 文档。
10.storeToXML(OutputStream os, String comment, String encoding)
使用指定的编码发出一个表示此表中包含的所有属性的 XML 文档。
普通方式进行拿取数据(此方法是行不通的)
public class Demo02 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 创建属性对象
Properties properties = new Properties();
//2. 指定载入的数据源
/*
* 此处,如果想获取web工程下的资源,用普通的FileInputStream 写法是不OK 的。
* 因为路径不对了。 这里相对的路径,其实是根据jre来确定的。 但是我们这是一个web工程,
* jre 后面会由tomcat管理,所以这里真正相对的路径是 tomcat里面的bin目录
*/
InputStream is = new FileInputStream("classes/config.properties");
properties.load(is);
//3. 获取name属性的值
String name = properties.getProperty("name");
System.out.println("name="+name);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
利用ServletContext 提供的方法,改进上述代码
Properties properties=new Properties();
ServletContext context=getServletContext();
//ServletContext提供了一种方法可以获取到文件的绝对路径
//context.getRealPath()获得的项目根目录
//然后根据一般流的方式进行编译
String path = context.getRealPath("file/text.txt");
FileInputStream is=new FileInputStream(path);
properties.load(is);
String usename = properties.getProperty("usename");
System.out.println(usename);
再次改进
利用ServletContext方法getResourceAsStream,
getResourceAsStream(),他的参数是接收一个路径,直接将其装换成流对象
可以直接将下面一行代码
FileInputStream is=new FileInputStream(path);
转换为
InputStream is=getResourceAsStream(path);
通过classloader获取
InputStream is =this.getClass().getClassLoader().getResourceAsStream(../../)
这里俩次上退之后才可以到达项目根目录
代码demo
Insert title here
servert
String username=request.getParameter("username");
String password=request.getParameter("password");
if("admin".equals(username) && "123".equals(password)) {
Object obj=getServletContext().getAttribute("count");
int tcount=0;
if(obj!=null) {
tcount=(int)obj;
}
System.out.println("已知登录成功的次数是:"+tcount);
getServletContext().setAttribute("count",tcount+1);
response.setStatus(302);
response.setHeader("Location","success.html");
}else {
response.getWriter().write("shibai");
}
Insert title here
登录成功
点我看登录过的次数
servlet
int count=(int) getServletContext().getAttribute("count");
System.out.println(count);
response.getWriter().write("chulai"+count);
因为get方式是把数据先拼接到url中,再转发的时候进行了编码。所以在服务器端得先转成tomcat默认的的 ISO-8859-1 格式
代码demo
username.getBytes("ISO-8859-1")
再用jdk的String的 new String(“字节”,“编码”)
username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
方法二
直接在tomcat里面做配置,加上上URIEncoding="utf-8"
POST方式是通过请求体进行传送数据的
故可直接设置请求体编码
request.setCharacterEncoding("UTF-8");
1 以字符流输出
//1. 指定输出到客户端的时候,这些文字使用UTF-8编码
response.setCharacterEncoding("UTF-8");
//2. 直接规定浏览器看这份数据的时候,使用什么编码来看。
response.setHeader("Content-Type", "text/html; charset=UTF-8");
response.getWriter().write("没问题了...");
2 以字节流输出
//1. 指定浏览器看这份数据使用的码表
response.setHeader("Content-Type", "text/html;charset=UTF-8");
//2. 指定输出的中文用的码表
response.getOutputStream().write("没问题了..".getBytes("UTF-8"));
之前的写法
response.setStatus(302);
response.setHeader("location","demo.html");
写法
response.sendRedirect("demo.html");
1. 地址栏显示的是最后访问到的那个页面的地址
2 请求次数至少有俩次,在第一次请求之后。服务器会返回一个302的状态码和一个新的地址。浏览器会根据这个地址执行第二次访问
3 可以访问到任意的路径,不是自己工程的路径也能访问到
4 效率会低一些,因为他执行了俩次请求
5 后续请求,没法再使用request中储存的数据,因为是俩次请求。不是同一个request对象
写法
request.getRequestDispatcher("demo.html").forward(request,response);
1 地址栏上显示的是请求servlet那个页面的地址
2 只请求了一次,后续操作是服务器帮其完成的。返回的状态码为200;
3 只能访问到本项目工程下的路径
4 效率高些,因为只请求了一次
5 可以使用request中储存的东西
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqmwICrL-1576297253833)(http://null/)]
简介:cookie,翻译为饼干。是服务器给客户端并且保存在客户端的一份小数据
应用:自动登录、浏览记录、购物车等
http请求是无状态的。所以客户端和服务器端交流的时候也是无状态的。就是说在客户端第二次访问服务器的时候,服务器根本不知道他原来是来过的。为了更好的客户体验。cookie应运而生
添加Cookie给客户端
Cookie cookie = new Cookie("key","value");
response.add(cookie);
获取客服端带过来的Cookie
Cookie[] cookies =request.getCookie();
if(cookies!=null){
for(Cookie c:cookies){
String cookiename=c.getName();
String cookievalue=c.getValue();
}
}
Cookie的其他常用方法
1 设置cookie的有效期,参数为秒。cookie的生命周期,在浏览器关闭的时候就会失效。
cookie.setMaxAge(60*60*24);
2 改变value值
cookie.setValue(新);
3 指定请求了指定的域名的时候,才会带上cookie
cookie.setDomain("域名");
4 访问指定路径
cookie.setPath("路径");
login.html
Insert title here
处理的Servlet
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
String username=request.getParameter("username");
String password =request.getParameter("password");
if("admin".equals(username) && "123".equals(password)){
Cookie[] cookies = request.getCookies();
Cookie cookie=new CookieUtil().find(cookies, "last");
if(cookie==null) {
Cookie c =new Cookie("last",System.currentTimeMillis()+"");//将cookie的value设置为时间戳
c.setMaxAge(60*60);
response.addCookie(c);
response.getWriter().write("欢迎"+username);
}else {
Long lastTime=Long.parseLong(cookie.getValue());
response.getWriter().write("欢迎您,你上次登录的时间为"+new Date(lastTime));
cookie.setValue(System.currentTimeMillis()+"");//将上次的cookie的value值更新
response.addCookie(cookie);
}
}else {
response.getWriter().write("登录失败");
}
}
Util
package Util;
import javax.servlet.http.Cookie;
public class CookieUtil {
public Cookie find(Cookie[] cookies,String name) {
if(cookies!=null) {
for(Cookie c:cookies) {
if(name.equals(c.getName())) {
return c;
}
}
}
return null;
}
}
由于Cookie是保存在客户端上的,所以会存在安全隐患。并且Cookie的大小和个数有限制
引出了Session ,Session是基于Cookie的一种会话机制,Cookie是服务器返回给客户端上的一个小数据,Session是,所有数据都保存在服务器上的
1 得到会话id
String id=session.getId();
2 存值
sesion.setAttribute(name,value);
3 取值
session.getAttribute(name);
4 移除值
session.removeAttribute(name);
创建:
在Servlet里面调用了request。getSesstion()方法时。Sesstion被创建。
销毁:
1 关闭浏览器。
2 等Session会话的有效期过期。一般默认的有效期为:30分钟。
jsp全程 java Server Page
从用户的角度来看,jsp就是一个页面;从程序员角度看,其实他就是一个java类,并且继承了servlet。所以可以说jsp就是一个servlet类
htmi多数情况下显示的是静态内容,但是有时候我们需要页面显示一些动态的东西。如查询储存在数据库中的学生成绩等等。所以出现了jsp
指令的用法 <%@指令名字 %>
<%@page %>
language
表明jsp中可以写java代码
contentType
告诉浏览器文件类型,编码
contentType="text/html; charset=UTF-8"
text/html MIMEType 这是一个文本,html网页
pageEncoding
jsp内容编码
extends
用于指定jsp翻译成java文件之后,继承的父类是谁,一般不用改
import
用于导包
sesstion
可选值 true or false
用于控制这个jsp页面里能否使用Sesstion对象
errorPage
指的是错误的页面,值需要给错误的页面地址
isErrorPage
声明这个页面是不是错误页面
用法
<%@ include file="demo.jsp"%>
包含另一个jsp的内容进来
用法
<%@ taglib prefix="" uri=""%>
uri: 标签库路径
prefix : 标签库的别名
用法
包含指定的页面,这里是动态包含。不把包含的页面所有元素标签拿过来输出。而是只拿他们的运行结果
用法
前往哪一个页面
用法
在包含某个页面或跳转到某个页面的时候加入这个参数
所谓内置对象,就是我们可以直接在jsp页面中直接使用这些对象不用创建
对作用域对象的理解:这些对象可以存值。但他们的取值是有范围限定的
使用作用域来存储数据
<%
pageContext.setAttribute("name", "page");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
取出四个作用域中的值
<%=pageContext.getAttribute("name")%>
<%=request.getAttribute("name")%>
<%=session.getAttribute("name")%>
<%=application.getAttribute("name")%>
作用范围(由低到高)
pageContext -- request --- session -- application 1 pageContext【pageContext】 作用域仅限于当前页面 还可以获得其他八个内置对象 2 request【HttpServletRequest】 作用域仅限于一次请求,只要服务器做出相应。这个request里面存的值就没有了 3 sesstion 【HTTPSesstion】 作用域仅限于一次会话 4 application【ServletContext】 在整个工程中都可以访问,只有当服务器关闭之后不能继续访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Oee6Mhw5-1576297253835)(http://null/)]
exception 【Throwable】
page 【Object】
jsp翻译成java类的实例对象
config 【ServletConfig】
作用:简化jsp代码,其实就简化在jsp中书写的那些Java代码
写法
${ 表达式 }
<%
pageContext.setAttribute("name", "page");
request.setAttribute("name", "request");
session.setAttribute("name", "session");
application.setAttribute("name", "application");
%>
按普通手段取值
<%= pageContext.getAttribute("name")%>
<%= request.getAttribute("name")%>
<%= session.getAttribute("name")%>
<%= application.getAttribute("name")%>
使用EL表达式取出作用域中的值
${ pageScope.name }
${ requestScope.name }
${ sessionScope.name }
${ applicationScope.name }
如果从作用域中取值,会先从小的作用域开始取,如果没有,就往下一个作用域取。 一直把四个作用域取完都没有, 就没有显示。
<%
String [] a = {"aa","bb","cc","dd"};
pageContext.setAttribute("array", a);
%>
使用EL表达式取出作用域中数组的值
${array[0] } , ${array[1] },${array[2] },${array[3] }
demo:
<%
String[] a={"1","2","3"};
pageContext.setAttribute("age", a);
%>
${pageScope.age[0] },${pageScope.age[1] },${pageScope.age[2] }
<%
Map map = new HashMap();
map.put(“name”, “zhangsna”);
map.put(“age”,18);
map.put(“address”,”北京..”);
map.put("address","深圳..");
pageContext.setAttribute("map", map);
%>
${map.name } , ${map.age } ,${map.address } , ${map.address}
demo:
<%
Map map =new HashMap();
map.put("name", "zhangsan");
map.put("age", "13");
pageContext.setAttribute("list", map);
%>
${pageScope.list.name }
${pageScope.list.age }
1 取值方式(如果这份值是有下标 的,直接用[])
<%
String [] array = {"aa","bb","cc"}
session.setAttribute("array",array);
%>
${ array[1] }
2 如果没有下标,直接使用 . 的方式去取
<%
User user = new User("zhangsan",18);
session.setAttribute("u", user);
%>
${ u.name } , ${ u.age }
总结:一般使用EL表达式,用的比较多的。都是从一个对象中取出他的属性值
用法
${ 对象名.成员 }
作用域相关的对象
头信息相关的对象
参数信息相关的对象
全局初始化参数
全称 : JSP Standard Tag Library jsp标准标签库
作用: 简化jsp的代码编写,替换<%%>的写法格式。一般与EL表达式配合
1 导入jar文件到工程中
2 在jsp页面上,使用taglib指令,来引入标签库
3 值得注意的是,如果想支持EL表达式,那么必须引入的标签库为1.1的版本,1.0的不支持EL表达式
<%@ taglib prefix=”c” uri=”http://java.sun.com/jsp/jstl/core” %>
常用标签
1 c:set
${sessionScope.name }
2 c:if
年龄大于了26岁...
年龄小于了26岁...
定义一个变量名 flag 去接收前面表达式的值,然后存在session域中
年龄大于了26岁...
3 c:forEach
从1 开始遍历到10 ,得到的结果 ,赋值给 i ,并且会存储到page域中, step , 增幅为2,
${i }
-----------------------------------------------
${user.name } ----${user.age }