一、Servlet的生命周期 容器最终要调用service方法为客户进行服务 1、Servlet接口中的常用方法: public void init(ServletConfig config):初始化。Servlet类被实例化后就执行,且执行一次。由容器进行调用 public void destroy():销毁Servlet对象。由容器进行调用 2、Servlet实例对象和初始化方法,默认情况下,只有第一次访问时才执行,且只执行一次。在内存中一个Servlet只有一个实例。针对不同的用户请求,容器采用多线程的机制调用service方法的。 希望在应用被Tomcat加载完毕后(此时还没有任何人访问),就实例化并完成初始化Servlet的工作? <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> 3、如果设计与HTTP协议有关的Servlet,一般选择集成javax.servlet.http.HttpServlet. HttpServlet覆盖了其父类GenericServlet的public abstract void service(ServletRequest req, ServletResponse res)方法, 然后在覆盖的service方法中调用了自己的protected void service(HttpServletRequest req, HttpServletResponse resp)方法, 在自己的service方法中调用了自己的doXXX方法。 故自己写的Servlet不应该覆盖HttpServlet的service方法,而应该去覆盖掉它的doXXX方法。 4、Servlet实例化对象和初始化方法,默认情况下,只有第一次访问时才执行,且只执行一次。 二、Servlet的线程安全问题 在内存中一个Servlet只有一个实例。针对不同的用户请求,容器采用多线程的机制调用service方法的。 在Servlet中定义变量,除非特殊要求,尽量使用局部变量。 如果有需要实例变量时,应做同步处理,且同步代码块尽量包围少的代码。 三、Servlet的配置 Servlet的配置对象ServletConfig:(容器来创建) 作用:代表了Servlet配置中的参数信息。 比如在web.xml中的参数配置如下: <servlet> <servlet-name>ServletDemo2</servlet-name> <servlet-class>cn.jxn.servlet.ServletDemo2</servlet-class> <!-- aaa=bbb --> <init-param> <param-name>aaa</param-name> <param-value>bbb</param-value> </init-param> <init-param> <param-name>xxx</param-name> <param-value>yyy</param-value> </init-param> </servlet> Servlet配置 1、一个Servlet可以被映射到多个URL地址上 2、URL地址映射还支持通配符* 方式一:以*开头,以扩展名结尾。比如 <url-pattern>*.do</url-pattern> 方式二:以/前缀开头,以*结尾。 比如<url-pattern>/action/*</url-pattern> 3、多个Servlet使用通配符时,有可能有多 以"/"开头(方式二)要比"*"开头(方式一)优先级高 都以"/"开头,还是有多个匹配,找最匹配的 4、如果一个Servlet的映射为一个"/",就称之为默认的Servlet,它负责处理没有映射路径的URL请求的响应。 四、ServletContext 1、在应用被服务器加载时就创建ServletContext对象的实例。每一个JavaWeb应用都有唯一的一个ServletContext对象。它就代表着当前的应用。 2、如何得到ServletContext对象:ServletConfig.getServletContext(); 3、作用: 3.1ServletContext对象是一个域对象(域对象就是说其内部维护了一个Map<String,Object>) Object getAttribute(String name):根据名称获取绑定的对象 Enumeration getAttributeNames() :获取ServletContext域中所有的值对应的名称 void removeAttribute(String name):根据名称移除对象 void setAttribute(String name,Object value):添加或修改对象。 3.2实现多个Servlet之间的数据共享 3.3获取WEB应用的初始化参数(应用的全局参数) 在web.xml下配置以下信息: <context-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </context-param> 这些参数就属于整个应用的全局参数,使用ServletContext来读取。 3.4读取资源文件的三种方式: 利用ServletContext.getRealPath(): 特点:读取应用中任何文件。只能在Web环境下用 利用ResourceBundle读取配置文件 特点:可以用在非web环境下。但是只能读取类路径中的properties文件 利用类加载器读取配置文件(专业) 特点:可以用在非web环境下。可以读取类路径下的任何文件。 五、HttpServletResponse详解 5.1输出中文数据: 字节流: 注:String.getBytes()方法:使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 String.getBytes("UTF-8")方法:使用UTF-8将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 ServletOutputStream out = response.getOutputStream(); out.write("中文".getBytes());无乱码 无乱码的原因:平台默认的字符集和浏览器默认的字符集一样(在中国一般为GBK) ServletOutputStream out = response.getOutputStream(); out.write("中文".getBytes("UTF-8"));有乱码 解决办法: 通知浏览器,使用的码表 方式一:response.setHeader("Content-Type", "text/html;charset=UTF-8"); 方式二:response.getOutputStream().write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes("UTF-8")); *方式三:response.setContentType("text/html;charset=UTF-8");//方式一、二、三都是一样的 字符流: 注:Servlet中的字符流默认查ISO-8859-1(SUN的Servlet规范要求的) PrintWriter out = response.getWriter(); out.write(s);//字符输出流out默认查的是ISO-8859-1码表,即默认以ISO-8859-1编码的形式输出到浏览器 解决办法: 方式一: 第一步:更改默认的编码: response.setCharacterEncoding("UTF-8"); 第二步:通知浏览器的编码: response.setHeader("Content-Type", "text/html;charset=UTF-8"); 方式二: response.setContentType("text/html;charset=UTF-8"); 在字符流输出中文数据时:response.setContentType("text/html;charset=UTF-8");有两个作用: (1)通知字符流以UTF-8编码输出 (2)通知客户端以UTF-8解码显示 5.2控制不要缓存 response.setHeader("Pragma","no-cache"); // HTTP1.0 response.setHeader("Cache-Control","no-cache"); // HTTP1.1 response.setDateHeader("Expires", 0); 5.3HttpServletResponse细节: 字节流和字符流不能同时使用,互斥的。 通过字符流或字节流输出的数据并不是直接打给浏览器的。而是把数据写到response对象的缓存中的。服务器从缓存中取出数据,按照HTTP协议的响应格式输出给浏览器。 如果你调用的response的输出流没有主动关闭,服务器会替你关的。 六、HttpServletRequest详解 HttpServletRequest代表着客户端的请求。要客户的信息只要找这个对象即可,该对象由容器创建。 ServletRequest是一个域对象(内部维护了一个Map<String,Object>) Object getAttribute(Stirng name): void setAttribute(String name,Object value): void removeAttribute(String name): 请求参数的编码: 浏览器当前使用什么编码,就以什么编码提交请求参数。<meta http-equiv="content-type" content="text/html; charset=UTF-8"> request.setCharacterEncoding(编码):通知程序,客户端提交的数据使用的编码。但是只对POST请求方式有效 如果是get请求提交数据,编码就是ISO-8859-1 请求转发、包含、重定向 1、请求转发:(当前应用内转) 请求转发借助于RequestDispatcher: RequestDispatcher.forward(request,response) 如何得到RequestDispatcher对象: 方式一:ServletContext.getRequestDispatcher(目标资源的URI); 方式二:ServletRequest.getRequestDispatcher(目标资源的URI); 区别: 方式一中的目标资源的URI必须以"/"开头,否则报错,此"/"就表示的是当前应用(绝对路径表示法) 方式二中的目标资源的URI如果以"/"开头,就表示的是当前应用(绝对路径表示法)。如果不以"/"开头,就表示相对路径。 转发的细节:AServlet(源组件)--->BServlet(目标组件) 注:Response对象是有缓存的。转发前,容器会清空response的缓存 1>转发前会清空response的正文。容器会清空源组件输出的数据。因此,用户只会看到目标组件输出的页面结果。但是,源组件的响应头信息是不清空的。 2>转发页面上只会输出目标组件的输出,源组件的任何页面输出都无效。 原则:转发前,不要刷新或关闭response的输出流。 2、包含:借助于RequestDispatcher: RequestDispatcher.include(request,response) AServlet(源组件)--->BServlet(目标组件):AServlet包含BServlet的输出内容 包含的细节: 由源组件包含到目标组件时,容器会清空目标组件的头。因此,只有源组件设置的头才有效。但是,目标组件的响应体信息是不清空的。 编码原则:不要在目标组件中设置响应头。(做无用功) 3、重定向:response.sendRedirect(String location) 各种URL地址的写法 相对路径:不是以"/"开头 绝对路径:(建议的) 原则:地址是不是给服务器用的,如果是,"/"就代表着当前应用。如果是给客户端用的绝对路径要加上应用名称。 <link href=path/> 要加/day07 <script src=path/> 要加/day07 <img src=path/> 要加/day07 <a href=path/> 要加/day07 <form action="path"/> 要加/day07 HttpServletResponse.sendRedirect(path) 要加/day07 getRequestDispatcher(String path): 不要加应用名称,"/"就代表着当前应用 ServletContext.getRealPath(path) 不要加,"/"就代表着当前应用 响应消息头:Refresh=2;URL=path 要加/day06 七、会话概述 (一)Cookie 是客户端技术 1、Cookie详细介绍 javax.servlet.http.Cookie 1)Cookie是什么? Cookie是一段小信息。Servlet把这些小信息写到客户端的缓存中(Set-Cookie),客户端还能带着小信息给服务器(Cookie)。 2)Cookie的属性: name:必须的 value:必须的 comment:(可选的)注释 path:(可选的) 写Cookie的程序的访问路径是:http://localhost:8080/day07/servlet/CookieDemo1 其中:localhost就是域名;/day07/servlet就是当前Cookie的path 若访问的地址的URI是以cookie的路径(path)开头的,那么发出的请求就会带上这个Cookie eg: 1、cookie的路径是/day07 现在访问的地址是:http://localhost:8080/day07/servlet/CookieDemo1 带Cookie 现在访问的地址是:http://localhost:8080/day07/CookieDemo1 带Cookie 2、cookie的路径是/day07/servlet/ 现在访问的地址是:http://localhost:8080/day07/servlet/CookieDemo1 带Cookie 现在访问的地址是:http://localhost:8080/day07/CookieDemo1 不带Cookie domain:(可选的)默认值是写Cookie的那个网站。如果domain取值为localhost,那么只有访问localhost这个网站时才会带过去。 maximum age: (可选的)设置Cookie的最大存活时间。默认值是浏览器进程(一次会话)。单位是秒。 可选的。不设置就是会话过程(存在浏览器的内存中)。单位是秒 若设置为0,则会删除Cookie。 version:可选的。 3)向客户端写Cookie:HttpServletResponse.addCookie(Cookie)(就是写了一个响应消息头:Set-Cookie:cookie的信息) 特点:一个浏览器针对一个网站最多存20个Cookie;一共最多存300个Cookie,每个Cookie的长度不能超过4KB。 4)服务器得到客户端传来的Cookie:HttpServletRequest.getCookies() 5)区分Cookie:domian+path+name:唯一定位一个Cookie eg:localhost:8080/day07/servlet/CookieDemo1 2、Cookie案例: 1记住用户最后一次的访问时间 2记住用户登录时的用户名 3电商网站:记住用户商品的历史浏览记录 (二)HttpSession是服务器端技术 1、HttpSession 是一个域对象。 2、HttpSession实际上用的是cookie技术。服务器向客户端写了一个特殊的cookie,名字为"JSESSIONID",值为当前session对象的id(由服务器生成、唯一),path是当前应用。 3、HttpSession中常用的方法 a、得到HttpSession对象:HttpServletRequest.getSession():根据客户端cookie(JSESSIONID=HttpSession对象的id)的值查找session对象,若没有,创建一个session对象。 b、HttpServletReqeust.getSession(boolean create):如果为true,与a没有区别。如果为false,只会查找。 c、HttpSession.getId():唯一的session对象标识。 HttpSession对象的状态及转换(序列化) 4、更改内存中HttpSession对象的超时时间。 修改web.xml <session-config> <session-timeout>1</session-timeout><!--自然整数,单位是分钟--> </session-config>
原文地址:http://blog.csdn.net/wodewutai17quiet/article/details/44005183