1. Load db3.properties
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db/config/db3.properties"); InputStream in = new FileInputStream(path); Properties prop = new Properties(); prop.load(in);
2. Load db4.properties
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/gacl/servlet/study/db4.properties"); Properties prop = new Properties(); prop.load(in);
ClassLoader loader = ServletContextDemo.class.getClassLoader(); InputStream in = loader.getResourceAsStream("gacl/servlet/study/db4.properties"); Properties prop = new Properties(); prop.load(in);
3. Load db2.properties
InputStream in = this.getServletContext().getResourceAsStream("/db2.properties"); Properties prop = new Properties(); prop.load(in);
4. Load db1.properties
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db1.properties"); Properties prop = new Properties(); prop.load(in);
ClassLoader loader = ServletContextDemo.class.getClassLoader(); InputStream in = loader.getResourceAsStream("db1.properties"); Properties prop = new Properties(); prop.load(in);
在客户端缓存Servlet的输出:
response.setDateHeader("expires",System.currentTimeMillis() + 24 * 3600 * 1000);
response.getOutputStream().write(data.getBytes());
多个Servlet通过ServletContext对象实现数据共享
ServletContext context = this.getServletConfig().getServletContext(); context.setAttribute("data", data);
ServletContext context = this.getServletContext(); String data = (String) context.getAttribute("data");
在web.xml文件中使用<context-param>标签配置WEB应用的初始化参数
<context-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost:3306/test</param-value> </context-param>
ServletContext context = this.getServletContext(); String contextInitParam = context.getInitParameter("url");
用servletContext实现请求转发
ServletContext context = this.getServletContext(); RequestDispatcher rd = context.getRequestDispatcher("/servlet/ServletContextDemo5"); rd.forward(request, response);
Servlet 3.0 with annotation of @WebServlet @WebInitParam and use reflection
<filter> <description>注解处理过滤器</description> <filter-name>AnnotationHandleFilter</filter-name> <filter-class>me.gacl.web.filter.AnnotationHandleFilter</filter-class> <init-param> <description>配置要扫描包及其子包, 如果有多个包,以逗号分隔</description> <param-name>basePackage</param-name> <param-value>me.gacl.web.controller,me.gacl.web.UI</param-value> <!-- <param-value>me.gacl.web.controller</param-value> --> </init-param> </filter> <filter-mapping> <filter-name>AnnotationHandleFilter</filter-name> <!-- 拦截后缀是.do的请求 --> <url-pattern>*.do</url-pattern> </filter-mapping>
package me.gacl.web.filter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import me.gacl.annotation.WebInitParam; import me.gacl.annotation.WebServlet; import me.gacl.util.ScanClassUtil; /** * @ClassName: AnnotationHandleFilter * @Description: 使用Filter作为注解的处理器 * @author: 孤傲苍狼 * @date: 2014-11-12 下午10:15:19 * */ public class AnnotationHandleFilter implements Filter { private ServletContext servletContext = null; /* 过滤器初始化时扫描指定的包下面使用了WebServlet注解的那些类 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ public void init(FilterConfig filterConfig) throws ServletException { System.out.println("---AnnotationHandleFilter过滤器初始化开始---"); servletContext = filterConfig.getServletContext(); Map<String, Class<?>> classMap = new HashMap<String, Class<?>>(); //获取web.xml中配置的要扫描的包 String basePackage = filterConfig.getInitParameter("basePackage"); //如果配置了多个包,例如:<param-value>me.gacl.web.controller,me.gacl.web.UI</param-value> if (basePackage.indexOf(",")>0) { //按逗号进行分隔 String[] packageNameArr = basePackage.split(","); for (String packageName : packageNameArr) { addServletClassToServletContext(packageName,classMap); } }else { addServletClassToServletContext(basePackage,classMap); } System.out.println("----AnnotationHandleFilter过滤器初始化结束---"); } /** * @Method: addServletClassToServletContext * @Description:添加ServletClass到ServletContext中 * @Anthor:孤傲苍狼 * * @param packageName * @param classMap */ private void addServletClassToServletContext(String packageName,Map<String, Class<?>> classMap){ Set<Class<?>> setClasses = ScanClassUtil.getClasses(packageName); for (Class<?> clazz :setClasses) { if (clazz.isAnnotationPresent(WebServlet.class)) { //获取WebServlet这个Annotation的实例 WebServlet annotationInstance = clazz.getAnnotation(WebServlet.class); //获取Annotation的实例的value属性的值 String annotationAttrValue = annotationInstance.value(); if (!annotationAttrValue.equals("")) { classMap.put(annotationAttrValue, clazz); } //获取Annotation的实例的urlPatterns属性的值 String[] urlPatterns = annotationInstance.urlPatterns(); for (String urlPattern : urlPatterns) { classMap.put(urlPattern, clazz); } servletContext.setAttribute("servletClassMap", classMap); System.out.println("annotationAttrValue:"+annotationAttrValue); String targetClassName = annotationAttrValue.substring(annotationAttrValue.lastIndexOf("/")+1); System.out.println("targetClassName:"+targetClassName); System.out.println(clazz); } } } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("---进入注解处理过滤器---"); //将ServletRequest强制转换成HttpServletRequest HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; Map<String, Class<?>> classMap = (Map<String, Class<?>>) servletContext.getAttribute("servletClassMap"); //获取contextPath String contextPath = req.getContextPath(); //获取用户请求的URI资源 String uri = req.getRequestURI(); //如果没有指明要调用Servlet类中的哪个方法 if (uri.indexOf("!")==-1) { //获取用户使用的请求方式 String reqMethod = req.getMethod(); //获取要请求的servlet路径 String requestServletName = uri.substring(contextPath.length(),uri.lastIndexOf(".")); //获取要使用的类 Class<?> clazz = classMap.get(requestServletName); //创建类的实例 Object obj = null; try { obj = clazz.newInstance(); } catch (InstantiationException e1) { e1.printStackTrace(); } catch (IllegalAccessException e1) { e1.printStackTrace(); } Method targetMethod = null; if (reqMethod.equalsIgnoreCase("get")) { try { targetMethod = clazz.getDeclaredMethod("doGet",HttpServletRequest.class,HttpServletResponse.class); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } }else { try { targetMethod = clazz.getDeclaredMethod("doPost",HttpServletRequest.class,HttpServletResponse.class); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } try { //调用对象的方法进行处理 targetMethod.invoke(obj,req,res); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }else { //获取要请求的servlet路径 String requestServletName = uri.substring(contextPath.length(),uri.lastIndexOf("!")); //获取要调用的servlet的方法 String invokeMethodName = uri.substring(uri.lastIndexOf("!")+1,uri.lastIndexOf(".")); //获取要使用的类 Class<?> clazz = classMap.get(requestServletName); //创建类的实例 Object obj = null; try { obj = clazz.newInstance(); } catch (InstantiationException e1) { e1.printStackTrace(); } catch (IllegalAccessException e1) { e1.printStackTrace(); } //获得clazz类定义的所有方法 Method[] methods = clazz.getDeclaredMethods(); //获取WebServlet这个Annotation的实例 WebServlet annotationInstance = clazz.getAnnotation(WebServlet.class); //获取注解上配置的初始化参数数组 WebInitParam[] initParamArr = annotationInstance.initParams(); Map<String, String> initParamMap = new HashMap<String, String>(); for (WebInitParam initParam : initParamArr) { initParamMap.put(initParam.paramName(), initParam.paramValue()); } //遍历clazz类中的方法 for (Method method : methods) { //该方法的返回类型 Class<?> retType = method.getReturnType(); //获得方法名 String methodName = method.getName(); //打印方法修饰符 System.out.print(Modifier.toString(method.getModifiers())); System.out.print(" "+retType.getName() + " " + methodName +"("); //获得一个方法参数数组(getparameterTypes用于返回一个描述参数类型的Class对象数组) Class<?>[] paramTypes = method.getParameterTypes(); for(int j = 0 ; j < paramTypes.length ; j++){ //如果有多个参数,中间则用逗号隔开,否则直接打印参数 if (j > 0){ System.out.print(","); } System.out.print(paramTypes[j].getName()); } System.out.println(");"); if (method.getName().equalsIgnoreCase("init")) { try { //调用Servlet的初始化方法 method.invoke(obj, initParamMap); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } //获取WebServlet这个Annotation的实例 System.out.println("invokeMethodName:"+invokeMethodName); try { try { //利用反射获取方法实例,方法的签名必须符合: //public void 方法名(HttpServletRequest request, HttpServletResponse response) //例如:public void loginHandle(HttpServletRequest request, HttpServletResponse response) Method targetMethod = clazz.getDeclaredMethod(invokeMethodName,HttpServletRequest.class,HttpServletResponse.class); //调用对象的方法进行处理 targetMethod.invoke(obj,req,res); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (IllegalAccessException e) { e.printStackTrace(); } } } public void destroy() { } }
package me.gacl.util; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ScanClassUtil { /** * 从包package中获取所有的Class * * @param pack * @return */ public static Set<Class<?>> getClasses(String pack) { // 第一个class类的集合 Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); // 是否循环迭代 boolean recursive = true; // 获取包的名字 并进行替换 String packageName = pack; String packageDirName = packageName.replace('.', '/'); // 定义一个枚举的集合 并进行循环来处理这个目录下的things Enumeration<URL> dirs; try { dirs = Thread.currentThread().getContextClassLoader().getResources( packageDirName); // 循环迭代下去 while (dirs.hasMoreElements()) { // 获取下一个元素 URL url = dirs.nextElement(); // 得到协议的名称 String protocol = url.getProtocol(); // 如果是以文件的形式保存在服务器上 if ("file".equals(protocol)) { System.err.println("file类型的扫描"); // 获取包的物理路径 String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); // 以文件的方式扫描整个包下的文件 并添加到集合中 findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); } else if ("jar".equals(protocol)) { // 如果是jar包文件 // 定义一个JarFile System.err.println("jar类型的扫描"); JarFile jar; try { // 获取jar jar = ((JarURLConnection) url.openConnection()) .getJarFile(); // 从此jar包 得到一个枚举类 Enumeration<JarEntry> entries = jar.entries(); // 同样的进行循环迭代 while (entries.hasMoreElements()) { // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 JarEntry entry = entries.nextElement(); String name = entry.getName(); // 如果是以/开头的 if (name.charAt(0) == '/') { // 获取后面的字符串 name = name.substring(1); } // 如果前半部分和定义的包名相同 if (name.startsWith(packageDirName)) { int idx = name.lastIndexOf('/'); // 如果以"/"结尾 是一个包 if (idx != -1) { // 获取包名 把"/"替换成"." packageName = name.substring(0, idx) .replace('/', '.'); } // 如果可以迭代下去 并且是一个包 if ((idx != -1) || recursive) { // 如果是一个.class文件 而且不是目录 if (name.endsWith(".class") && !entry.isDirectory()) { // 去掉后面的".class" 获取真正的类名 String className = name.substring( packageName.length() + 1, name .length() - 6); try { // 添加到classes classes.add(Class .forName(packageName + '.' + className)); } catch (ClassNotFoundException e) { // log // .error("添加用户自定义视图类错误 找不到此类的.class文件"); e.printStackTrace(); } } } } } } catch (IOException e) { // log.error("在扫描用户定义视图时从jar包获取文件出错"); e.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); } return classes; } /** * 以文件的形式来获取包下的所有Class * * @param packageName * @param packagePath * @param recursive * @param classes */ public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, Set<Class<?>> classes) { // 获取此包的目录 建立一个File File dir = new File(packagePath); // 如果不存在或者 也不是目录就直接返回 if (!dir.exists() || !dir.isDirectory()) { // log.warn("用户定义包名 " + packageName + " 下没有任何文件"); return; } // 如果存在 就获取包下的所有文件 包括目录 File[] dirfiles = dir.listFiles(new FileFilter() { // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) public boolean accept(File file) { return (recursive && file.isDirectory()) || (file.getName().endsWith(".class")); } }); // 循环所有文件 for (File file : dirfiles) { // 如果是目录 则继续扫描 if (file.isDirectory()) { findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes); } else { // 如果是java类文件 去掉后面的.class 只留下类名 String className = file.getName().substring(0, file.getName().length() - 6); try { // 添加到集合中去 //classes.add(Class.forName(packageName + '.' + className)); //经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净 classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className)); } catch (ClassNotFoundException e) { // log.error("添加用户自定义视图类错误 找不到此类的.class文件"); e.printStackTrace(); } } } } }
package me.gacl.util; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** * 对java反射中操作的一些封装 */ public class BeanUtils { /** * 实例化一个class * @param <T> * @param clazz Person.class * @return */ public static <T> T instanceClass(Class<T> clazz){ if(!clazz.isInterface()){ try { return clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return null; } /** * 通过构造函数实例化 * @param <T> * @param ctor * @param args * @return * @throws IllegalArgumentException * @throws InstantiationException * @throws IllegalAccessException * @throws InvocationTargetException */ public static <T> T instanceClass(Constructor<T> ctor, Object... args) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{ makeAccessible(ctor); return ctor.newInstance(args);//调用构造方法实例化 } /** * 查找某个class的方法 * @param clazz * @param methodName * @param paramTypes * @return * @throws SecurityException * @throws NoSuchMethodException */ public static Method findMethod(Class<?> clazz, String methodName, Class<?>... paramTypes){ try { return clazz.getMethod(methodName, paramTypes); } catch (NoSuchMethodException e) { return findDeclaredMethod(clazz, methodName, paramTypes);//返回共有的方法 } } public static Method findDeclaredMethod(Class<?> clazz, String methodName, Class<?>[] paramTypes){ try { return clazz.getDeclaredMethod(methodName, paramTypes); } catch (NoSuchMethodException ex) { if (clazz.getSuperclass() != null) { return findDeclaredMethod(clazz.getSuperclass(), methodName, paramTypes); } return null; } } public static Method [] findDeclaredMethods(Class<?> clazz){ return clazz.getDeclaredMethods(); } public static void makeAccessible(Constructor<?> ctor) { if ((!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) && !ctor.isAccessible()) { ctor.setAccessible(true);//如果是私有的 设置为true 使其可以访问 } } public static Field[] findDeclaredFields(Class<?> clazz){ return clazz.getDeclaredFields(); } }
Listener-Class in Web.xml
<listener> <listener-class>com.sanlogic.uum.init.SystemSettingContextListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>