JavaEE Servlet 学习笔记
一、Servlet概述
1、什么是Servlet
Servlet是一个运行在服务器端的Java小程序,通过HTTP协议用于接收来自客户端请求,并发出响应。
2、Servlet中的方法
public void service(ServletRequest req,ServletResponse res)
throws ServletException,java.io.IOException
ServletRequest req:代表着请求对象,该对象中有HTTP协议的请求部分的所有内容。它的实现类由服务器提供的,封装数据也是服务器来做的。
ServletResponse res:代表着响应对象,该对象中由我们写数据(HTTP协议的响应部分)进去。它的实现类也是由服务器提供的。
service:由服务器调用,每次请求都会调用一次。服务器采用的是多线程机制。
二、Servlet的编码步骤
1、编写一个类实现javax.servlet.Servlet接口,或者继承javax.servlet.GenericServlet。
2、编译Servlet的源码
3、映射Servlet
修改web.xml
4、把应用部署Tomcat中,访问地址:http://localhost:8080/firstServlet/hello
明确:规范 服务器 应用间的关系
三、Servlet的执行过程
实例 class代码
package com.it.Serlvet; import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class SerlvetDemo1 extends GenericServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { // TODO Auto-generated method stub res.getWriter().write("this is yif's page "); } }
web 定义及映射
<servlet>
<!--定义Servlet:给Servlet类取一个名字-->
<servlet-name>SerlvetDemo1</servlet-name>
<servlet-class>com.it.Serlvet.SerlvetDemo1</servlet-class>
</servlet>
<servlet-mapping>
<!--映射Servlet:给Servlet一个访问地址-->
<servlet-name>SerlvetDemo1</servlet-name>
<url-pattern>/SerlvetDemo1</url-pattern>
</servlet-mapping>
四、Servlet的编写方式:
1、javax.servlet.GenericServlet:通用的Servlet实现,抽象类
(经常用)2、javax.servlet.http.HttpServlet:与HTTP协议有关的,抽象类
继承HttpServlet,然后覆盖掉doGet或doPost方法即可,不要覆盖掉service方法。
*Servlet规范中的核心接口类图
五、Servlet的生命周期
1、生命周期(必须清晰):诞生--活着--死亡。人有这个过程,内存中的对象也有。
2、Servlet对象的生命周期
l 诞生:用户第一次访问时,由容器创建他的实例。
l 活着:一旦创建就驻留内存(单例)。每次用户的访问,容器都会调用sevice方法发出响应(多线程)
l 死亡:应用被卸载或者Tomcat关闭了
实例:
public class ServletDemo3 extends HttpServlet { //用户第一次访问时,只执行一次 public ServletDemo3(){ System.out.println("调用了Servlet的默认构造方法"); } //用户第一次访问时,执行一次。用于对象的初始化 public void init() throws ServletException { System.out.println("调用了Servlet的初始化方法"); } //每次用户访问都执行 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("执行了Service方法"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } //调用一次。用于清理工作 public void destroy() { System.out.println("调用了Servlet的销毁方法"); } }
六、Servlet的线程安全
七、Servlet的一些细节
1、一个Servlet可以被映射到多个地址上
2、可以使用地址通配符*
写法一:*.do结尾 。必须以*开头 比如*.do
写法二(比一优先级略高):以/开头,必须以*结尾 比如/action/*
3、默认的Servlet
默认的Servlet的映射路径是<url-pattern>/</url-pattern>。不需要大家配,因为默认的Servlet负责处理用户的请求URL找不到匹配的处理工作。
一切都是Servlet。访问 1.html
4、应用在启动时就完成Servlet的实例化和初始化
八、ServletConfig:Servlet的参数配置
1、ServletConfig:代表着针对当前Servlet的参数配置
2、如何得到ServletConfig对象的引用:在初始化Servlet时,由容器产生,并传递给你
代码:
public class ServletDemo5 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用config了 ServletConfig config = getServletConfig(); test2(config); } //得到当前Servlet所有的配置参数 private void test2(ServletConfig config) { Enumeration e = config.getInitParameterNames();//参数的名字 while(e.hasMoreElements()){ String paramName = (String)e.nextElement(); System.out.println(paramName+"="+config.getInitParameter(paramName)); } } //得到指定名称的参数的值 private void test1(ServletConfig config) { //得到指定名称的参数值 String value = config.getInitParameter("encoding"); System.out.println(value); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }
九、ServletContext
1、ServletContext代表着当前应用。每个应用只有一个ServletContext对象的实例,由容器提供。
2、如何获取ServletContext的实例:
ServletConfig.getServletContext();
3、ServletContext的生命周期
诞生:应用被加载时就由容器创建好
活着:应用不挂就一直活着
死亡:应用挂了,就挂了
4、域(存活范围)对象:
ServletContext称为应用范围域对象。
可以通过ServletContext 传递 参数
public class ServletContextDemo1 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ServletConfig config = getServletConfig(); // ServletContext sc = config.getServletContext(); ServletContext sc = getServletContext(); sc.setAttribute("p", "ppp"); response.getWriter().write("put done"); }
public class ServletContextDemo2 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext sc = getServletContext(); String str = (String)sc.getAttribute("p"); response.getWriter().write(str); }
ServletContextDemo1 设置参数 ,ServletContextDemo2取出 共享的 ServletContext 实现数据共享
5、配置应用级的参数web.xml
用ServletContext来取
//获取应用级的参数 public class ServletContextDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext sc = getServletContext(); //得一个参数 // String value = sc.getInitParameter("encoding"); // System.out.println(value); //得所有的参数 Enumeration<String> names = sc.getInitParameterNames(); while(names.hasMoreElements()){ String paramName = names.nextElement(); System.out.println(paramName+"="+sc.getInitParameter(paramName)); } }
附:
实现 请求转发
//转发:源 public class ServletContextDemo4 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext sc = getServletContext(); RequestDispatcher rd = sc.getRequestDispatcher("/servlet/ServletContextDemo5");//转发的地址。ServletContext得到的,地址必须以"/"开头,该"/"就代表着当前应用的访问路径/day07_01_servlet rd.forward(request, response);//转发 }
//转发:目标 public class ServletContextDemo5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write("I am five"); }
实现中文文件的下载
//实现中文文件的下载 public class ServletContextDemo6 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //文件在哪儿?以不变应万变 ServletContext sc = getServletContext(); String realPath = sc.getRealPath("/WEB-INF/classes/霉女.jpg");// 文件存放的真实绝对路径 // System.out.println(realPath); //构建文件的输入流 InputStream in = new FileInputStream(realPath); //告知客户端以下载的方式打开:Content-Disposition=attachment;filename=27.jpg //获取要下载的文件名 String filename = realPath.substring(realPath.lastIndexOf(File.separator)+1); response.setHeader("Content-Type", "application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));//中文属于不安全的字符,需要进行URL编码 //用response的字节流进行输出 OutputStream out = response.getOutputStream(); int len = -1; byte b[] = new byte[1024]; while((len=in.read(b))!=-1){ out.write(b, 0, len); } in.close(); out.close(); }
encode 编码
实例: 使用utf-8编码
import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import org.junit.Test; public class UrlEncodeDemo { @Test public void test1() throws UnsupportedEncodingException{ String s = "胡轩"; System.out.println(URLEncoder.encode(s, "UTF-8")); } @Test public void test2() throws UnsupportedEncodingException{ String s = "%E8%83%A1%E8%BD%A9"; String v = URLDecoder.decode(s, "UTF-8"); System.out.println(v); } }
读取配置文件的各种方式
//演示:读取配置文件的各种方式 public class ServletContextDemo7 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { test31(request, response); } //请不要把Tomcat等服务器装在有空格的目录中 //类加载器读取:只能读取classes或者类路径中的任意资源。但是不适合读取特别大的资源。b c private void test31(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ClassLoader cl = ServletContextDemo7.class.getClassLoader();//得到类加载器 URL url = cl.getResource("com/itheima/resources/c.properties"); String path = url.getPath(); InputStream in = new FileInputStream(path); Properties props = new Properties(); props.load(in); System.out.println(props.getProperty("hello")); } //类加载器读取:只能读取classes或者类路径中的任意资源。但是不适合读取特别大的资源。b c private void test30(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ClassLoader cl = ServletContextDemo7.class.getClassLoader();//得到类加载器 // InputStream in = cl.getResourceAsStream("b.properties"); InputStream in = cl.getResourceAsStream("com/itheima/resources/c.properties"); Properties props = new Properties(); props.load(in); System.out.println(props.getProperty("hello")); } //利用ResourceBundle读取:b c ,不能读a,只能读取properties的文件 private void test20(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // ResourceBundle rb = ResourceBundle.getBundle("b"); ResourceBundle rb = ResourceBundle.getBundle("com.itheima.resources.c"); System.out.println(rb.getString("hello")); } //利用ServletContext读取:a b c //可以读取应用中任何位置上的资源。使用限制:只能在web应用中用 private void test10(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // String path = getServletContext().getRealPath("/a.properties"); // String path = getServletContext().getRealPath("/WEB-INF/classes/b.properties"); String path = getServletContext().getRealPath("/WEB-INF/classes/com/itheima/resources/c.properties"); InputStream in = new FileInputStream(path); Properties props = new Properties(); props.load(in); System.out.println(props.getProperty("hello")); }