博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaWeb学习总结(四十八)——模拟Servlet3.0使用注解的方式配置Servlet
阅读量:5924 次
发布时间:2019-06-19

本文共 23859 字,大约阅读时间需要 79 分钟。

一、Servlet的传统配置方式

  在JavaWeb开发中, 每次编写一个Servlet都需要在web.xml文件中进行配置,如下所示:

1 
2
ActionServlet
3
me.gacl.web.controller.ActionServlet
4
5 6
7
ActionServlet
8
/servlet/ActionServlet
9

  每开发一个Servlet,都要在web.xml中配置Servlet才能够使用,这实在是很头疼的事情,所以Servlet3.0之后提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署描述,简化开发流程。本文所讲的基于注解方式配置Servlet不是针对Servlet3.0的,而是基于Servlet2.5的,通过开发自定义注解和注解处理器来实现类似于Servlet3.0的注解方式配置Servlet。

二、基于注解的方式配置Servlet

  JDK1. 5版本之后, JAVA提供了一种叫做Annotation的新数据类型,中文译为注解或标注,它的出现为铺天盖地的XML配置文件提供了一个完美的解决方案,让 JAVA EE开发更加方便快速,也更加干净了。不过Servlet2.5默认情况下是不支持注解方式的配置的,但是我们可以开发自定义注解,然后将注解标注到Servlet上,再针对我们自定义的注解写一个注解处理器,具体的做法如下:

2.1、开发用于配置Servlet的相关注解

  1、开发WebServlet注解,用于标注处理请求的Servlet类

1 package me.gacl.annotation; 2  3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7  8 /** 9  * 自定义WebServlet注解,模拟Servlet3.0的WebServlet注解10  * @Target 注解的属性值表明了 @WebServlet注解只能用于类或接口定义声明的前面, 11  * @WebServlet注解有一个必填的属性 value 。12  * 调用方式为: @WebServlet(value="/xxxx") ,13  * 因语法规定如果属性名为 value 且只填 value属性值时,可以省略 value属性名,即也可以写作:@WebServlet("/xxxx") 14  */15 @Retention(RetentionPolicy.RUNTIME)16 @Target(ElementType.TYPE)17 public @interface WebServlet {18     //Servlet的访问URL19     String value();20     //Servlet的访问URL21     String[] urlPatterns() default {""};22     //Servlet的描述23     String description() default "";24     //Servlet的显示名称25     String displayName() default "";26     //Servlet的名称27     String name() default "";28     //Servlet的init参数29     WebInitParam[] initParams() default {};30 }

  将Servlet在web.xml中的配置信息使用WebServlet注解来表示,使用注解后,只需要在相应Servlet 类的前面使用类似@WebServlet("/servlet/LoginServlet") 注解就可以达到和上述 web.xml 文件中配置信息一样的目的。注解@WebServlet中的属性值"/servlet/LoginServlet"表示了web.xml 配置文件中 <servlet-mapping> 元素的子元素 <url-pattern> 里的值。通过这样的注解能简化在 XML 文件中配置 Servlet 信息,整个配置文件将会非常简洁干净,开发人员的工作也将大大减少。

  2、开发WebInitParam注解,用于配置Servlet初始化时使用的参数

1 package me.gacl.annotation; 2  3 import java.lang.annotation.ElementType; 4 import java.lang.annotation.Retention; 5 import java.lang.annotation.RetentionPolicy; 6 import java.lang.annotation.Target; 7  8 /** 9 * @ClassName: WebInitParam10 * @Description: 定义Servlet的初始化参数注解11 * @author: 孤傲苍狼12 * @date: 2014-10-1 下午3:25:5313 *14 */15 @Retention(RetentionPolicy.RUNTIME)16 @Target(ElementType.TYPE)17 public @interface WebInitParam {18     //参数名19     String paramName() default "";20     //参数的值21     String paramValue() default "";22 }

2.2、编写处理注解的处理器

  上面简要地介绍了注解的定义声明与使用方式,注解在后台需要一个处理器才能起作用,所以还得针对上面的注解编写处理器,在这里我们使用Filter作为注解的处理器,编写一个AnnotationHandleFilter,代码如下:

1 package me.gacl.web.filter;  2   3 import java.io.IOException;  4 import java.lang.reflect.InvocationTargetException;  5 import java.lang.reflect.Method;  6 import java.lang.reflect.Modifier;  7 import java.util.HashMap;  8 import java.util.Map;  9 import java.util.Set; 10 import javax.servlet.Filter; 11 import javax.servlet.FilterChain; 12 import javax.servlet.FilterConfig; 13 import javax.servlet.ServletContext; 14 import javax.servlet.ServletException; 15 import javax.servlet.ServletRequest; 16 import javax.servlet.ServletResponse; 17 import javax.servlet.http.HttpServletRequest; 18 import javax.servlet.http.HttpServletResponse; 19 import me.gacl.annotation.WebInitParam; 20 import me.gacl.annotation.WebServlet; 21 import me.gacl.util.ScanClassUtil; 22  23 /** 24 * @ClassName: AnnotationHandleFilter 25 * @Description: 使用Filter作为注解的处理器 26 * @author: 孤傲苍狼 27 * @date: 2014-11-12 下午10:15:19 28 * 29 */  30 public class AnnotationHandleFilter implements Filter { 31  32     private ServletContext servletContext = null; 33      34     /* 过滤器初始化时扫描指定的包下面使用了WebServlet注解的那些类 35      * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 36      */ 37     public void init(FilterConfig filterConfig) throws ServletException { 38         System.out.println("---AnnotationHandleFilter过滤器初始化开始---"); 39         servletContext = filterConfig.getServletContext(); 40         Map
> classMap = new HashMap
>(); 41 //获取web.xml中配置的要扫描的包 42 String basePackage = filterConfig.getInitParameter("basePackage"); 43 //如果配置了多个包,例如:
me.gacl.web.controller,me.gacl.web.UI
44 if (basePackage.indexOf(",")>0) { 45 //按逗号进行分隔 46 String[] packageNameArr = basePackage.split(","); 47 for (String packageName : packageNameArr) { 48 addServletClassToServletContext(packageName,classMap); 49 } 50 }else { 51 addServletClassToServletContext(basePackage,classMap); 52 } 53 System.out.println("----AnnotationHandleFilter过滤器初始化结束---"); 54 } 55 56 /** 57 * @Method: addServletClassToServletContext 58 * @Description:添加ServletClass到ServletContext中 59 * @Anthor:孤傲苍狼 60 * 61 * @param packageName 62 * @param classMap 63 */ 64 private void addServletClassToServletContext(String packageName,Map
> classMap){ 65 Set
> setClasses = ScanClassUtil.getClasses(packageName); 66 for (Class
clazz :setClasses) { 67 if (clazz.isAnnotationPresent(WebServlet.class)) { 68 //获取WebServlet这个Annotation的实例 69 WebServlet annotationInstance = clazz.getAnnotation(WebServlet.class); 70 //获取Annotation的实例的value属性的值 71 String annotationAttrValue = annotationInstance.value(); 72 if (!annotationAttrValue.equals("")) { 73 classMap.put(annotationAttrValue, clazz); 74 } 75 //获取Annotation的实例的urlPatterns属性的值 76 String[] urlPatterns = annotationInstance.urlPatterns(); 77 for (String urlPattern : urlPatterns) { 78 classMap.put(urlPattern, clazz); 79 } 80 servletContext.setAttribute("servletClassMap", classMap); 81 System.out.println("annotationAttrValue:"+annotationAttrValue); 82 String targetClassName = annotationAttrValue.substring(annotationAttrValue.lastIndexOf("/")+1); 83 System.out.println("targetClassName:"+targetClassName); 84 System.out.println(clazz); 85 } 86 } 87 } 88 89 public void doFilter(ServletRequest request, ServletResponse response, 90 FilterChain chain) throws IOException, ServletException { 91 System.out.println("---进入注解处理过滤器---"); 92 //将ServletRequest强制转换成HttpServletRequest 93 HttpServletRequest req = (HttpServletRequest)request; 94 HttpServletResponse res = (HttpServletResponse)response; 95 Map
> classMap = (Map
>) servletContext.getAttribute("servletClassMap"); 96 //获取contextPath 97 String contextPath = req.getContextPath(); 98 //获取用户请求的URI资源 99 String uri = req.getRequestURI();100 //如果没有指明要调用Servlet类中的哪个方法101 if (uri.indexOf("!")==-1) {102 //获取用户使用的请求方式103 String reqMethod = req.getMethod();104 //获取要请求的servlet路径105 String requestServletName = uri.substring(contextPath.length(),uri.lastIndexOf("."));106 //获取要使用的类107 Class
clazz = classMap.get(requestServletName);108 //创建类的实例109 Object obj = null;110 try {111 obj = clazz.newInstance();112 } catch (InstantiationException e1) {113 e1.printStackTrace();114 } catch (IllegalAccessException e1) {115 e1.printStackTrace();116 }117 Method targetMethod = null;118 if (reqMethod.equalsIgnoreCase("get")) {119 try {120 targetMethod = clazz.getDeclaredMethod("doGet",HttpServletRequest.class,HttpServletResponse.class);121 } catch (SecurityException e) {122 e.printStackTrace();123 } catch (NoSuchMethodException e) {124 e.printStackTrace();125 }126 }else {127 try {128 targetMethod = clazz.getDeclaredMethod("doPost",HttpServletRequest.class,HttpServletResponse.class);129 } catch (SecurityException e) {130 e.printStackTrace();131 } catch (NoSuchMethodException e) {132 e.printStackTrace();133 }134 }135 136 try {137 //调用对象的方法进行处理138 targetMethod.invoke(obj,req,res);139 } catch (IllegalArgumentException e) {140 e.printStackTrace();141 } catch (IllegalAccessException e) {142 e.printStackTrace();143 } catch (InvocationTargetException e) {144 e.printStackTrace();145 }146 }else {147 //获取要请求的servlet路径148 String requestServletName = uri.substring(contextPath.length(),uri.lastIndexOf("!"));149 //获取要调用的servlet的方法150 String invokeMethodName = uri.substring(uri.lastIndexOf("!")+1,uri.lastIndexOf("."));151 152 //获取要使用的类153 Class
clazz = classMap.get(requestServletName);154 //创建类的实例155 Object obj = null;156 try {157 obj = clazz.newInstance();158 } catch (InstantiationException e1) {159 e1.printStackTrace();160 } catch (IllegalAccessException e1) {161 e1.printStackTrace();162 }163 //获得clazz类定义的所有方法164 Method[] methods = clazz.getDeclaredMethods();165 //获取WebServlet这个Annotation的实例166 WebServlet annotationInstance = clazz.getAnnotation(WebServlet.class);167 //获取注解上配置的初始化参数数组168 WebInitParam[] initParamArr = annotationInstance.initParams();169 Map
initParamMap = new HashMap
();170 for (WebInitParam initParam : initParamArr) {171 initParamMap.put(initParam.paramName(), initParam.paramValue());172 }173 //遍历clazz类中的方法174 for (Method method : methods) {175 //该方法的返回类型176 Class
retType = method.getReturnType();177 //获得方法名178 String methodName = method.getName();179 //打印方法修饰符180 System.out.print(Modifier.toString(method.getModifiers()));181 System.out.print(" "+retType.getName() + " " + methodName +"(");182 //获得一个方法参数数组(getparameterTypes用于返回一个描述参数类型的Class对象数组)183 Class
[] paramTypes = method.getParameterTypes();184 for(int j = 0 ; j < paramTypes.length ; j++){185 //如果有多个参数,中间则用逗号隔开,否则直接打印参数186 if (j > 0){187 System.out.print(",");188 } 189 System.out.print(paramTypes[j].getName());190 }191 System.out.println(");");192 if (method.getName().equalsIgnoreCase("init")) {193 try {194 //调用Servlet的初始化方法195 method.invoke(obj, initParamMap);196 } catch (IllegalArgumentException e) {197 e.printStackTrace();198 } catch (IllegalAccessException e) {199 e.printStackTrace();200 } catch (InvocationTargetException e) {201 e.printStackTrace();202 }203 }204 }205 //获取WebServlet这个Annotation的实例206 System.out.println("invokeMethodName:"+invokeMethodName);207 try {208 try {209 //利用反射获取方法实例,方法的签名必须符合:210 //public void 方法名(HttpServletRequest request, HttpServletResponse response)211 //例如:public void loginHandle(HttpServletRequest request, HttpServletResponse response)212 Method targetMethod = clazz.getDeclaredMethod(invokeMethodName,HttpServletRequest.class,HttpServletResponse.class);213 //调用对象的方法进行处理214 targetMethod.invoke(obj,req,res);215 } catch (SecurityException e) {216 e.printStackTrace();217 } catch (NoSuchMethodException e) {218 e.printStackTrace();219 } catch (IllegalArgumentException e) {220 e.printStackTrace();221 } catch (InvocationTargetException e) {222 e.printStackTrace();223 } 224 } catch (IllegalAccessException e) {225 e.printStackTrace();226 }227 }228 }229 230 public void destroy() {231 232 }233 }

  AnnotationHandleFilter过滤器初始化时扫描指定的包下面使用了WebServlet注解的那些类,然后将类存储到一个Map集合中,再将Map集合存储到servletContext对象中。

  

  在web.xml文件中配置AnnotationHandleFilter过滤器和需要扫描的包

1     
2
注解处理过滤器
3
AnnotationHandleFilter
4
me.gacl.web.filter.AnnotationHandleFilter
5
6
配置要扫描包及其子包, 如果有多个包,以逗号分隔
7
basePackage
8
me.gacl.web.controller,me.gacl.web.UI
9
10
11
12 13
14
AnnotationHandleFilter
15
16
*.do
17

  AnnotationHandleFilter过滤器初始化方法init(FilterConfig filterConfig)使用到了一个用于扫描某个包下面的类的工具类ScanClassUtil,ScanClassUtil的代码如下:

1 package me.gacl.util;  2   3 import java.io.File;  4 import java.io.FileFilter;  5 import java.io.IOException;  6 import java.net.JarURLConnection;  7 import java.net.URL;  8 import java.net.URLDecoder;  9 import java.util.Enumeration; 10 import java.util.LinkedHashSet; 11 import java.util.Set; 12 import java.util.jar.JarEntry; 13 import java.util.jar.JarFile; 14  15 public class ScanClassUtil { 16  17     /** 18      * 从包package中获取所有的Class 19      *  20      * @param pack 21      * @return 22      */ 23     public static Set
> getClasses(String pack) { 24 25 // 第一个class类的集合 26 Set
> classes = new LinkedHashSet
>(); 27 // 是否循环迭代 28 boolean recursive = true; 29 // 获取包的名字 并进行替换 30 String packageName = pack; 31 String packageDirName = packageName.replace('.', '/'); 32 // 定义一个枚举的集合 并进行循环来处理这个目录下的things 33 Enumeration
dirs; 34 try { 35 dirs = Thread.currentThread().getContextClassLoader().getResources( 36 packageDirName); 37 // 循环迭代下去 38 while (dirs.hasMoreElements()) { 39 // 获取下一个元素 40 URL url = dirs.nextElement(); 41 // 得到协议的名称 42 String protocol = url.getProtocol(); 43 // 如果是以文件的形式保存在服务器上 44 if ("file".equals(protocol)) { 45 System.err.println("file类型的扫描"); 46 // 获取包的物理路径 47 String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); 48 // 以文件的方式扫描整个包下的文件 并添加到集合中 49 findAndAddClassesInPackageByFile(packageName, filePath, 50 recursive, classes); 51 } else if ("jar".equals(protocol)) { 52 // 如果是jar包文件 53 // 定义一个JarFile 54 System.err.println("jar类型的扫描"); 55 JarFile jar; 56 try { 57 // 获取jar 58 jar = ((JarURLConnection) url.openConnection()) 59 .getJarFile(); 60 // 从此jar包 得到一个枚举类 61 Enumeration
entries = jar.entries(); 62 // 同样的进行循环迭代 63 while (entries.hasMoreElements()) { 64 // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 65 JarEntry entry = entries.nextElement(); 66 String name = entry.getName(); 67 // 如果是以/开头的 68 if (name.charAt(0) == '/') { 69 // 获取后面的字符串 70 name = name.substring(1); 71 } 72 // 如果前半部分和定义的包名相同 73 if (name.startsWith(packageDirName)) { 74 int idx = name.lastIndexOf('/'); 75 // 如果以"/"结尾 是一个包 76 if (idx != -1) { 77 // 获取包名 把"/"替换成"." 78 packageName = name.substring(0, idx) 79 .replace('/', '.'); 80 } 81 // 如果可以迭代下去 并且是一个包 82 if ((idx != -1) || recursive) { 83 // 如果是一个.class文件 而且不是目录 84 if (name.endsWith(".class") 85 && !entry.isDirectory()) { 86 // 去掉后面的".class" 获取真正的类名 87 String className = name.substring( 88 packageName.length() + 1, name 89 .length() - 6); 90 try { 91 // 添加到classes 92 classes.add(Class 93 .forName(packageName + '.' 94 + className)); 95 } catch (ClassNotFoundException e) { 96 // log 97 // .error("添加用户自定义视图类错误 找不到此类的.class文件"); 98 e.printStackTrace(); 99 }100 }101 }102 }103 }104 } catch (IOException e) {105 // log.error("在扫描用户定义视图时从jar包获取文件出错");106 e.printStackTrace();107 }108 }109 }110 } catch (IOException e) {111 e.printStackTrace();112 }113 114 return classes;115 }116 117 /**118 * 以文件的形式来获取包下的所有Class119 * 120 * @param packageName121 * @param packagePath122 * @param recursive123 * @param classes124 */125 public static void findAndAddClassesInPackageByFile(String packageName,126 String packagePath, final boolean recursive, Set
> classes) {127 // 获取此包的目录 建立一个File128 File dir = new File(packagePath);129 // 如果不存在或者 也不是目录就直接返回130 if (!dir.exists() || !dir.isDirectory()) {131 // log.warn("用户定义包名 " + packageName + " 下没有任何文件");132 return;133 }134 // 如果存在 就获取包下的所有文件 包括目录135 File[] dirfiles = dir.listFiles(new FileFilter() {136 // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)137 public boolean accept(File file) {138 return (recursive && file.isDirectory())139 || (file.getName().endsWith(".class"));140 }141 });142 // 循环所有文件143 for (File file : dirfiles) {144 // 如果是目录 则继续扫描145 if (file.isDirectory()) {146 findAndAddClassesInPackageByFile(packageName + "."147 + file.getName(), file.getAbsolutePath(), recursive,148 classes);149 } else {150 // 如果是java类文件 去掉后面的.class 只留下类名151 String className = file.getName().substring(0,152 file.getName().length() - 6);153 try {154 // 添加到集合中去155 //classes.add(Class.forName(packageName + '.' + className));156 //经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净157 classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className)); 158 } catch (ClassNotFoundException e) {159 // log.error("添加用户自定义视图类错误 找不到此类的.class文件");160 e.printStackTrace();161 }162 }163 }164 }165 }

  经过以上两步,我们的自定义注解和针对注解的处理器都开发好了。

2.3、WebServlet注解简单测试

  编写一个用于跳转到Login.jsp页面的LoginUIServlet,LoginUIServlet就是一个普通的java类,不是一个真正的Servlet,然后使用WebServlet注解标注LoginUIServlet类,代码如下:

1 package me.gacl.web.UI; 2  3 import java.io.IOException; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import me.gacl.annotation.WebServlet; 8  9 @WebServlet("/servlet/LoginUI")10 public class LoginUIServlet {11 12     public void doGet(HttpServletRequest request, HttpServletResponse response)13             throws ServletException, IOException{14         request.getRequestDispatcher("/Login.jsp").forward(request, response);15     }16     17     public void doPost(HttpServletRequest request, HttpServletResponse response)18             throws ServletException, IOException {19         doGet(request, response);20     }21 }

  在浏览器中输入访问地址:http://gacl-pc:8080/AnnotationConfigServlet/servlet/Login.do,根据web.xml文件的配置,所有后缀名为 .do请求,都会经过AnnotationHandleFilter过滤器的doFilter方法,在doFilter方法的实现代码中,从HttpServletRequest请求对象中得到请求的方式类型(GET/POST)和请求的URI 。如有请求http://gacl-pc:8080/AnnotationConfigServlet/servlet/LoginUI.do,此时请求方法类型为GET, URI 值为/AnnotationConfigServlet/servlet/LoginUI.do。从ServletConext对象中获取到在过滤器中保存的Map结构,根据 URI 获得一个 Key=”/servlet/LoginUI” ,从 Map 结构中根据此Key得到Value ,此时Value就是要请求调用的那个Servlet类,根据Servlet类创建对象实例,再根据前面得到的请求方法类型,能决定调用此Servlet对象实例的 doGet 或 doPost 方法。最终客户端发生的后缀为.do请求,经由AnnotationHandleFilter对请求对象(HttpServletRequest)的分析,从而调用相应某Servlet的doGet或doPost方法,完成了一次客户端请求到服务器响应的过程。

  使用注解后程序流程如下所示:

  

  运行结果如下:

  

  从运行结果中可以看到,我们的注解处理器成功调用了目标Servlet处理用户的请求,通过@WebServlet注解, Servlet不用再在web.xml 文件中进行繁冗的注册,这就是使用@WebServlet注解的方便之处。

2.3、WebServlet注解复杂测试

  编写Login.jsp页面,代码如下:

1 <%@ page language="java" pageEncoding="UTF-8"%> 2  3  4    5     登录页面 6    7    8    9     
10
用户登录11
12 用户名:
13
14 密码:
15
16
17
18
19

20 21 22

   form表单中的action属性的URL="${pageContext.request.contextPath}/servlet/LoginServlet!loginHandle.do"/servlet/LoginServlet表示要访问的是LoginServlet!后面的loginHandle表示要调用LoginServlet中的loginHandle方法处理此次的请求,也就是说,我们在访问Servlet时,可以在URL中指明要访问Servlet的哪个方法,AnnotationHandleFilter过滤器的doFilter方法在拦截到用户的请求之后,首先获取用户要访问的URI,根据URI判断用户要访问的Servlet,然后再判断URI中是否包含了"!",如果有,那么就说明用户显示指明了要访问Servlet的哪个方法,遍历Servlet类中定义的所有方法,如果找到了URI中的那个方法,那么就调用对应的方法处理用户请求!

  LoginServlet的代码如下:

1 package me.gacl.web.controller; 2  3 import java.io.IOException; 4 import java.util.Map; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import me.gacl.annotation.WebInitParam; 9 import me.gacl.annotation.WebServlet;10 11 /**12 * 13 * @ClassName: LoginServlet14 * @Description:处理用户登录的Servlet,15 * LoginServlet现在就是一个普通的java类,不是一个真正的Servlet16 * @author: 孤傲苍狼17 * @date: 2014-10-8 上午12:07:5818 *19 */20 //将开发好的WebServlet注解标注到LoginServlet类上21 @WebServlet(22             //Servlet的访问URL23             value="/servlet/LoginServlet",24             //Servlet的访问URL,可以使用数组的方式配置多个访问路径25             urlPatterns={"/gacl/LoginServlet","/xdp/LoginServlet"},26             //Servlet的初始化参数27             initParams={28                     @WebInitParam(paramName="gacl",paramValue="孤傲苍狼"),29                     @WebInitParam(paramName="bhsh",paramValue="白虎神皇")30             },31             name="LoginServlet",32             description="处理用户登录的Servlet"33         )34 public class LoginServlet {35 36     public void loginHandle(HttpServletRequest request, HttpServletResponse response) 37             throws ServletException, IOException{38         String username = request.getParameter("usename");39         String pwd = request.getParameter("pwd");40         if (username.equals("gacl") && pwd.equals("xdp")) {41             request.getSession().setAttribute("usename", username);42             request.setAttribute("msg", "欢迎您!"+username);43             request.getRequestDispatcher("/index.jsp").forward(request, response);44         }else {45             request.setAttribute("msg", "登录失败,请检查用户名和密码是否正确!");46             request.getRequestDispatcher("/Login.jsp").forward(request, response);47         }48     }49     50     51     /**52     * @Method: init53     * @Description: Servlet初始化54     * @Anthor:孤傲苍狼55     *56     * @param config57     */ 58     public void init(Map
initParamMap){59 System.out.println("--LoginServlet初始化--");60 System.out.println(initParamMap.get("gacl"));61 System.out.println(initParamMap.get("bhsh"));62 }63 }

  运行结果如下:

  

  可以看到,我们使用注解方式配置的Servlet已经成功调用了,loginHandle方法处理用户登录请求的完整处理过程如下图所示:

  

  Servlet3.0是支持采用基于注解的方式配置Servlet的,在此我使用过滤器作为注解处理器模拟模拟出了类似Servlet3.0的注解处理方式,简化了Servlet的配置。这种使用自定义注解+注解处理器的方式山寨出来的Servlet3.0大家了解一下即可,了解一下这种处理思路,在实际应用中还是不要这么做了,要真想使用注解的方式配置Servlet还是直接用Servlet3.0吧。

转载地址:http://vzivx.baihongyu.com/

你可能感兴趣的文章
13.文档模板架构
查看>>
Linux-软件安装管理
查看>>
C# DataTable的詳細用法
查看>>
spring集成mybatis的mybatis参考配置
查看>>
Coursera机器学习编程作业Python实现(Andrew Ng)—— 1.1 Linear regression with one variable...
查看>>
总结一些写毕业论文背景研究可以参考的资源
查看>>
IE中的CSS3不完全兼容方案
查看>>
centos6中iptables单机网络防火墙的使用
查看>>
剑指offer——面试题5:替换空格
查看>>
【我所理解的Cocos2d-x】第六章 精灵Sprite 读书笔记
查看>>
java面试题整理二(转灰灰+灰灰)
查看>>
Sequelize-nodejs-4-Model usage
查看>>
CSS3制作心形头像
查看>>
电子自旋
查看>>
虚拟环境virtualenv
查看>>
连续子数组的最大和
查看>>
把MacBook里的电影导入到iPad
查看>>
数据挖掘过程中:数据预处理
查看>>
JavaScript高级程序设计(第三版)学习笔记6、7章
查看>>
jQuery-DOM操作之创建、插入、删除元素
查看>>