JavaWeb总结
文章目录
JavaWeb的概念
JavaWeb是指使用java语言配合web容器编写出可以通过浏览器访问的程序的总称,它是基于请求和响应来进行开发的。
请求(request)就是客户端向服务端发送数据,
响应(response)就是服务器给客户端回传数据
所以我们要编写web程序通常就需要配置好各项环境和各种包,其中服务器就是必不可少的一项。
常用的Web服务器
一、Tomcat
1、什么是Tomcat?
tomcat是一个开源而且免费的jsp服务器,属于轻量级应用服务器。它可以实现JavaWeb程序的装载。
2、Tomcat的下载和在IDEA中的安装配置
示范环境为:win10 64位系统,IDEA,Tomcat9
第一步:下载Tomcat服务器
首先到Tomcat的官网(http://tomcat.apache.org/)下载Tomcat,(根据自己的jdk版本选择tomcat版本,如果版本不相应的话可能会导致运行报错,比如我是jdk14,可以下载Tomcat8),下载完后将解压包移动到随意一个路径,最好不要含有中文名,例如我解压在D:\tomcat 中
第二步:配置Tomcat环境变量
不配置环境变量也可以,可以直接从Tomcat安装路径bin目录中找到"startup.bat"打开服务器
1、右击此电脑->属性->高级系统设置->高级->环境变量
2、在"系统变量"里新建变量名:CATALINA_HOME,变量值是第一步下载的Tomcat安装包解压好的路径。
如果要配置多个版本的Tomcat的话需要在配置一个CATALINA_BASE变量,详情自己百度“如何配置多个版本的Tomcat”
3、在"系统变量"里打开Path变量,添加变量值:
%CATALINA_HOME%\bin
第三步:启动Tomcat服务器
打开命令提示窗口输入catalina就可以看到Tomcat的详细信息,
输入"catalina run"或者"startup"打开tomcat服务器
不要关闭这个命令行窗口,打开浏览器,在地址栏中输入http://localhost:8080,如果出现小猫页面则代表安装成功
控制台乱码现象解决方法
找到tomcat安装目录,找到conf下的logging.properties文件,将其中的
java.util.logging.ConsoleHandler.encoding = UTF-8
修改为
java.util.logging.ConsoleHandler.encoding = GBK
即可解决
Tomcat文件目录介绍
第四步:将Tomcat服务器整合到IDEA中使用
打开IDEA->File->Settings->Build,Execution,Deployment->Application Servers 配置好tomcat的路径,完成
第五步:创建一个动态Web工程项目
1、File->New->Project->Java Enterprise–>Web Application->Next->Finish,这样一个动态Web工程项目就创建好了
二、Servlet
1、什么是Servlet?
Servlet是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。它可以接受客户端发送的请求并响应给客户端。
2、如何创建一个Servlet?
第一步:创建Servlet实现类或者继承类
Servlet是一个java程序,所以我们在src下面创建一个包去放Servlet程序,可以用new->Servlet(注意是否使用注解创建serlvet)或者新建一个类去实现Servlet接口或者继承HttpServlet类(一般实际开发中都是选择后者)
/* 继承HttpServlet类 */
public class servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
/* 实现Servlet接口 */
public class servlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
第二步:在web.xml文件中配置servlet的信息
web.xml文件在WEB-INF中
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- servlet标签是给Tomcat配置Servlet程序 -->
<servlet>
<!-- servlet-name标签是给servlet程序起一个别名(一般是类名) -->
<servlet-name>servlet</servlet-name>
<!-- servlet-class是servlet程序的全类名 -->
<servlet-class>com.linzhijie.Servlet.servlet</servlet-class>
</servlet>
<!-- servlet-mapping标签是给servlet程序配置访问地址 -->
<servlet-mapping>
<!-- servlet-name标签的作用是告诉服务器当前配置的地址是给哪个servlet使用 -->
<servlet-name>servlet</servlet-name>
<!-- url-pattern标签是配置访问地址,就是要访问到这个servlet要前往的地址 -->
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
</web-app>
2.1 为什么选择继承HttpServlet类而不是实现Servlet接口?
因为Servlet是一个接口,所以实现servlet接口必须实现接口中所有的方法,而继承HttpServlet类可以只重写类中的一个或多个方法
3、Servlet的生命周期
在第一次访问的时候首先会执行Servlet构造器方法,然后执行init方法,随后每次访问都会调用service方法,在工程停止时会执行destroy方法。doGet方法和doPost方法在具体需要的时候执行。
4、ServeletConfig类
ServletConfig是Servlet程序的配置信息类,每个Servlet程序创建时就会自动创建一个ServletConfig对象,它可以获取Servlet程序的别名,获取初始化参数init-param(如果有在web.xml的servlet标签里配置init-param的话),获取ServletContext(上下文对象)对象
5、ServletContext类
Servelt上下文对象,ServletContext是一个域对象,一个Web工程只有一个ServletContext对象实例,它在Web工程部署启动的时候创建,在Web工程停止的时候销毁。
5.1 什么是域对象?
像Map一样存取数据的对象,这里的域指是整个Web工程目录,与Map的区别:
5.2 ServletContext的用处
- 获取在web.xml配置的上下文参数(在web-app标签中即可,不受其他标签约束)
- 获取当前的工程路径
- 获取工程部署后在服务器硬盘的绝对路径
- 像Map一样存取数据
6、HttpServletRequest类
我们通过HttpServletRequest对象从服务器获取客户端(浏览器)的信息
6.1 常用方法
6.2 请求转发(包含)
请求转发(包含)指的是服务器收到客户端的请求后从一个资源跳转到另外一个资源的操作。
举个例子来说客户端发起了一次请求,第一个servlet程序要你稍等一下,然后它自己到另一个servlet去获取你想要的资源给你,最后你拿着资源回到客户端(浏览器)。
6.2.1 特点
- 浏览器的地址栏没有发生变化
- 一次请求一次响应
- 共享Request域中的数据
- 只能访问该网站的内部资源和WEB-INF中的资源(如servlet,jsp,html等)
- 不可以访问网站外部的资源(如转发到百度页面)
6.2.2 使用
使用Request对象实现请求转发(包含),需要用到下面两个方法
什么时候使用请求转发什么时候使用请求包含看这篇博文
请求转发和请求包含
request.getRequestDispatcher("/要转发的资源路径").forward(request,response);
7、HttpServletResponse类
我们通过HttpServletResponse对象从服务器返回给客户端(浏览器)信息
7.1 常用的两个输出流
7.2 请求重定向
请求重定向指客户端给服务器发请求,然后服务器回传一个地址让客户端去新地址访问。像一个网址已经迁移到别的地址,然后你仍然去访问这个地址,它就会回传一个新地址让你去重新访问。
7.2.1 特点
- 浏览器地址栏会改变
- 请求-响应-再请求
- 不共享Request域中的数据
- 不能访问WEB-INF中的资源
- 可以访问工程之外的资源(比如百度等网站)
7.2.2 使用
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("http://www.baidu.com");
}
8、请求和响应的中文乱码解决
设置请求体的字符即为UTF-8就可以解决请求的中文乱码问题,最好在进行其他操作之前设置。
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
}
三、JSP
1、什么是JSP?
JSP(全称Java Server Pages),是一种动态网页开发技术,它的本质是一种Servlet,它的出现大部分是因为用常规servlet回传html页面数据太过于繁琐,开发起来成本较高。
2、JSP的本质
JSP的本质是一个Servlet程序,当我们第一次访问jsp页面时, 服务器会把jsp页面翻译成一个java源文件,并把它编译成字节码文件进行运行,其中查看你源文件的内容会发现源文件的类归根结底是间接继承HttpServlet,并且通过out.println()将页面的内容输出。
3、JSP页面的使用
JSP页面除了静态的html代码外还有许多语法让我们去使用,其中包括头部的page指令、声明脚本、表达式脚本、代码脚本等脚本供我们使用开发。
3.1 头部page指令
通常jsp页面的第一行代码都是以下这行代码,这是jsp页面中的page指令,它控制着jsp页面中的一些重要的属性和行为,不只只有这两个属性。一个jsp页面可以含有多个头部指令。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
以上两个属性及其他属性介绍,
3.2 JSP其他指令
3.2.1 引入标签库
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>
prefix是定义的标签的前缀,uri是要使用的标签库的一个资源的定位
3.2.2 静态包含
静态包含就是将被包含的文件编译好后复制到包含的页面中输出,像是将一个页面分多个板块,然后都分离开来处理最后再用静态包含拼接起来成一个页面。
<%@include file="1.jsp"%>
3.3 脚本程序
脚本程序可以包含任意量的Java语句、变量、方法或表达式,只要它们在脚本语言中是有效的。
<% 代码片段 %>
3.3.1 声明脚本
一个声明语句可以声明一个或多个变量、方法,供后面的Java代码使用。在JSP文件中,您必须先声明这些变量和方法然后才能使用它们。
<%! int i = 0; %>
<%! int a, b, c; %>
<%! Circle a = new Circle(2.0); %>
3.3.2 表达式脚本
表达式脚本可以在jsp页面代码中的任意一个位置输出数据,但是不能以分号来结束表达式。
<%!double balance=100.0; %>
<h1>您的余额为<%=balance%></h1>
3.3.3 注释
4、JSP九大内置对象
九大内置对象就是JSP的隐置对象,它们是JSP页面中的java对象
request对象
request对象提供了一系列方法来获取HTTP头信息,cookies,HTTP方法等等。
response对象
通过这个对象,开发者们可以添加新的cookies,时间戳,HTTP状态码等等。
out对象
jsp页面的输出流对象。
out对象的输出和response.getWriter()的输出的区别
两者的输出虽然都是向页面输出信息的,但是他们的输出顺序和执行顺序是不同的。
out对象有一个out缓冲区,我们使用out对象输出的时候它会把输出的数据写入out缓冲区,out.flush()刷新操作会将out缓冲区的数据追加到response缓冲区中,最后才输出。
而response.getWriter()的输出则是直接写入response缓冲区,然后执行刷新操作输出到页面中。
session对象
session对象用来跟踪在各个客户端请求间的会话。
application对象
application对象直接包装了servlet的ServletContext类的对象,是javax.servlet.ServletContext 类的实例。 这个对象在JSP页面的整个生命周期中都代表着每个JSP页面。这个对象在每个JSP页面初始化时被创建,随着jspDestroy()方法的调用即关闭服务器而被移除。
通过向application中添加属性,则所有组成您web应用的JSP文件都能访问到这些属性。
config对象
config对象是 javax.servlet.ServletConfig 类的实例,直接包装了servlet的ServletConfig类的对象。
这个对象允许开发者访问Servlet或者JSP引擎的初始化参数,比如文件路径等。
pageContext 对象
代表整个JSP页面,application是pageContext的一种。 这个对象存储了request对象和response对象的引用。application对象,config对象,session对象,out对象可以通过访问这个对象的属性来导出。
pageContext对象也包含了传给JSP页面的指令信息,包括缓存信息,ErrorPage URL,页面scope等。看起来pageContext对象的作用域范围很大,但其实只是在一个jsp页面中的作用域。
page 对象
这个对象就是页面实例的引用。它可以被看做是整个JSP页面的代表。
page 对象就是this对象的同义词。
exception 对象
exception 对象包装了从先前页面中抛出的异常信息。它通常被用来产生对出错条件的适当响应。
5、JSP四大域对象
域对象是可以存取数据的对象,以下这四个域对象的功能一样,只是数据的存取范围不同。
1、pageContext域对象只在当前这个jsp页面存取数据,离开了当前的jsp页面pageContext域对象的数据就丢失了。
2、request域域对象只在相同一个request链中存取数据,如果发起其他请求的话这个request域对象中的数据也就没有了。
3、session域对象在创建session的生命周期中(默认为30分钟)和浏览器关闭之前存取数据,如果关闭了浏览器或者session过期时间到了,那么session域对象中的数据就丢失了。
4、application域对象,它的作用域范围值四个域对象中最大的,只要web工程不销毁,他就会一直可以存取数据,直到服务器关闭。
6、JSP的其他标签
6.1 动态包含
<jsp:include page="/footer.jsp"></jsp:include>
6.2 转发标签
<jsp:forward page="index.jsp"></jsp:forward>
四、EL表达式和JSTL标签库
EL表达式和JSTL标签库都是为了程序员在jsp中能更方便地进行jsp页面的数据以及功能的操作和维护
1、EL表达式(JSP表达式语言)
1.1 定义
EL(Expression Language)表达式,是JSP表达式语言。它提供了在 JSP 中简化表达式的方法,让JSP输出的代码更加简化。
1.2 作用
代替JSP页面中的表达式脚本进行数据的输出。
当访问的数据为null时,使用EL表达式将会输出空串,
而使用JSP表达式脚本输出的话会是一个"null"字符串。
1.3 语法格式
${表达式}
表达式可以是 数字、字符串、数组、对象等等
1.4 基础操作符
包括.,[],()运算符,算数运算符,关系运算符,逻辑运算符,empty运算,以及三元运算符
操作符 | 描述 |
---|---|
. | 访问Bean属性或者其他属性 |
[] | 访问数组或者链表中的元素 |
() | 组织一个子表达式以改变优先级 |
+, - ,* ,/ ,div ,% ,mod | 加减乘除取模 |
== ,eq | 相等 |
!= ,ne | 不等 |
< ,lt | 小于 |
,gt | 大于
<= ,le | 小于等于
= ,ge | 大于等于
&& ,and | 逻辑与
|| ,or | 逻辑或
! ,not | 取反
empty | 测试是否空值,当值为null,空串,长度为0的数组,list,map集合返回true
表达式1?表达式2:表达式3:| 三元运算
empty运算的使用
${empty 表达式}
1.5 EL中的隐含对象
EL中定义了11个隐含对象,这些隐含对象可以很方便的获取一些开发中常用的对象,不需要事先定义,可以直接使用。
隐含对象 | 描述 |
---|---|
pageContext | 当前页面的pageContext,通过pageContext对象可以访问到jsp的九大内置对象 |
pageScope | page 作用域,可以获取pageContext域中的数据 |
requestScope | request 作用域,可以获取request域中的数据 |
sessionScope | session 作用域,可以获取session域中的数据 |
applicationScope | application 作用域,可以获取ServletContext域中的数据 |
initParam | 获取上下文初始化参数(返回字符串) |
param | 获取单个请求参数的值(返回字符串),类似request.getParameter(); |
paramValues | 获取多个请求参数的值(返回字符串集合),类似request.getParameterValues(); |
header | 获取HTTP 信息头(返回字符串) |
headerValues | 获取多个HTTP 信息头(返回字符串集合) |
cookie | 获取当前请求的Cookie值(返回Cookie对象) |
如何使用这些隐含对象?
<!-- pageContext对象的使用 -->
${pageContext.request.servletName}
<!-- Scope对象的使用 -->
<!--
如果四个域对象中都有相同的key的时候,应该在使用前加上是哪个域调用的,
否则将会根据作用域的大小顺序从小到大调用(pageScrope域没有就找requestScope域,以此类推)
-->
${requestScrope.key}
<!-- param对象的使用 -->
${param.username}
<!-- paramValues对象的使用 -->
${paramValues.hobby[0]}
<!-- initParam 对象的使用 -->
${initParam.username}
<!-- header 对象的使用 -->
${header.Connection}
${header['User-Agent']}
<!-- headerValues 对象的使用 -->
${headerValues['User-Agent'][0]}
<!-- cookie 对象的使用 -->
${cookie.JSESSIONID.name}
2、JSTL标签库
2.1 定义
JSTL(JSP Standard Tag Library) JSP标签库是一个不断完善的开放源码JSP标签库。需要我们自己去官网下载(自行根据操作系统和自己想要的JSTL版本号进行下载)。JSTL标签库下载地址
2.2 作用
EL表达式是为了代替JSP的表达式脚本,而标签库则是替换掉JSP的代码脚本,使整个JSP页面变得更加整洁。
2.3 组成
JSTL由五个不同功能的标签库组成
功能范围 | URI | 前缀 |
---|---|---|
核心标签库(重点) | http://java.sun.com/jsp/jstl/core | c |
格式化 | http://java.sun.com/jsp/jstl/fmt | fmt |
函数 | http://java.sun.com/jsp/jstl/functions | fn |
数据库(不使用) | http://java.sun.com/jsp/jstl/sql | sql |
XML(不使用) | http://java.sun.com/jsp/jstl/xml | x |
2.4 使用
第一步:下载JSTL标签库的zip包并解压
第二步:将解压完后的JSTL包lib目录中的standard.jar 和 jstl.jar 文件拷贝到 /WEB-INF/lib/ 下。
第三步:在jsp中使用,记得得在头部加头部page指令导入jstl库,如导入核心标签库,
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2.5 核心标签库
核心标签是最常用的 JSTL标签。引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签 | 描述 |
---|---|
<c:out> | 用于在JSP中显示数据,就像<%= … > |
<c:set> | 用于保存数据 |
<c:remove> | 用于删除数据 |
<c:catch> | 用来处理产生错误的异常状况,并且将错误信息储存起来 |
<c:if> | 与我们在一般程序中用的if一样 |
<c:choose> | 本身只当做<c:when>和<c:otherwise>的父标签 |
<c:when> | <c:choose>的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行 |
<c:import> | 检索一个绝对或相对 URL,然后将其内容暴露给页面 |
<c:forEach> | 基础迭代标签,接受多种集合类型 |
<c:forTokens> | 根据指定的分隔符来分隔内容并迭代输出 |
<c:param> | 用来给包含或重定向的页面传递参数 |
<c:redirect> | 重定向至一个新的URL. |
<c:url> | 使用可选的查询参数来创造一个URL |
2.6 格式化标签
JSTL格式化标签用来格式化并输出文本、日期、时间、数字。引用格式化标签库的语法如下:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
标签 | 描述 |
---|---|
fmt:formatNumber | 使用指定的格式或精度格式化数字 |
fmt:parseNumber | 解析一个代表着数字,货币或百分比的字符串 |
fmt:formatDate | 使用指定的风格或模式格式化日期和时间 |
fmt:parseDate | 解析一个代表着日期或时间的字符串 |
fmt:bundle | 绑定资源 |
fmt:setLocale | 指定地区 |
fmt:setBundle | 绑定资源 |
fmt:timeZone | 指定时区 |
fmt:setTimeZone | 指定时区 |
fmt:message | 显示资源配置文件信息 |
fmt:requestEncoding | 设置request的字符编码 |
2.7 JSTL函数
JSTL包含一系列标准函数,大部分是通用的字符串处理函数。引用JSTL函数库的语法如下:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
标签 | 描述 |
---|---|
fn:contains() | 测试输入的字符串是否包含指定的子串 |
fn:containsIgnoreCase() | 测试输入的字符串是否包含指定的子串,大小写不敏感 |
fn:endsWith() | 测试输入的字符串是否以指定的后缀结尾 |
fn:escapeXml() | 跳过可以作为XML标记的字符 |
fn:indexOf() | 返回指定字符串在输入字符串中出现的位置 |
fn:join() | 将数组中的元素合成一个字符串然后输出 |
fn:length() | 返回字符串长度 |
fn:replace() | 将输入字符串中指定的位置替换为指定的字符串然后返回 |
fn:split() | 将字符串用指定的分隔符分隔然后组成一个子字符串数组并返回 |
fn:startsWith() | 测试输入字符串是否以指定的前缀开始 |
fn:substring() | 返回字符串的子集 |
fn:substringAfter() | 返回字符串在指定子串之后的子集 |
fn:substringBefore() | 返回字符串在指定子串之前的子集 |
fn:toLowerCase() | 将字符串中的字符转为小写 |
fn:toUpperCase() | 将字符串中的字符转为大写 |
fn:trim() | 移除首尾的空白符 |
注:JSTL表签库的使用还应实践使用练习,以上只是列出有哪些标签
五、Cookie&Session
1、Cookie
Cookie 是存储在客户机的文本文件,它们保存了大量轨迹信息。是服务器通知客户端保存键值对的一种技术,每个Cookie的大小不超过4kb。
Cookie 通常在 HTTP 信息头中设置,信息头中有一个Set-Cookie信息头,它包含一个或多个键值对,键值对会被编码为URL。有效期域是个指令,告诉浏览器在什么时候之后就可以清除这个 cookie。
如果浏览器被配置成可存储 cookie,那么它将会保存这些信息直到过期。如果用户访问的任何页面匹配了 cookie 中的路径和域名,那么浏览器将会重新将这个 cookie 发回给服务器。
1.2 Cookie的创建
第一步:创建一个Cookie对象
调用 cookie 的构造函数,使用一个 cookie 名称和值做参数,它们都是字符串。
Cookie cookie = new Cookie("key","value");
名称和值中都不能包含空格或者如下的字符:
[ ] ( ) = , " / ? @ : ;
第二步:设置有效期
调用 setMaxAge() 函数表明 cookie 在多长时间(以秒为单位)内有效。
cookie.setMaxAge(60*60*24);
第三步:将 cookie 发送至 HTTP 响应头中
调用 response.addCookie() 函数来向 HTTP 响应头的Set-Cookie信息头中添加 cookie。这样客户端才能保存cookie。
response.addCookie(cookie);
1.3 Cookie的获取
获取 cookie需要调用 request.getCookies() 方法来获得一个Cookie 对象的数组,然后遍历这个数组,最后使用 getName() 方法和 getValue() 方法来获取每一个 cookie 的名称和值。
Cookie[] cookies = request.getCookies();
for(Cookie cookie:cookies){
out.println("Cookie的key为"+cookie.getName()+",value为:"+cookie.getValue()+"<br/>");
}
// 查找cookie的方法
public static void findCookie(String name,Cookie[] cookies){
if(name==null||cookies==null||cookies.length=0){
return 0;
}
for(Cookie cookie:cookies){
if(name.equals(cookie.getName())){
return cookie;
}
}
return null;
}
1.4 Cookie的修改
先创建一个和要修改的cookie名称一样的cookie,在构造器中将value设置为要修改完成后的内容,最后将其添加到响应头中,就可以实现Cookie的修改。
Cookie cookie = new Cookie("key","newvalue");
response.addCookie(cookie);
1.5 Cookie的删除
先获取要删除的cookie,然后将其的有效生存期设置为0,最后将cookie添加到响应头中,就可以实现Cookie的删除。
Cookie[] cookies = request.getCookies();
Cookie cookie = findCookie("key",cookies)
cookie.setMaxAge(0);
response.addCookie(cookie);
1.6 Cookie有效路径的配置
设置 cookie 的路径,可以有效地过滤哪些cookie可以发送给服务器,哪些不能。默认为当前页面目录下的所有 URL,还有此目录下的所有子目录。
Cookie cookie = new Cookie("key","value");
cookie.setPath(request.getContextPath+"/xxx");
cookie.addCookie(cookie);
2、Session
HTTP是无状态协议,这意味着每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会记录下先前客户端请求的任何信息。
JSP利用servlet提供的HttpSession接口来识别一个用户,在服务器存储这个用户的所有访问信息。Session依赖于SessionID,而SessionID存储在客户端的Cookie中。
2.1 Session的创建和获取
Session的创建和获取和Cookie类似,Session不需要我们去创建,当我们第一次去调用Session时它就会去创建,第二次调用就是获取第一次创建的Session会话对象。我们通过isNew()方法判断Session是否是新创建出来的。true表示是,false表示不是。每一个会话都有一个唯一的ID值,可以通过getID()方法获取。
Integer visit_count = new Integer(1);
if(session.isNew()){
out.println("第1次访问");
session.setAttribute("visit_count",visit_count);
}else{
visit_count = (Integer) session.getAttribute("visit_count");
visit_count+=1;
session.setAttribute("visit_count",visit_count);
out.println("第"+session.getAttribute("visit_count")+"次访问");
}
2.2 Session的生命周期控制
一般情况下,当客户端和服务器建立连接时,session就创建了,session的默认超时时长是30分钟,即30分钟后会销毁。如果要更改默认时长可以在web.xml中修改。
<session-config>
<session-timeout>20</session-timeout>
</session-config>
如何使Session销毁
- 可以直接断开与服务器的连接(关闭会话)
- 设置Session的超时时间(以秒为单位)使用setMaxInactiveInterval(int interval),传入值为正数时设定时长,负数或者0时为永不超时。设置个别Session的超时时长用这个方法。
- 调用invalidate()让当前对话马上超时无效。
2.3 Session的重要方法
方法 | 方法描述 |
---|---|
public Object getAttribute(String name) | 返回session对象中与指定名称绑定的对象,如果不存在则返回null |
public Enumeration getAttributeNames() | 返回session对象中所有的对象名称 |
public long getCreationTime() | 返回session对象被创建的时间, 以毫秒为单位,从1970年1月1号凌晨开始算起 |
public String getId() | 返回session对象的ID |
public long getLastAccessedTime() | 返回客户端最后访问的时间,以毫秒为单位,从1970年1月1号凌晨开始算起 |
public int getMaxInactiveInterval() | 返回最大时间间隔,以秒为单位,servlet 容器将会在这段时间内保持会话打开 |
public void invalidate() | 将session无效化,解绑任何与该session绑定的对象 |
public boolean isNew() | 返回是否为一个新的客户端,或者客户端是否拒绝加入session |
public void removeAttribute(String name) | 移除session中指定名称的对象 |
public void setAttribute(String name, Object value) | 使用指定的名称和值来产生一个对象并绑定到session中 |
public void setMaxInactiveInterval(int interval) | 用来指定时间,以秒为单位,servlet容器将会在这段时间内保持会话有效 |
六、Listener监听器
监听器(Listener)是JavaWeb的三大组件之一,它在web中的作用是监听某种事物的变化,如servlet的创建,销毁等等。然后通过回调函数反馈给程序去做相应的处理。
例如监听ServletContext对象
先写一个监听器实现类
package com.linzhijie.Listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class servletListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext对象创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("servletContext对象销毁了");
}
}
再到web.xml配置监听器
<listener>
<listener-class>com.linzhijie.Listener.servletListener</listener-class>
</listener>
这样一个监听器就完成了。
七、Filter过滤器
1、定义
过滤器(Filter)是JavaWeb三大组件之一,它可以动态地拦截请求和过滤响应,以变换或使用包含在请求或响应中的信息。它常用于身份验证、加密、触发资源访问事件、日志记录和审核等等用途,是十分实用的一个接口。
2、过滤器的常用方法
过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:
方法 | 描述 |
---|---|
public void init(FilterConfig filterConfig) | web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。 |
public void doFilter (ServletRequest, ServletResponse, FilterChain) | 该方法完成实际的过滤操作,当客户端的请求与过滤器设置的 URL 匹配时,Servlet 容器将先调用过滤器的 doFilter 方法。FilterChain 用于访问后续过滤器。 |
public void destroy() | Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。 |
3、FilterChain过滤器链
即多个过滤器一起工作。所有的filter和目标资源都是默认执行在同一个线程中,当多个filter共同执行时使用的是同一个request对象。FilterChain.doFilter()方法是如果有下一个过滤器则执行下一个过滤器,否则执行目标资源。在多个filter过滤器执行的时候,执行的优先顺序取决于它们在web.xml中的上下顺序
4、Filter的拦截路径
- 精确匹配:
<url-pattern>/target.jsp</url-pattern>
- 目录匹配:
<url-pattern>/admin/*</url-pattern>
- 后缀名匹配:
<url-pattern>*.html</url-pattern>
Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在。
5、Filter过滤器的使用
第一步:创建Filter类
import javax.servlet.*;
import java.io.IOException;
public class loginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 在这里可以获取init-param参数和初始设置
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 在这里执行过滤器要执行的操作
}
@Override
public void destroy() {
// 过滤器销毁
}
}
第二步:在web.xml中配置过滤器
<!-- 指定过滤器 -->
<filter>
<!-- 用于为过滤器指定一个名字,该元素的内容不能为空。 -->
<filter-name>loginFilter</filter-name>
<!-- 元素用于指定过滤器的完整的限定类名。 -->
<filter-class>com.linzhijie.Filter.loginFilter</filter-class>
</filter>
<!-- 元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径 -->
<filter-mapping>
<!-- 子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字 -->
<filter-name>loginFilter</filter-name>
<!-- 设置 filter 所拦截的请求路径(过滤器关联的URL样式) -->
<url-pattern>/.*</url-pattern>
</filter-mapping>
八、JSON、AJAX、i18n
1、JSON
1.1 定义
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。体积小,易解析。JSON也可以称为无类型对象。
1.2 格式
var 变量名 = {
"key1":value, // Number类型
"key2":"value", // 字符串类型
"key3":[], // 数组类型
"key4":{"key4-1":"value"} // Json对象类型
"key5":[{"key5-1":value},{"key6-1":value}] // Json数组
};
1.3 在JS中的使用
如何访问JSON中的值
/* 1、Json的基本使用 */
// 创建一个json对象
var jsons = {
"key1":1,
"key2":"abc",
"key3":[1,2,"a"],
"key4":{"key4_1":1,"key4_2":"abc"},
"key5":[{"name":"zhangsan","age":11},{"name":"li","age":13},{"name":"wangwu","age":17}]
};
// 访问jsons对象中的数据
// 这边有一个小细节,如果json对象中的key值命名包含关键字或者符号,则需要使用[]符号来进行取key值
alert(jsons.key1);
alert(jsons.key2);
alert(jsons); // [object Object]
alert(jsons.key3); // 1,2,a
alert(jsons.key3[1]); // 2
alert(jsons.key4); // [object Object]
alert(jsons.key4["key4-1"]); // 1
alert(jsons.key4[1]) // undefined
alert(jsons.key5[1].name); //li
// Json的遍历
for (var i=0;i<3;i++){
alert(jsons.key3[i]);
}
alert(jsons.key4.key4_1);
alert(jsons.key4.key4_2);
for (var i=0;i<3;i++) {
alert(jsons.key5[i].name + " " + jsons.key5[i].age);
}
转换JSON对象和字符串的方法
函数 | 描述 |
---|---|
JSON.stringify( json ); | 可以把一个 json 对象转换成为 json 字符串 |
JSON.parse( jsonString ); | 可以把一个 json 字符串转换成为 json 对象 |
// 将json对象转换为json字符串
var jsonString = JSON.stringify(jsons);
alert(jsonString);
/*
{"key1":1,
"key2":"abc",
"key3":[1,2,"a"],
"key4":{"key4-1":1,"key4_2":"abc"},
"key5":[{"name":"zhangsan","age":11},{"name":"li","age":13},{"name":"wangwu","age":17}]
}
*/
// 将json字符串转换为json对象
var jsonObj = JSON.parse(jsonString);
alert(jsonObj); // [object Object]
alert(jsonObj.key3) // 1,2,a
1.4 JSON在java中的使用
要使用json在java中使用需要导入一个第三方包———gson.jar
Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。
像是在JS中使用两个函数之前需要使用到的JSON对象。
它可以将一个 JSON 字符串转成一个 Java 对象,或者把一个JSON对象转换为JSON字符串
方法 | 描述 |
---|---|
toJson() | java对象转换成json字符串 |
fromJosn() | json字符串转换成java对象 |
json 在 java 中的操作。常见的有三种情况。
- java 对象和 json 的转换
- java 对象 list 集合和 json 的转换
- map 对象和 json 的转换
要把复杂的json字符串转换为java对象需要创建一个类继承TypeToken类,并把返回的类型当成TypeToken的泛型注入
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JsonTest {
static class Person{
int no;
String name;
public Person(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
// json操作一定要先创建一个gson对象
Gson gson = new Gson();
// 创建Person对象
Person person = new Person(10, "zhangsan");
// 1、java 对象和 json 的转换
// java对象转换成json字符串
String personJson = gson.toJson(person);
System.out.println("转换成json字符串为:"+personJson);
// json字符串转换成java对象
Person person1 = gson.fromJson(personJson, Person.class);
System.out.println(person1);
System.out.println("===================================================");
// 2、java 对象 list 集合和 json 的转换
List<Person> personList = new ArrayList<>();
for (int i=0;i<3;i++){
personList.add(new Person(10+i,"zhangsan"+i));
}
// java对象转换成json字符串
String personListJson = gson.toJson(personList);
System.out.println("转换成json字符串为:"+personListJson);
// json字符串转换成java对象
List<Person> list = gson.fromJson(personListJson, new TypeToken<List<Person>>() {
}.getType());
System.out.println(list);
System.out.println("===================================================");
// 3、map 对象和 json 的转换
Map<Integer,Person> personMap = new HashMap<>();
for (int i=0;i<3;i++){
personMap.put(i,new Person(i,"lisi"+i));
}
// java对象转换成json字符串
String personMapJson = gson.toJson(personMap);
System.out.println("转换成json字符串为:"+personMapJson);
// json字符串转换成java对象
Map<Integer,Person> map = gson.fromJson(personMapJson, new TypeToken<Map<Integer, Person>>() {
}.getType());
System.out.println(map);
}
}
2、AJAX
2.1 定义
AJAX(Asynchronous JavaScript and XML)异步的JavaScript和XML 是在不重新加载整个页面的情况下与服务器交换数据并更新部分网页的技术。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。而通过AJAX在后台与服务器进行少量数据交换,可以使网页实现异步更新。
例如注册账号时可以检测用户名是否被人注册过,如果被人注册过了会在旁边提示这个用户名已经被人注册过了,请您更改。
2.2 原生的AJAX请求
客户端:
第一步:创建 XMLHttpRequest 对象
var xmlHttpRequest = new XMLHttpRequest();
第二步:向服务器发送请求,调用open方法设置参数,send方法发送请求。
一般会在send方法之前绑定好onreadystatechange事件处理请求完成后的操作
xmlHttpRequest.open(method:String,url:String,async:boolean);
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState==4&&xmlHttpRequest.status==200){
}
}
xmlHttpRequest.send();
示例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>AjaxRequest</title>
</head>
<script type="text/javascript">
function ajaxRequest() {
// 创建 XMLHttpRequest 对象
var xmlHttpRequest = new XMLHttpRequest();
// 调用open方法设置请求参数
xmlHttpRequest.open("GET","http://localhost:8080/WebTest/ajaxServlet?action=JavaScriptAjax",true);
xmlHttpRequest.open()
// 绑定onreadystatechange事件
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState==4&&xmlHttpRequest.status==200){
var jsonObj = JSON.parse(xmlHttpRequest.responseText);
document.getElementById("div0").innerHTML = "编号:"+jsonObj.no+"姓名:"+jsonObj.name;
}
}
// 发送请求
xmlHttpRequest.send();
}
</script>
<body>
<button onclick="ajaxRequest()">ajax请求</button>
<div id="div0"></div>
</body>
</html>
服务器端:
第三步:创建好类和方法处理请求
实例中的Person类自己创建
import com.linzhijie.Pojo.Person;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AjaxServlet extends BaseServlet {
/**
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void JavaScriptAjax(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Person person = new Person(1,"张三");
Gson gson = new Gson();
String s = gson.toJson(person);
resp.getWriter().write(s);
}
}
这样一个原生的AJAX请求就完成了。
2.3 JQuery中的AJAX请求
JQuery中将ajax请求变得比原生的ajax请求简洁明了,省去了原生创建ajax请求的麻烦。其中有一点要注意的是在请求成功中的回调函数要加上参数data,这样才能获取到后端传过来的值。
$.ajax()方法
参数 | 描述 |
---|---|
url | 请求的地址 |
type | 请求的方式 |
data | 请求的参数,可以传字符串或者是json |
success | 请求成功后的回调函数 |
dataType | 返回的数据类型 |
$.ajax({
url:"http://localhost:8080/WebTest/ajaxServlet",
// data:action="JQueryAjax",
data:{action:"JQueryAjax",key:value},
type:"GET",
success:function (data) {
$("#msg").html("ajax 编号:" + data.no + " , 姓名:" + data.name);
},
dataType:"json"
});
$.get()方法
参数 | 描述 |
---|---|
url | 请求的地址 |
data | 待发送的key/value参数 |
callback | 载入成功时回调函数 |
type | 返回内容的格式 |
$.get()方法是基于$.ajax()方法上对操作进行简化,减少了前面的参数名以及type需要传的请求方式。 |
$.get("http://localhost:8080/WebTest/ajaxServlet",{action: "JQueryGet"},function (data) {
$("#msg").html("Get 编号:" + data.no + " , 姓名:" + data.name);
},"json");
$.post()方法
$post()方法和$get()方法同理
$.post("http://localhost:8080/WebTest/ajaxServlet","action=JQueryPost",function (data) {
$("#msg").html("Post 编号:" + data.no + " , 姓名:" + data.name);
},"json");
$.getJSON()方法
参数 | 描述 |
---|---|
url | 请求的url地址 |
data | 发送给服务器的数据 |
callback | 成功的回调函数 |
$.getJSON()方法使用get请求返回JSON类型的内容格式,也是属于简化操作。 | |
因此也是只需要三个参数。 |
$.getJSON("http://localhost:8080/WebTest/ajaxServlet","action=JQueryGetJson",function (data) {
$("#msg").html("GetJson 编号:" + data.no + ",姓名:" + data.name);
});
serialize()表单序列化方法
serialize()方法可以把表单中所有表单项的内容全部都获取到,并以 name=value&name=value 的形式进行拼接。
$("#submit").click(function () {
alert( $("#form01").serialize() );
$.getJSON("http://localhost:8080/WebTest/ajaxServlet","action=JQuerySerialize&"+$("#form01").serialize(),function (data) {
$("#msg").html("serialize 编号:" + data.no + ",姓名:" + data.name);
})
})
3、I18N
i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称。但其实现在较为广泛使用的还是应该像苹果公司一样为每个国家创建一个相应的网站。
以下是i18n中的一些常用方法的使用。
import org.junit.Test;
import java.util.Locale;
import java.util.ResourceBundle;
public class i18nTest {
@Test
public void localeTest(){
// 获取当前默认时区使用的语言
Locale locale = Locale.getDefault();
System.out.println(locale); // ZH_CN
// 遍历所有的其他国家语言信息
// for (Locale availableLocale:Locale.getAvailableLocales()){
// System.out.println(availableLocale);
// }
// 获取中文中国常量的Locale对象
System.out.println(Locale.CHINA);
// 获取英文美国常量的Locale对象
System.out.println(Locale.US);
}
@Test
public void i18nTest(){
// 得到我们需要用到的Locale对象
Locale locale = Locale.CHINA;
// 通过指定的basename和Locale对象读取相应的配置文件
ResourceBundle bundle = ResourceBundle.getBundle("i18n", locale);
System.out.println("username:" + bundle.getString("username"));
System.out.println("password:" + bundle.getString("password"));
System.out.println("Sex:" + bundle.getString("sex"));
System.out.println("age:" + bundle.getString("age"));
}
}
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// 从请求头中获取Locale信息(语言)
Locale locale = null;
String country = request.getParameter("country");
if ("cn".equals(country)) {
locale = Locale.CHINA;
} else if ("usa".equals(country)) {
locale = Locale.US;
} else {
locale = request.getLocale();
}
System.out.println(locale);
// 获取读取包(根据 指定的baseName和Locale读取 语言信息)
ResourceBundle i18n = ResourceBundle.getBundle("i18n", locale);
%>
<a href="i18n.jsp?country=cn">中文</a>|
<a href="i18n.jsp?country=usa">english</a>
<center>
<h1><%=i18n.getString("regist")%></h1>
<table>
<form>
<tr>
<td><%=i18n.getString("username")%></td>
<td><input name="username" type="text" /></td>
</tr>
<tr>
<td><%=i18n.getString("password")%></td>
<td><input type="password" /></td>
</tr>
<tr>
<td><%=i18n.getString("sex")%></td>
<td>
<input type="radio" /><%=i18n.getString("boy")%>
<input type="radio" /><%=i18n.getString("girl")%>
</td>
</tr>
<tr>
<td><%=i18n.getString("email")%></td>
<td><input type="text" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="reset" value="<%=i18n.getString("reset")%>" />
<input type="submit" value="<%=i18n.getString("submit")%>" /></td>
</tr>
</form>
</table>
<br /> <br /> <br /> <br />
</center>
国际化测试:
<br /> 1、访问页面,通过浏览器设置,请求头信息确定国际化语言。
<br /> 2、通过左上角,手动切换语言
</body>
</html>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%--1 使用标签设置Locale信息--%>
<fmt:setLocale value="${param.locale}" />
<%--2 使用标签设置baseName--%>
<fmt:setBundle basename="i18n"/>
<a href="i18n_fmt.jsp?locale=zh_CN">中文</a>|
<a href="i18n_fmt.jsp?locale=en_US">english</a>
<center>
<h1><fmt:message key="regist" /></h1>
<table>
<form>
<tr>
<td><fmt:message key="username" /></td>
<td><input name="username" type="text" /></td>
</tr>
<tr>
<td><fmt:message key="password" /></td>
<td><input type="password" /></td>
</tr>
<tr>
<td><fmt:message key="sex" /></td>
<td>
<input type="radio" /><fmt:message key="boy" />
<input type="radio" /><fmt:message key="girl" />
</td>
</tr>
<tr>
<td><fmt:message key="email" /></td>
<td><input type="text" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="reset" value="<fmt:message key="reset" />" />
<input type="submit" value="<fmt:message key="submit" />" /></td>
</tr>
</form>
</table>
<br /> <br /> <br /> <br />
</center>
</body>
</html>