Java Servlet(Server Applet) 是运行在Web服务器或者应用服务器上的程序,它作为来自浏览器或者其他http客户端的请求和http服务器上的数据库或者应用程序的中间层。主要功能是用于交互式地浏览数据和修改数据,生成动态Web内容。
1、客户端发送请求至服务器
2、服务器启动并调用Servlet,再根据客户端请求生成响应内容并将其传回给服务器。
3、服务器响应客户端
Servlet API 包含以下4个Java包:
1.javax.servlet 其中包含定义servlet和servlet容器之间约定的类和接口。
2.javax.servlet.http 其中包含定义HTTP Servlet 和Servlet容器之间的关系。
3.javax.servlet.annotation 其中包含标注servlet,Filter,Listener的标注。它还为被标注元件定义元数据。
4.javax.servlet.descriptor,其中包含提供程序化登录Web应用程序的配置信息的类型。
public interface Servlet {
void init(ServletConfig var1) throws ServletException;
ServletConfig getServletConfig();
void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
String getServletInfo();
void destroy();
}
在servlet第一次请求时,Servlet会调用当前方法来初始化一个Servlet对象出来,但是每一个Servlet只会调用一次来完成初始化工作。Servlet容器会在其调用此方法时传入一个ServletConfIg对象对其初始化。
它是一个需要用户手动添加的HttpServlet接口未实现方法,但是只有当请求Servlet时,Servlet容器才会调用这个方法。所以它的周期是它处理Servlet请求的这一段时间。
当Servlet被销毁时,Servlet会自动调用这个方法来执行收尾的工作。
从第一次调用,到服务器关闭。如果在web.xml 中配置了load-on-startup则是从服务器开启到服务器关闭。
不管是之后提到的doGet方法还是doPost方法的请求,如果Servlet类中有service方法则优先调用Service方法。只有在没有的情况下才会按请求类型调用相应的方法。而在声明父类的情况下service才会调用doGet或者doPost方法,否则只调用service而不执行另外两个方法。
在没有service方法的情况下如果是get方式的请求所调用的处理请求的方法 。
在没有service方法的情况下如果是post方式的请求所调用的处理请求的方法
浏览器在对服务器发起请求时,会遵循http协议的请求发送数据给服务器。而服务器在接收到这个请求时同时把浏览器端发送的数据存储到request对象中供服务器调用。
一次请求之内。
request.getMethod();//获取请求方式
request.getRequestURL();//获取请求URL信息
request.getRequestURI();//获取请求URI信息
request.getScheme();//获取协议
request.getHeader("键名");//返回指定的请求头信息
request.getHeaderNames();//返回请求头的键名的枚举集合
//返回指定的用户数据
request.getParameter("键名");
//返回同键不同值的请求数据(多选),返回的数组。
request.getParameterValues("键名");
//返回所有用户请求数据的枚举集合
request.getParameterNames()
用于不同servlet对同一请求的数据传输问题
request.setAttribute(objectname,Objectvalue);
request.getAttribute(Objectobj);
如果获取的请求不存在时,服务器并不会报错,但是会返回null。
request对象由服务器直接创建,并作为实参传递给处理请求的servlet的service方法。
用来响应来自浏览器端的请求。
setHeader(String name,String value);//在响应头中添加响应信息,但是同键会覆盖
addHeader(String name,String value);//在响应头中添加响应信息,但是不会覆盖。
endError(int num,String msg);//自定义响应状态码。
resp.getWrite().write(String str);//响应具体的数据给浏览器
resp.setContentType("text/html;charset=utf-8");
HttpServletResponse.sendRedirect(url);
request.getRequestDispatcher(URL).forward(request,response);
重定向是网页跳转的方式之一,它是通过返回一个新的网页地址给浏览器实现的页面跳转。它的优点在于能够通过绝对URL调取除了本WEB项目外的其他资源。书写时以"/"开头表示项目根目录。
请求转发是网页跳转的另外一种方式,由服务器端发起的请求转发动作,能够存储request的数据。
需要注意的是sendRedire重定向之后它的request和response对象不再与原先的重定向前的servlet有关系。同时它相当于浏览器发起了两次请求,所以HttpServletRequest.setAttribute()方法将无法传递所需要的键值。同时它的地址栏也会发生转变,行为上重定向是由客户端的行为,而转发是服务器端的行为。重定向还会丢失request范围以下的数据。
百度百科:
Cookie,有时也用其复数形式 Cookies。类型为“小型文本文件”,是某些网站为了辨别用户身份,进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),由用户客户端计算机暂时或永久保存的信息。
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。
Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。
javaEE:
cookie是客户端(浏览器)的使用,它的数据类型会被写入到浏览器的响应头中,可以通过特定的类进行键值对的调用。同时由于是浏览器端的数据存储技术,所以它能在一次请求结束之后保存数据。故也能用来实现三天面登录的功能。
具体实现:
//创建Cookie对象
Cookie c = new Cookie(String name,String value);
//设置cookie对象
//设置生命周期,seconds为秒单位
c.setMaxAge(int seconds);
//设置有效路径,这样可以限定cookie在特定响应头中出现(有效路径)。
c.setPath(String uri);
//获取cookie信息
Cookie[] cks=req.getCookies();//获得此请求响应头的所有cookie信息。
//此处的c为cookie对象的实例
String name=c.getName();//获取cookie中的键名
String value=c.getValue();//获取cookie中的键值
session
服务器会为第一次访问服务器的用户提供一个session对象,并会将ID以JSESSIONID为名的键值对的格式储存到浏览器中,保证用户的不同请求能取到同一个用户的数据。实现不同请求的数据共享问题。
代码实现:
//获取Session对象
HttpSession hs = request.getSession();
//设置存储时间(单位秒)
hs.setMaxInactiveInterval(int m);
//设置强制失效
hs.invalidate();
//存储数据
hs.setAttribute(String name,Object value);
cookie的生命周期:
创建:cookie的创建开始
销毁:会话cookie会在浏览器关闭时销毁,设置过cookieMaxAge的则会在过期后销毁
session的生命周期:
创建:request.getSession()创建Session
销毁:1、服务器关闭。2、session过期时销毁。3、手动调用session.invalidate进行销毁。
默认是30分钟(这里指的是自上一次操作结束后的时间,如果30分钟内用户再进行一次操作则重新计时)。
jsp是由Sun Microsystems 公司倡导的一种动态网页技术标准。本质上还是Servlet。
浏览器发起请求,请求jsp后该请求被Tomcat服务器接收,执行jspServlet将jsp文件转义成响应的java文件(Servlet)。
前端注释 :
会被转译,也会被发送,但是浏览器不会执行
java注释(直接在里面加双斜杠即可)
会被转译,但是不会被Servlet执行
<%
//
%>
jsp注释
不会被转译。
<%-- 注释内容–%>
<%@page 属性名="属性值" 属性名="属性值" ...%>
部分属性介绍
属性名 | 定义 | 格式 |
---|---|---|
language | 指定相关语言来编译,目前只支持java | <%@ page language=“java” %> |
import | 声明转义的java文件要导入的java包 | <%@page import=“java.util.*” %> |
pageEncoding | 配置jsp的数据编码格式 | <%@page pageEncoding=“utf-8”%> |
contentType | 设置响应给浏览器端的解析和编码格式 | <%@page contentType = "text/html;charset=“utf-8”%> |
session | 设置转译的Servlet中是否开启Session支持,默认开启 | <%@page session = “true”%> |
errorPage | 设置jsp运行错误跳转界面 | <%@page errorPage=“路径”%> |
extend | 设置jsp转译的java文件要继承的父类(包名+类名) | <%@page extend=""%> |
作用:配置jsp相关转译的参数。
特点:局部代码块中声明书写的代码会被原样给到Servlet文件的service方法中。代码中的变量为局部变量。
使用方式:<% java代码%>
缺点:使用不方便,对于书写逻辑判断时会出现明显的阅读困难。
特点:该处声明的变量会被转译成对应Servlet类中的全局变量。
使用方式:<%! java全局代码%>
作用:在网页中显示合拼后的效果,效果相当于当前的jsp文件代码中接入另一个jsp文件的代码。
静态引入
<%@include file=“要引入的jsp文件的相对路径”%>
特点:
注意:
动态引入
< jsp:include page=“要引入文件的相对路径”>< /jsp:include>
特点:
注意:动态引入中允许文件中声明相同的变量名称。
使用:
< jsp:forward page = “转发的路径”>
< jsp:param name=“str” value=“aaa” />
< /jsp:forward>
特点:
注意:
内置对象:
jsp文件在转译成相应的Servlet文件时会自动生成并声明的对象。我们则能直接在jsp页面中直接使用。
注意:
内置对象在jsp页面中使用,使用局部代码块或者脚本语句中使用。不能在全局变量中使用。
使用:在<%%>内使用的对象
对象名称 | 介绍 |
---|---|
pageContext | 页面上下文对象,封存了其他的内置对象。还封存了当前jsp的运行信息。每个jsp都存在自己的pageContext对象,并只作用于当前页面。 |
request | 封存当前请求数据的对象。由服务器创建。一次请求。 |
session | 此对象用来存储用户不同请求的共享数据的。一次会话。 |
application | ServletContext对象,一个项目只有一个。存储用户共享数据对象,以及其他完成的操作。 |
response | 响应对象,用来响应请求处理结果给浏览器对象。如设置响应头和重定向。 |
out | 响应对象,jsp内部使用。带有缓冲区的响应对象,效率高于response。 |
page | 代表当前jsp的对象。相当于this。 |
exception | 异常对象。存储了当前运行的异常信息。但是要将page中的isErrorPage属性设置为true。 |
config | 相当于ServletConfig,主要获取web.xml中的配置数据完成一些初始化操作。 |
对象名称 | 对象介绍 |
---|---|
pageContext | 当前页面,解决了当前页面的数据共享问题。获取其他内置对象。 |
request | 一次请求。一次请求的Servlet的数据共享问题。可以通过请求转发可以将数据流给下一个Servlet。 |
session | 一次会话。对于一个用户的不同请求的数据共享问题。即使用重定向时相当于一次新请求,此时的数据流转可以有session完成。 |
application | 项目内不同用户的数据共享问题,可以让不同的数据共享。 |
全称Asynchronous JavaScript and XML(异步JavaScript和XML)
是一种交互式网页应用的网页开发技术,不是一种新的知识而是多个知识点的结合。同时它也是浏览器端的技术。
基本原理
基本的图解意思:本来由网页端直接发送请求数据给服务器端再重新获取响应页面(这里的网页其实已经不再是原先的页面而是响应后的页面),而ajax实现的就是在原来页面的基础上同时出现响应后的界面。它通过JavaScript的函数功能实现。
基本流程
<script type="text/javascript">
function 函数名称(){
//创建ajax引擎对象
var ajax;
if(window.XMLHttpRequest){
ajax = new XMLHttpRequest();
}else if(window.ActiveXObject){
ajax = new ActiveXObject("Msxml2.XMLHTTP");
}
//覆写onreadystatechange
ajax.onreadystatechange = function(){
//判断状态码-->代码下有相关值的解释
if(ajax.readyState == 4){
//判断响应状态值
if(ajax.status==200){
//获取响应内容
//
var result=ajax.responseText;
}
}
}
ajax.open(Method,url,Asynchronous(默认true));
ajax.send();//用于post请求的数据储存
}
</script>
//get请求
get的请求实体拼接在URL后面,?隔开,键值对
ajax.open("get","url");
ajax.send(null);
//post请求
有单独的请求实体
ajax.open("post", "url");
ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
ajax.send("name=张三&pwd=123");
ajax的响应问题
var n =responseText–>普通字符串的请求格式
json格式:
responseText
var 对象名={
属性名:属性值
属性名:属性值
…
}
eval("var u = "n对象名)//转成对应的Object类型
XML格式:
responseXML 返回document对象
EL(Expression Language)一种写法非常简洁的表达式写法,它的出现让jsp语法更加简单易懂,便于使用。(与此语言有关ECMAScript 和XPath)
使用方式:
${表达式}
使用格式 | 说明 |
---|---|
${param.键名} | request对象存储的请求数据的返回值 |
${paramvalues.键名} | 返回了request对象的请求数据,返回数组 |
${键名} | 存储了由setAttribute方法作用域存储的对象中的数据。 |
${pageScope.键名} | 获取不同作用域的数据,此处的是获取pageContext的数据。 |
${requestScope.键名} | 获取request作用域的数据 |
${sessionScope.键名} | 获取session里面存储的数据 |
${applicationScope.键名} | 获取application里面的数据 |
${逻辑运算表达式:&&,!..} | 使用逻辑判断 |
${算术运算表达式:+,-,*,/} | 使用算术表达式 |
${关系表达式:<,>…} | 关系表达式 |
${a>b?c:d} | 支持三目运算 |
${empty 键名} | 判断是否为空值 |
${header} | 返回所有的请求头数据 |
${header[“键名”]} | 返回指定的键名的请求头数据 |
${hedaerValues[“键名”]} | 返回指定的键名(同键不同值)的值的数组 |
${cookie} | 返回存储了所有的cookie对象的map集合 |
${cookie.键名 | 返回指定的cookie对象 |
${cookie.键名.name} | 返回指定的cookie对象存储的数据的键名。 |
${cookie.键名.value} | 返回指定的cookie对象存储的数据的值。 |
JSTL标签库:它是apache对EL表达式的扩展包,放在lib文件夹下(需要导包)。
步骤
1、导入jar包
2、声明jstl标签库的引入(核心标签库)
<%@taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>//注意此处的“c”
基本标签
数据:可以为常量值也可以是EL表达式。
作用:将数据输出给客户端。
作用:存储数据到作用域对象中
var:表示存储的键名
value:表示存储的数据
scope:表示要存储的作用域对象 //page //request //session //application
作用:删除作用域中的指定键的数据。
var:表示要删除的键的名字。
scope:表示要删除的作用域(可选)//如果不选等于只要键名相同的四个作用域全删除。
逻辑标签
<c:if test="${表达式}">
// 前端代码
</c:if>
/*
作用:进行逻辑判断,相当于java代码的单分支判断。
注意:
逻辑判断标签需要依赖于EL的逻辑运算,也就是表达式中涉及到的数据必须从作用域中获取。
*/
<c:choose>
<c:when test="">执行内容</c:when>
<c:when test="">执行内容</c:when>
...
<c:otherwise>执行内容</c:otherwise>
</c:choose>
/*
作用:
用来进行多条件的逻辑判断,类似java中的多分支语句
注意:
条件成立只会执行一次,都不成立则执行otherwise
*/
//循环标签:
<c:forEach begin="1" end="4" step="2">
// 循环体
</c:forEach>
/*
作用:
循环内容进行处理
使用:
begin:声明循环开始位置
end:声明循环结束位置
step:设置步长(也就是每一次执行时跳的步数)
varStatus:声明变量记录每次循环的数据(角标,次数,是否是第一次循环,是否是最后一次循环)
注意:数据存储在作用域中,需要使用EL表达式获取。
例如:${vs.index}--${vs.count}--${vs.first}--${vs.last}
items:声明要遍历的对象。结合EL表达式获取对象
var:声明变量记录每次循环的结果。存储在作用域中,需要使用EL表达式获取。
*/
<!-- 使用JSTL方式完成循环 -->
<!--常量循环 -->
<c:forEach begin="0" end="4" step="1" varStatus="vs">
${vs.index}--${vs.count}--${vs.first}--${vs.last}<br />
</c:forEach>
<!--动态循环 -->
<c:forEach items="${list}" var="str">
${str}<br />
</c:forEach>
<!--创建表格数据 -->
<table border="1px">
<tr>
<td>课程名称</td>
<td>教师</td>
<td>价格</td>
<td>重要性</td>
</tr>
<c:forEach items="${list}" var="s">
<tr>
<td>${s}</td>
<td>${s}</td>
<td>${s}</td>
<td>${s}</td>
</tr>
</c:forEach>
</table>
<!--遍历map集合 -->
<c:forEach items="${map}" var="m">
${m.key}--${m.value} <br />
</c:forEach>
更多JSTL标签库可以参考菜鸟教程
过滤器:对浏览器请求Servlet时起到“滤网”作用,可以通过设置过滤器来保证浏览器在访问之前保证其安全性和编码格式等规定的统一。
步骤:
配置web.xml文件(如果是直接创建的Filter文件一般已经配置完毕)
<filter>
<filter-name>myFilter</filter-name>
<filter-class>包名+类名</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*
注意:
url-pattern:/*
表示拦截所有的请求。
url-pattern:*.do
表示所有以.do结尾的请求。一般是用来进行模块拦截处理。
url-pattern:/ts
表示拦截指定url的请求。针对某个servlet的请求进行拦截,保护servlet。
对应的java文件实现接口Filter并覆写相应的方法
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("MyFilter.init(我被初始化了)");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("MyFilter.doFilter(我被执行了)");
//设置编码格式
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
}
@Override
public void destroy() {
System.out.println("MyFilter.destroy(我被销毁了)");
}
监听器:用于对监听作用域对象request,session和application对象而建立
步骤:
配置web.xml文件
<listener>
<listener-class>包名+类名</listener-class>
</listener>
创建监听对象
//由于本类中一共实现了三个接口所以有点类似方法,可以先看后面的注释再结合代码理解
public class MyListener implements ServletRequestListener,ServletRequestAttributeListener,HttpSessionListener,HttpSessionAttributeListener,ServletContextListener,ServletContextAttributeListener{
//request对象销毁
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("我被销毁了");
}
//request对象创建
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("我被创建了");
}
//监听request作用域数据的添加
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("request中增加了一条数据-"+srae.getName()+":"+srae.getValue());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
// TODO Auto-generated method stub
}
/*------------------------------------------------------------------------------*/
//监听session的创建
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("session被创建了");
}
//监听session的销毁
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session被销毁了");
}
//监听session数据的表更
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("session中增加了一条数据"+event.getName()+":"+event.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
/*------------------------------------------------------------------------------*/
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("application对象被初始化了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("application对象被销毁了");
}
//监听application的数据变更
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("application中存储了数据:"+event.getName()+":"+event.getValue());
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
// TODO Auto-generated method stub
}
}
监听request--->ServletRequestListener 监听request对象的创建和销毁
requestInitialized(ServletRequestEvent sre)//创建
requestDestroyed(ServletRequestEvent sre)//销毁
注意:
形参可以获取监听的request对象
sre.getServletRequest();
监听request--->ServletRequestAttributeListener 监听request作用域数据的变更。
attributeAdded(ServletRequestAttributeEvent srae)
attributeRemoved(ServletRequestAttributeEvent srae)
attributeReplaced(ServletRequestAttributeEvent srae)
注意:形参可以获取被监听的数据
srae.getName() 获取监听数据的键
srae.getValue() 获取监听数据的值
监听session--->HttpSessionListener 监听session的创建和销毁
sessionCreated(HttpSessionEvent se) 创建
sessionDestroyed(HttpSessionEvent se) 销毁
注意:形参可以获取被监听的session对象
se.getSession();
监听session--->HttpSessionAttributeListener 监听session数据的变更
attributeAdded(HttpSessionBindingEvent event)
attributeRemoved(HttpSessionBindingEvent event)
attributeReplaced(HttpSessionBindingEvent event)
注意:形参可以获取被监听的数据
event.getName() 获取数据的键名
event.getValue() 获取数据的值
监听application--->ServletContextListener 监听application对象的初始化和销毁
contextInitialized(ServletContextEvent sce) 初始化 服务器启动
contextDestroyed(ServletContextEvent sce) 销毁 服务器关闭
注意:
形参可以获取当前application对象。
sce.getServletContext();
监听application--->ServletContextAttributeListener 监听数据的变更
attributeAdded(ServletContextAttributeEvent event)
attributeRemoved(ServletContextAttributeEvent event)
attributeReplaced(ServletContextAttributeEvent event)
注意:
形参可以获取当前监听的数据
event.getName() 获取数据的键名
event.getValue() 获取数据的值
本文章参考自学步园的page指令介绍
本文章参考自博主刘扬俊的总结,点击转入(更详细)