简介
servle是一个Sun公司提供的接口。servlet是一种实现了servlet接口的类,它是由Web容器负责创建并使用,用于接收和响应用户的请求。servlet中有五个抽象方法。
Servlet
public class DemoServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//负责servlet的初始化工作。启动服务器的时候会调用该方法,只调用一次。
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//请求一次调用一次。客户端请求时,容器会构造一个携带客户端请求信息的ServletRequest对象和一个用于响应客户端的的ServletResponse
//对象作为参数传递给Service()方法。
}
@Override
public String getServletInfo() {
return null; //返回一个字符串包含servlet的信息,如作者,版本和版权等信息。
}
@Override
public void destroy() {i
//负责释放servlet对象占用的资源,当servlet对象被销毁时,调用此方法,只调用一次
}
}
Servlet生命周期:上述五个方法中init()service()destroy()三个方法属于生命周期方法。
- 初始化阶段:客户端向servlet容器发出HTTP请求,要求访问servlet时容器会首先解析请求,检查内存中是否已经有该Servlet对象,如果有,直接调用。如果没有,通过init()方法实现Servlet的初始化工作,在整个生命周期内,他的init()方法只被调用一次。
- 运行阶段:每请求一次,调用一次service方法,其中生成请求和响应的封装对象:request和response。在整个生命周期会被调用多次
- 销毁阶段:当服务器关闭黑哦这WEB应用被移除容器时,在销毁之前,servlet容器会调用destroy()方法啊,释放Servlet对象所占用 的资源。在整个生命周期中,只会被调用一次。servlet对象一但被创建就会驻留在内存中等待客户端的访问,知道拂去其关闭或者web应用被移除容器时,servlet对象才会被销毁。
自动加载Servlet程序,有时候我们希望某些Servlet陈旭可以在Tomcat启动时随即启动。我们只需要配置web.xml文件中<load-on-startup>元素。其中的元素必须时一个整数。如果是负数,或者没有设定,Servlet将在客户端首次请求这个Servlet时加载它,如果式正整数或者0,则Servlet容器在Web应用启动时加载并初始化,值越小,越先被加载
GenericServlet
public class GenerServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
}
继承GenericServlet抽象类只需要重写service()方法
HttpServlet
大多数得Web引用都是通过HTTP和客户端进行交互的,所以在Servlet及口中提供了一个HttpServlet的抽象类,它是GenericServlet的子类,专门应用于HTTP的Servlet
public class chinaServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post方法有请求体,用来封装客户端提交的数据
System.out.println("我是doPost");//如果不定义post 默认是Get方法
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//get方法没有请求体,直接显示在地址栏中
System.out.println("我是doGet");
}
}
请求和响应
详解HttpServletRequest和HttpServletResponse对象
客户端向Servlet发出请求,Web服务器调用service()方法之前生成。
二者随着浏览器的提交请求而同时创建,随着响应的完毕同时消失。
1. HttpServletRequest
HTTP请求分为请求行,请求头,(请求空行),请求体。
1. 请求行:包含请求方法, 请求资源名,请求路径等信息。其相关方法描述如下:
@WebServlet("/WuYanZuServlet")
public class WuYanZuServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//防止输出有中文乱码
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
//获取请求消息中的请求方法(如Get·Post等)
writer.println("getMethod:"+request.getMethod()+"<br>");
//获取请求行中该资源名称部分,即位于URL主机和端口以后,参数之前的部分。
writer.println("getRequestURI:"+request.getRequestURI()+"<br>");
//获取请求行参数部分,即?以后的所有内容。
writer.println("getQueryString:"+request.getQueryString() +"<br>");
//获取请求行中协议名和版本信息,eg:HTTP 1.0
writer.println("getProtocol:"+request.getProtocol()+"<br>");
/*获取请求URL中属于Web应用程序的路径。路径以“/”开头,表示相对于
Web站点的根目录,路径结尾不含“/”,如果请求的URL属于Web站点的根目录,则返回
的果为空字符串("")
*/
writer.println("getContextPath:"+request.getContextPath()+"<br>");
writer.println("getPathInfo:"+request.getPathInfo()+"<br>");
writer.println("getPathTranslated:"+request.getPathTranslated()+"<br>");
writer.println("getServletPath:"+request.getServletPath()+"<br>");
}
}
2.请求头:向服务器传递附加信息,eg:客户端可以接受的数据类型,压缩方式,语言等。其相关方法描述如下:
3.请求体:用户提交的表单数据都是通过请求体发送给服务器的,为此在HttpServletRequest接口中,定义了两个于输入流相关的方法
-
getInputStream()
获取实体内容的ServletInputStream对象InputStream in = request.getInputStream();
-
getReader()
获取实体内容的BufferedReader对象,该对象将实体内容中给字节数据按照请求消息中指的字符编码转换为文本字符串。调用该方法时,使用 response.setContentType(“text/html;charset=utf-8”);指定字符编码,如果没有指定,则按照默认ISO8859-1为默认编码。@WebServlet("/demo03") public class RequestDemo01 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { BufferedReader reader = request.getReader(); String line =null; while ((line=reader.readLine())!=null){ System.out.println(line); } } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { }
4. 应用
-
getParameter(String name):获取指定参数名称的参数值,如果没有,则为null。如果有多个该指定参数名称的参数,只返回第一个出现的参数值
String username = request.getParameter("username"); String password = request.getParameter("password");
-
getParameterValues(String name):返回一个String[]数组。包含相同名称参数的所有参数值
-
getParameterNames():返回一个包含所有参数名的Enumeration对象,在此基础上可以对请求消息中的所有参数进行便利处理。
-
getParameterMap()将请求消息中所有的参数名和参数值装进一个Map对象中返回。
2. HttpServletResponse
HTTP响应分为:响应行,响应头,(响应空行),响应体。
1.响应行:
2.响应头:
3.响应体:在HTTP响应消息中,大量得数据都是通过响应消息体传递得,因此,ServletResponse以IO流的形式进行数据的传递。将数据发送到客户端浏览器。
-
getOutputStream():直接输出字节数组中的二进制数据。
-
getWriter():直接输出字符文本内容。
两个方法互斥,不能同时使用,否则会发生IllegalStateException。异常
// 字符输出流:PrintWriter getWriter()
//字节输出流:ServletOutputStream getOutputStream()
4.应用:
乱码问题
出现原因:由于计算机中的数据都是以二进制形式储存的,因此当传输文本时,就会发生字符和字节之间的转换,字符和字节之间的转换时透过查码表完成的,将字符转化成字节的过程成为编码,将字节转换成字符的过程称为解码。如果编码和解码使用的码表不一致就会出现乱码问题。默认是IOS-8859-1编码。解码为GBK。
1.request中乱码
-
Poast请求体乱码:如果提交的表单中有中文,浏览器默认时GBK编码,解码默认ISO-8859-1,因此就会出现中文乱码,所以用定义解码方式:
这种方式只对Post方法有效,Get方法不可以
request.setCharacterEncoding("utf-8");//设置请求体编码方式为utf-8 String name = request.getParameter();
-
Get方式提交表单解中文乱码问题:先用错误码表ISO-8859-1将用户名重新编码,然后再使用GBK解码(tomcat8以后的版本默认编码方式为utf-8,不用解决乱码问题)
name=new String(name.getBytes("iso8859-1"),"utf-8");
2.response中乱码
解决响应头中的乱码:多用于下载案例,下载文件名有中文。可用工具类解决。
解决响应体中的乱码:
- response.setContentType(“text/html;charset=utf-8”);//通知浏览器要和服务器同时使用utf-8编码,解码
- response.setHeader(“Content-Type”,“text/html;charset=utf-8”)_例1的底层
- response.setCharaterEncoding(“utf-8”);//设置响应消息的编码方式,“utf-8”必须和浏览器的解码方式一样,所以还的获取浏览器客户端的编码方式。
请求转发和重定向
转发
自己不想想处理了,让别人处理。跳转到另一个Servlet,但是地址栏显示还是原访问Servlet,是一次响应和请求,只能在本服务器转发。
request.getRequestDispatcher("/fail").forward(request,response);
//(/fail)是转发的另一个Servlet
重定向
客户端向AServlet发出请求,A响应客户端去BServlet,则客户端去向BServlet发出请求,B响应客户端。是两次请求二号响应,地址栏路径为BServlet路径。可以访问当前项目,或者其他项目
//1. 设置状态码为302
response.setStatus(302);
//2.设置响应头location
//response.setHeader("location","/day15/responseDemo2");
//相对于location和setHeader配合设置虚拟路径要简单的多
response.sendRedirect(“待访问路径”);