10.Servlet注解方式之前演示的Servlet例子都是使用web.xml文件来配置的 , 现在来看看使用注解方式配置Servlet
10.1快速入门具体步骤:
- 编写类OkServlet去继承HttpServlet
- 注解方式配置OkServlet,一个Servlet支持配置多个urlPattern(即通过不同的urlPattern可以访问同一个Servlet)
文章插图
package com.li.servlet.annotation;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * 注解的方式来配置: * * 1.@WebServlet 是一个注解 * 2.@WebServlet 源码: *@Target({ElementType.TYPE}) =>用于指定 被修饰的Annotation可以用于修饰 哪些程序元素 * @Retention(RetentionPolicy.RUNTIME) =>用于指定该Annotation可以保留多长时间 * @Documented =>在Javadoc工具生成文档时,可以看到该注解 。* public @interface WebServlet { * String name() default ""; * * String[] value() default {}; * * String[] urlPatterns() default {}; * * int loadOnStartup() default -1; * } * 3. urlPatterns对应 web.xml的 <url-pattern></url-pattern> * 4. {"/ok1","/ok2"} 表示可以给OKServlet配置多个url-pattern * 5. 相当于这个@WebServlet(urlPatterns = {"/ok1","/ok2"}) 代替了web.xml的配置 *底层使用了反射+注解+IO+集合 来完成一个支撑 * 6. 浏览器访问OkServlet时,可以输入 http://localhost:8080/web应用名/ok1 * 或者http://localhost:8080/web应用名/ok2 * 7. */@WebServlet(urlPatterns = {"/ok1", "/ok2"})public class OkServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("注解方式 OkServlet doGet()");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("注解方式 OkServlet doPost()");}}
在浏览器中输入:http://localhost:8080/servlet_demo/ok1
或者http://localhost:8080/servlet_demo/ok2
文章插图
文章插图
后台的显示如下:说明两次都能正常地访问OkServlet
文章插图
10.2注解方式是如何完成Servlet配置的?一个疑问:web.xml文件是通过dom4j来获取数据 , 然后进行反射 。那注解为什么也能进行Servlet的调用或者是初始化等操作的呢?它的原理是什么?
文章插图
根据上图:Tomcat得到http请求的工作如下
详见Servlet01--浏览器调用Servlet流程分析
- 如果是注解的方式 , 就对包进行扫描,如果发现某个类是用@WebServlet注解过的,就说明该类是一个Servlet,就会读取@WebServlet的urlPatterns的值
- 看看浏览器请求的资源 /XxxServlet 有没有在包配置过
- 如果找到对应的urlPatterns,就会得到对应的servletname
- Tomcat维护了一个大的HashMap<id,Servlet> , 查询该HashMap,看看有没有这个Servlet实例
- 如果没有查询到该servlet-name对应的id,即没有这个Servlet实例时
- 就去得到servlet类的全路径(之前扫描包的时候就可以获取全路径)
- 使用反射技术,将servlet实例化(同时调用init方法),并将该实例放入到Tomcat维护的HashMap<id,Servlet>中
不要同时配置注解和web.xml 。即不要配置了该Servlet的web.xml,又在该Servlet类上添加注解下面模拟一下Tomcat是如何通过@WebServlet(urlPatterns = {"/ok1", "/ok2"})来装载一个Servlet的:
反射+注解+IO+集合
package com.li.servlet.annotation;import javax.servlet.annotation.WebServlet;import java.util.HashMap;/** * 模拟一下Tomcat是如何通过@WebServlet(urlPatterns = {"/ok1", "/ok2"}) * 来装载一个Servlet的 */public class TestAnnotationServlet {private static final HashMap<String, Object> hm = new HashMap<>();public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//1.首先要得到扫描的包 路径(IO),进而得到类的全路径(如何扫描包的过程暂时略过)String classAllPath = "com.li.servlet.annotation.OkServlet";//2.得到OkServlet的class对象Class<?> aclass = Class.forName(classAllPath);//3.通过class对象,得到annotationWebServlet annotation = aclass.getAnnotation(WebServlet.class);//4.获取annotation的属性System.out.println(annotation);String[] strings = annotation.urlPatterns();for (String url : strings) {System.out.println("url=" + url);}//如果匹配url,如果是第一次请求tomcat,tomcat就会创建一个OkServlet实例,放入HashMap中Object instance = aclass.newInstance();System.out.println(instance);//instance就是一个OkServlet的实例对象//简单地模拟hm.put("OkServlet", instance);System.out.println(hm);//如果是第二次及以后请求tomcat,就会直接去HashMap中去查找OkServlet的实例对象}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-