一、Servlet的框架是由俩个Java包组成:
- javax.servlet包:定义了所有的servlet类都必须实现或扩展的通用接口和类。
- javax.servlet.http包:定义了采用HTTP协议通信的HttpServlet类。
二、Servlet生命周期
servlet的生命周期:init(ServletConfig)、service(ServletRequest,ServletResponse)、destroy()
public class HelloWorldInit implements Servlet { public HelloWorldInit(){ System.out.println("hello 默认构造"); } public void init(ServletConfig config) throws ServletException { System.out.println("init"); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { System.out.println("service"); } public void destroy() { System.out.println("destroy"); } public ServletConfig getServletConfig() { return null; } public String getServletInfo() { return null; } }
输出结果:
为什么会创建构造方法?
Tomcat服务器加载web.xml中的<servlet-class>com.test.HelloWorldInit</servlet>时,会根据这个类路径通过反射创建该类的实例。在服务器中操作大概过程如下:
Class clazz = Class.forName("com.test.HelloWorldInit"); Object obj = clazz.newInstance();//调用了构造方法
然后通过反射获取该对象里的init和service方法并调用,调用时会传入相应的实参(ServletConfig、ServletRequest和ServletResponse)
三、init(ServletConfig config)和service(ServletRequest request, ServletResponse response)俩方法的参数解析
public void init(ServletConfig config) throws ServletException { System.out.println("config:"+config); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { System.out.println("request:"+request+"\n"+"response:"+response); }
输入结果:
上图输出的结果分别是ServletConfig、ServletRequest、ServletResponse的实现类,下图为源码中的实现
(1)javax.servlet.ServletConfig(接口),该接口下有四个抽象方法
public void init(ServletConfig config) throws ServletException { //1、<servlet-name>返回这个里面的名称</servlet-name> System.out.println(config.getServletName()); //2、返回指定初始化参数名称的值,如果参数不存在就返回Null(在web.xml中要配置初始化参数) System.out.println(config.getInitParameter("gf")); //3、返回当前servlet的所有的初始化参数的名称,返回的是一个Enumeration(枚举) Enumeration<String> names = config.getInitParameterNames(); while(names.hasMoreElements()){ String name = names.nextElement(); System.out.println(name + ":" + config.getInitParameter(name)); } //4、ServletConfig保存了当前web项目的 ServletContext的引用 ServletContext sc = config.getServletContext(); System.out.println(sc); //实现类:org.apache.catalina.core.ApplicationContextFacade }
<servlet> <servlet-name>helloWorldInit</servlet-name> <servlet-class>cn.test.HelloWorldInit</servlet-class> <!-- 配置初始化参数列表 --> <init-param> <!-- 初始化参数的名称 --> <param-name>gf</param-name> <!-- 初始化参数的值 --> <param-value>规范</param-value> </init-param> </servlet>
(2)javax.servlet.ServletRequest和javax.servlet.ServletResponse(service方法的两个参数)]
/**第一个参数*/ //接口:javax.servlet.ServletRequest //实现类:org.apache.catalina.connector.RequestFacade /* * 关系: * * public class RequestFacade implements HttpServletRequest { * * public interface HttpServletRequest extends ServletRequest { * * 总结: RequestFacade --> HttpServletRequest --> ServletRequest * ************ * ServletRequest req = new RequestFacade(); * HttpServletRequest http = new RequestFacade(); * HttpServletRequest http2 = (HttpServletRequest)req; */
/**第二个参数*/ //接口:javax.servlet.ServletResponse //实现类:org.apache.catalina.connector.ResponseFacade /* 关系: * * public class ResponseFacade implements HttpServletResponse { * * public interface HttpServletResponse extends ServletResponse { * * * 总结:ResponseFacade --> HttpServletResponse --> ServletResponse */ HttpServletResponse response = (HttpServletResponse)resp;
四、Servlet实现初始化工作
public class FirstServlet extends HttpServlet { //进行初始化,直接覆盖GenericServlet的init()方法 @Override public void init() throws ServletException { //初始化工作 } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
<servlet> <servlet-name>FirstServletxx</servlet-name> <servlet-class>cn.itcast.servlet.FirstServlet</servlet-class> <!-- 配置当前servlet在服务器启动时加载顺序 取值:0-6 ,值越小,优先加载 --> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>FirstServletxx</servlet-name> <url-pattern>/firstServlet</url-pattern> </servlet-mapping>
五、servlet的虚拟路径
1) 只能使用 / 或 * 开头
2) / 和 *. 不能同时存在
3) / 或 /* 表示任意
4) 只有*.才表示通配符
六、项目路径
(1)getAbsolutePath( )
案例1:
public static void main(String[] args) { File file = new File(""); System.out.println(file.getAbsolutePath());//absolute绝对的意思 }
用命令窗口执行:
JAVA项目的class文件是存放在项目根目录的bin目录下
案例2:
public static void main(String[] args) { File file = new File("/") ; // '/'是相对路径,相对于当前盘符 可以获得当前盘符 System.out.println(file.getAbsolutePath()); }
输出结果都为:F:\(命令运行和eclipse运行)
总结:getAbsolutePath()使用java命令时输出的路径是当前Java命令停留的目录,使用eclipse运行时输出的路径是当前项目根目录的绝对路径
注意:生成jar包后里面的没有src和bin目录的,生成jar包的过成是把bin目录下的文件全都拷贝过来,所以将配置文件放在src下其实就是在根目录下
(2)类加载器获取路径
public static void main(String[] args) { //类加载器 //通过类 -> 获得字节码 -> 获得类加载器 -> 获得资源路径 //路径指向class文件存放的目录 URL url = Hello.class.getClassLoader().getResource(""); // InputStream is = Hello.class.getClassLoader().getResourceAsStream(""); //跟getResource一样 System.out.println(url); }
输出结果:file:/F:/myeclipse/Workspaces/TestProject/WebRoot/WEB-INF/classes/
注意:类加载器不能使用"/"
(3)ServletContext获取路径
ServletContext是对当前项目上下文的描述(对当前web项目所有内容的描述),tomcat为每一个web项目单独创建一个区域,用来管理整个项目。此区域称为ServletContext。
context root是指当前项目的根目录:
* tomcat --> webapps/webName
* myeclipse --> webName/WebRoot 指向的是WebRoot目录
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext sc2 = this.getServletConfig().getServletContext(); ServletContext sc = this.getServletContext(); //1 、 String path = sc.getRealPath("/1.html");//获得实际路径,要求/开头 System.out.println(path);// F:\apache-tomcat-7.0.29\webapps\day06\1.html //2、获得资源文件 URL url = sc.getResource("/1.html"); System.out.println(url.getPath());// /localhost/day06/1.html //3、 InputStream is = sc.getResourceAsStream("/1.html"); System.out.println(is); }
输出结果:F:\apache-tomcat-7.0.29\webapps\day06\1.html
要求必须以'/'开头
(4)web的相对路径
1、abc:与当前页面同级的目录或servlet的名称
* <a href="c/c.html">c.html</a><br>
2、/abc:相对于web站点,%tomcat%/webapps/
* <a href="/day06_web/b/c/c.html">c.html</a><br>
3、./abc:当前目录,与第一种情况相同
* <a href="./c/c.html">c.html</a><br>
4、../abc:上一次目录
* <a href="../b/c/c.html">c.html</a><br>
七、Servlet过滤器Filter
所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:
init( FilterConfig config);//Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数
doFilter( ServletRequest req, ServletResponse resp ,FilterChain chain);//FilterChain参数用于访问后续过滤器
destroy( );
在web.xml中必须先配置过滤器再配置Servlet
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class MyFilter implements Filter { private FilterConfig config = null; private String blackList = null; public void init(FilterConfig config) throws ServletException { this.config = config; blackList = config.getInitParameter("blacklist"); } public void destroy() { config = null; } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String username = ((HttpServletRequest) request) .getParameter("username"); if (username != null) username = new String(username.getBytes("ISO-8859-1"), "GB2312"); if (username != null && username.indexOf(blackList) != -1) { response.setContentType("text/html;charset=GB2312"); PrintWriter out = response.getWriter(); out.println("<html><head></head><body>"); out.println("<h1>对不起," + username + ",你没有权限留言 </h1>"); out.println("</body></html>"); out.flush(); return; } long before = System.currentTimeMillis(); config.getServletContext().log( "NoteFilter:before call chain.doFilter()"); chain.doFilter(request, response); config.getServletContext() .log("NoteFilter:after call chain.doFilter()"); long after = System.currentTimeMillis(); String name = ""; if (request instanceof HttpServletRequest) { name = ((HttpServletRequest) request).getRequestURI(); } config.getServletContext().log( "NoteFilter:" + name + ": " + (after - before) + "ms"); } }
<filter> <filter-name>myFilter</filter-name> <filter-class>com.test.filter.MyFilter</filter-class> <init-param> <param-name>blacklist</param-name> <param-value>hello</param-value> </init-param> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/NoteServlet</url-pattern> </filter-mapping>