概念
servlet(server applet)是Java Servlet的简称,使用java代码编写的服务器端的小程序,用来交互式的浏览和修改数据,生成动态Web内容。
生命周期
servlet执行流程如图
servlet的生命周期
加载和实例化,当用户第一次请求Servlet时,Servlet容器将会创建Servlet实例
初始化,Servlet容器加载完成servlet后必须进行初始化,此时init()方法被执行
服务,初始化之后,servlet处于处理请求的就绪状态,此时客户端若发送请求,缺省的service()方法会根据请求的方式调用doGet()或者doPost()方法执行处理逻辑
销毁,Servlet只会初始化一次(只调用一次init方法,只有一个对象),当Server不再需要Servlet时(Server关闭时),Servlet容器负责将Servlet销毁,调用Servlet的destroy()方法
gc回收垃圾释放资源
servlet中核心方法
Servlet提供了两个基本软件包:javax.servlet和javax.servlet.http
javax.servlet.http包中的类和接口继承自javax.servlet的类和接口,并添加了协议相关的方法,从而为基于HTTP协议的servlet开发提供了方便
javax.servlet.http包中的HttpServlet类继承自javax.servlet包中的GenericServlet类,我们日常的servlet开发一般都继承自HttpServlet类
HttpServlet
其中的service()方法是整个Servlet的核心
当用户请求时,HttpServlet将会调用service()方法,并且传递给这个方法一个请求参数HttpServletRequest和HttpServletResponse
缺省的service()方法,将调用HttpServlet中相应的doGet()、doPost()方法
get和post请求的区别
一般理解
Get请求会把请求信息放在URL中;Post请求会将信息放在请求体中
Get请求提交的数据会收到URL长度的限制;Post请求理论上是不受限制(HTTP协议并未限制Post请求的大小,但是会收到服务器处理能力的限制),可以处理大量的数据。
Get请求由于URL地址数据可见,安全性差一些。
从HTTP协议规范区分
根据HTTP协议RESTFul规范,Get请求用来查询、获取信息而Post请求用来添加信息
由于Get只是获取信息,因此是安全和幂等的;而Post请求则会使服务器上的资源发生改变
servlet的会话跟踪技术
cookie
概念
Cookie是浏览器客户端技术,程序将用户数据以cookie的形式存放于客户端,当用户再次访问web浏览器时,就会携带这些数据进行访问
java提供的API
Cookie的构造方法 Cookie(String name,String value)
获取cookie的名字 String getName(String name)
获取cookie的值 String getValue()
设置cookie的值 void setValue(String value)
设置cookie的有效期(参数单位是秒) void setMaxAge(int expiry)
获取cookie的有效期 int getMaxAge()
设置cookie的有效路径 void setPath(String url)
获取cookie的有效路径 String getPath()
设置cookie的有效域 void setDomain(String pattern)
获取cookie的有效域 String getDomain()
java操作Cookie需要注意的地方
关于有效期
如果服务器端没有设置cookie的有效期,那么cookie存活时间为一次会话(cookie此时是放在浏览器缓存的),即一旦用户关闭浏览器那么cookie消失;如果服务器端设置了有效期,那么cookie的存活时间即为设置的时长(cookie此时是存放于用户磁盘的)。
删除cookie:将cookie的有效期设置为0,就会立即删除cookie。
关于有效路径
子路径是可以读取父路径上的cookie的,父路径不可读取子路径上的cookie。
如果将cookie的路径设置为(“/test”),那么浏览器访问test目录下的资源就会携带cookie;如果将路径设置为(“/test/abc”),那么浏览器访问abc目录下的资源携带cookie,在访问test下的资源时将不会携带cookie。
cookie代码示例
session
概念
Session是服务器端的技术,浏览器向服务器发送请求时,服务器会为每个用户创建一个独有的session对象,用户数据会被放在此session对象中,因此当用户再次请求时,服务器就可以从session中提取资源为用户服务
session实现原理
浏览器发送请求,服务器为浏览器单独开辟内存空间,创建session对象
该session对象持有唯一的一个sessionID,服务器将此sessionID以cookie的形式发送给浏览器
浏览器再次访问服务器,将会携带此sessionID,服务器根据sessionID找到session对象,提取数据
java中操作session
获取session
HttpSession session = request.getSession();
设置属性
session.setAttribute(String key,Object value);
获取属性
session.getAttribute(String key);
删除属性
session.removeAttribute(String key);
销毁session
session.invalidate();
session操作需要注意的地方
getSession()方法是有参数的,参数为布尔类型的变量。
当参数为true时,如果之前存在session对象则返回该session对象;如果不存在则创建一个session对象并返回
当参数为false时,如果之前存在session对象则返回该session对象;不存在则返回null
缺省值默认为true
cookie和session区别
cookie是存放于浏览器端的,数据并不安全;session存放于服务器端,数据相对安全
cookie保存的数据类型只能是字符串;session可以保存多种数据类型数据
cookie保存数据大小有限制,每个cookie的大小为4kb;session由于占用的是服务器内存,存储量要大很多
servlet如何处理多个请求
Servlet采用多线程来处理多个请求的同时访问。Servlet容器通过线程池来管理维护服务请求。
当容器收到一个Servlet的访问请求,调度者线程就从线程池中选出一个工作者线程,将用户请求传递给该线程,然后由该线程处理Servlet的service()方法
当这个线程在执行的时候,容器收到一个新的请求,调度者线程再次从线程池中选出一个新的工作者线程
当容器同时收到对同一个Servlet的多个请求时,那么Servlet的service方法将在多线程中并发执行
如何开发线程安全的servlet
变量的线程安全; 多线程并不共享局部变量,所以我们要尽可能的在Servlet中使用局部变量
代码块的线程安全; 使用同步块Synchronized,防止可能调用的代码块;但是要注意的是,要尽可能得缩小同步代码的方范围,不要在service方法和响应方法上直接使用同步,这会严重影响性能
属性的线程安全; ServletContext,HttpSession,ServletRequest对象中属性
使用同步集合; 使用Vector代替ArrayList,使用HashTable代替HashMap
不要在Servlet中创建自己的线程来完成某个功能; Servlet本身就是多线程的,如果再创建新的线程,将会导致线程执行复杂化,出现线程安全问题
在多个Servlet中,对外部对象,比如:文件;进行修改操作一定要加锁,做到互斥访问
测试代码
获取请求头测试代码:
package star.july;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 获取Http协议的请求行,请求头
*
*/
public class RequestDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("请求行的方法:" + request.getMethod());
System.out.println("请求行的URI:" + request.getRequestURI());
System.out.println("请求行的URL:" + request.getRequestURL());
System.out.println("请求行的版本:" + request.getProtocol());
System.out.println("请求头:"+request.getHeader("User-Agent"));
//利用迭代器遍历所有的请求头
Enumeration names = request.getHeaderNames();
while(names.hasMoreElements()){
//获取请求头
String nextElement = (String)names.nextElement();
//获取每个请求头的内容
String header = request.getHeader(nextElement);
System.out.print(nextElement+" : ");
System.out.println(header);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
cookie测试代码
添加cookie
@WebServlet("/ac.do")
public class TestCreateCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");//设置输出编码
response.setContentType("text/html;charset=UTF-8");//设置浏览器接收的编码格式
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
if(cookies != null){
out.write("您最后访问本站时间是:");
for(Cookie cookie:cookies){
if(cookie.getName().equals("lastAccessTime")){
Date date = new Date(Long.parseLong(cookie.getValue()));
out.write(date.toLocaleString());
}
}
}else{
out.write("您是首次登录网站!");
}
Cookie cookie = new Cookie("lastAccessTime",""+System.currentTimeMillis() );
// cookie.setMaxAge(24*60*60);
// Cookie c2 = new Cookie("username", URLEncoder.encode("花花","utf-8"));
response.addCookie(cookie);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
删除cookie
@WebServlet("/dc.do")
public class TestDeleteCookieServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie:cookies){
if(cookie.getName().equals("lastAccessTime")){
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
}
response.getWriter().append("Cookie 已经删除了!");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
session测试代码
@WebServlet("/TestSessionServlet")
public class TestSessionServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");//输出编码
response.setContentType("text/html;charset=UTF-8");//浏览器端接收格式及编码
HttpSession session = request.getSession();//获取session对象
String id= session.getId();//获取sessionID
session.setAttribute("username", "花花");
//判断session是否为新建
if(session.isNew()){
response.getWriter().println("创建成功,session的id为:"+id);
}else{
response.getWriter().println("session已存在了,id为"+id);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}