Servlet学习记录2
读取web.xml参数
上篇文章ImageServlet里只设置了JPG,GIF,DOC类型文件的Content-Type。如果这时候需求变化了,需要增加Excel文件格式的Content-Type,就得修改ImageServlet源代码,重新编译class文件,然后重新部署。一个看起来很微小的改动却带来了大量的工作,很让人心烦。
现在在Java Web开发中,这种常量信息更倾向于写在某个配置文件里。需求变化时只需要修改一下配置文件就可以了,而不会修改源程序,也不会重新编译,维护起来相当方便。web.xml提供了设置初始化参数的功能,可以将这些信息配置在web.xml中。
初始化参数(init-param)
web.xml中配置Servlet的时候,标签<servlet>中可以包含标签<init-param>来配置初始化参数。一个Servlet可以配置0到多个初始化参数。接下来的例子InitParamServlet中配置了3个初始化参数。
- <servlet>
- <servlet-name>InitParamServlet</servlet-name>
- <servlet-class>
- com.helloweenvsfei.servlet.InitParamServlet
- </servlet-class>
- <init-param>
- <param-name>helloween</param-name>
- <param-value>password</param-value>
- </init-param>
- <init-param>
- <param-name>admin</param-name>
- <param-value>admin</param-value>
- </init-param>
- <init-param>
- <param-name>babyface</param-name>
- <param-value>babyface</param-value>
- </init-param>
- </servlet>
配置完毕后,Servlet中提供方法getInitParameter(String param)来获取初始化参数值。如果配置了名为param的参数,则返回参数值,否则返回null。在这段配置中,getInitParameter("helloween")将返回password,getInitParameter("Cobain")将返回null。还可以使用getInitParameterNames()方法返回所有的参数名称,返回结果为枚举类型(Enumeration)。
这些初始化的参数也可以由ServletConfig对象取得。Servlet提供getServletConfig()这个ServletConfig对象。由ServletConfig取初始化参数与Servlet直接取方式一样。
看一例子。公司要在网站上颁布一个机密文件notice.html,要求仅有少数几个人能够浏览到。我们来实现这种权限控制。
(1)把notice.html放在/WEB-INF文件夹下面。因为Java Web应用程序的WEB-INF文件夹有这个特性,任何人都不能通过浏览器直接获取下面的文件,即使他知道文件的准确位置及名称。WEB-INF下的文件是受保护的,这样就保证了文件的安全性。如果浏览器中输入http://localhost:8080/servlet/WEB-INF/notice.html,服务器会报404 Error,尽管这个文件地址是对的。
(2)编写一个程序InitParamServlet,提示用户输入用户名密码。如果密码验证通过,则通过程序转到notice.html上。虽然WEB-INF下的文件不能通过浏览器直接获取到,但是仍然可以通过程序读取到。程序如下:
- package com.helloweenvsfei.servlet;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Enumeration;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class InitParamServlet extends HttpServlet {
- private static final long serialVersionUID = 7298032096933866458L;
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
- out.println("<HTML>");
- out.println(" <HEAD><TITLE>请登录查看 Notice 文件</TITLE></HEAD>");
- out.println("<style>body, td, div {font-size:12px; }</style>");
- out.println(" <BODY>");
- out.println("<form action='" + request.getRequestURI() + "' method='post'>");
- out.println("帐号:<input type='text' name='username' style='width:200px; '> <br/>");
- out.println("密码:<input type='password' name='password' style='width:200px; '> <br/><br/>");
- out.println("<input type='submit' value=' 登录 '>");
- out.println("</form>");
- if(true){
- out.println("<br/><br/><br/><br/><br/><br/><br/>用户名、密码为:<br/>");
- Enumeration params = this.getInitParameterNames();
- while(params.hasMoreElements()){
- String usernameParam = (String)params.nextElement();
- String passnameParam = this.getInitParameter(usernameParam);
- out.println("[" + usernameParam + ", " + passnameParam + "], ");
- }
- }
- out.println(" </BODY>");
- out.println("</HTML>");
- out.flush();
- out.close();
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 提交的 username 参数
- String username = request.getParameter("username");
- // 提交的 password 参数
- String password = request.getParameter("password");
- // 取所有的初始化参数名称
- Enumeration params = this.getInitParameterNames();
- while(params.hasMoreElements()){
- String usernameParam = (String)params.nextElement();
- // 取参数值
- String passnameParam = this.getInitParameter(usernameParam);
- // 如果 username 匹配且 password 匹配. username 大小写不敏感,password大小写敏感
- if(usernameParam.equalsIgnoreCase(username)
- && passnameParam.equals(password)){
- // 显示文件。/WEB-INF 下的文件不能通过浏览器访问到,因此是安全的
- request.getRequestDispatcher("/WEB-INF/notice.html").forward(request, response);
- return;
- }
- }
- // username,password 不匹配,显示登录页面
- this.doGet(request, response);
- }
- }
登陆前后的效果如图3.6所示。Servlet显示/WEB-INF/下的文件。
一个月后,公司要求增加Peter为可以浏览该机密文件的人选,同时禁止babyface的账号。由于没有将这些信息写在源程序里而是写在了web.xml里,因此改动相当简单。在参数配置里添加一个Peter,删掉babyface就可以了。
初始化参数的好处是可以把某些变量拿到web.xml中配置,需要修改时只需要修改web.xml文件并重启服务器即可,而不需要修改Servlet类。
上下文参数(context-param)
由于init-param是配置在<servlet>标签里的,只能由这个Servlet来读取,因此它不是全局的参数,不能被其他的Servlet读取。
如果需要配置一个所有Servlet都能够读取的参数,就需要用到上下文参数(Context-Param),或者叫文档参数。上下文参数使用标签<context-param>配置,代码如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <context-param>
- <param-name>upload folder</param-name>
- <param-value>attachment</param-value>
- </context-param>
- <context-param>
- <param-name>allowed file type</param-name>
- <param-value>.gif,.jpg,.bmp</param-value>
- </context-param>
获取context-param可以使用ServletContext对象。Servlet中通过getServletConfig().getServletContext()来获取一个ServletContext对象,使用ServletContext的getInitParameter()方法来获取指定名称的参数,通过getInitParameterNames()获取所有的context-param参数名称。下面是一个例子:
- package com.helloweenvsfei.servlet;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.ServletContext;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class ContextParamServlet extends HttpServlet {
- private static final long serialVersionUID = 3194071196406358461L;
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
- out.println("<HTML>");
- out.println(" <HEAD><TITLE>读取文档参数</TITLE></HEAD>");
- out.println(" <link rel='stylesheet' type='text/css' href='../css/style.css'>");
- out.println(" <BODY>");
- out.println("<div align=center><br/>");
- out.println("<fieldset style='width:90%'><legend>所有的文档参数</legend><br/>");
- ServletContext servletContext = this.getServletConfig().getServletContext();
- String uploadFolder = servletContext.getInitParameter("upload folder");
- String allowedFileType = servletContext.getInitParameter("allowed file type");
- out.println("<div class='line'>");
- out.println(" <div align='left' class='leftDiv'>上传文件夹</div>");
- out.println(" <div align='left' class='rightDiv'>" + uploadFolder + "</div>");
- out.println("</div>");
- out.println("<div class='line'>");
- out.println(" <div align='left' class='leftDiv'>实际磁盘路径</div>");
- out.println(" <div align='left' class='rightDiv'>" + servletContext.getRealPath(uploadFolder) + "</div>");
- out.println("</div>");
- out.println("<div class='line'>");
- out.println(" <div align='left' class='leftDiv'>允许上传的类型</div>");
- out.println(" <div align='left' class='rightDiv'>" + allowedFileType + "</div>");
- out.println("</div>");
- out.println("</fieldset></div>");
- out.println(" </BODY>");
- out.println("</HTML>");
- out.flush();
- out.close();
- }
- }
运行效果如图:
初始化参数与上下文参数只能配置简单的字符串类型的参数。如果需要配置更多更灵活的参数,更推荐把参数配置写到xml文件或者properties文件里,然后编写程序读取这些文件。
资源注射(@Resource)
上面的例子都是在Servlet里编写程序代码读取web.xml初始参数。Java EE 5提供了一种新的方案叫做资源注射(Resource Injection),或者叫资源注入。也就是说,不需要Servlet主动去读取资源,Tomcat启动的时候会把web.xml里配置的信息主动“注射”到Servlet里。这个过程是运行时自动完成的,不需要编写任何代码,不需要做任何工作。
资源注射是通过注解(Annotation)完成的。注解是Java 5.0里引入的新特性。注解是一种特殊的接口,以“@”符号为标志。用法如下:
- @Resource(name="messageNameInWebXml")
- private String message;
使用@Resource标注字符串变量message,表示message的值会在Servlet运行时动态注入。然后在web.xml中配置一个名为messageNameInWebXml的参数就可以了。注解以及变量可以写在一行代码中,看起来更简洁一些;
- private @Resource(name="messageNameInWebXml") String message;
看一个实例
- package com.helloweenvsfei.servlet;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.annotation.Resource;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class InjectionServlet extends HttpServlet {
- private static final long serialVersionUID = -8526907492073769090L;
- // 注入的 字符串
- private @Resource(name="hello") String hello;
- // 注入的 整数
- private @Resource(name="i") int i;
- // 注入更常见的写法
- @Resource(name="persons")
- private String persons;
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setCharacterEncoding("UTF-8");
- request.setCharacterEncoding("UTF-8");
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
- out.println("<HTML>");
- out.println(" <HEAD><TITLE>资源注入</TITLE></HEAD>");
- out.println("<style>body {font-size:12px; }</style>");
- out.println("<b>注入的字符串</b>:<br/> - " + hello + "<br/>");
- out.println("<b>注入的整数</b>:<br/> - " + i + "<br/>");
- out.println("<b>注入的字符串数组</b>:<br/>");
- for(String person : persons.split(",")){
- out.println(" - " + person + "<br/>");
- }
- out.println(" <BODY>");
- out.println(" </BODY>");
- out.println("</HTML>");
- out.flush();
- out.close();
- }
- }
web.xml中使用标签<env-entry>来配置资源。<env-entry>仅能配置java.lang包下的标准类型的变量,如String,Integer,Double等。配置后的代码如下:
- <env-entry>
- <env-entry-name>hello</env-entry-name>
- <env-entry-type>java.lang.String</env-entry-type>
- <env-entry-value>
- Hello, Welcome to the JavaEE Resource Injection.
- </env-entry-value>
- </env-entry>
- <env-entry>
- <env-entry-name>i</env-entry-name>
- <env-entry-type>java.lang.Integer</env-entry-type>
- <env-entry-value>30</env-entry-value>
- </env-entry>
- <env-entry>
- <env-entry-name>persons</env-entry-name>
- <env-entry-type>java.lang.String</env-entry-type>
- <env-entry-value>
- Helloween, Cobain, Roses, Axl,
- </env-entry-value>
- </env-entry>
程序运行效果:
使用JNDI获取资源
资源注射的工作原理是JNDI(Java命名与目录接口,Java Naming and Directory Interface)。InjectionServlet实例中使用<env-entry>配置了名为hello, i, persons的JNDI资源,然后使用@Resource将指定名称的JNDI资源注射到InjectionServlet里。
如果不使用@Resource,通过查找JNDI同样可以获取到这三个资源,代码如下:
- Context ctx = new InitialContext(); //实例化一个Context对象
- String message = (String)ctx.lookup("message"); //查找资源message
- Integer i = (Integer)ctx.lookup("i"); //查找资源i
- String persons = (String)ctx.lookup("persons"); //查找资源persons
注射数据源
Servlet中不仅可以注射String,Integer等类型的变量,还可以注入自定义的Java Bean以及数据源等复杂类型变量。例如,下面的代码将会注射一个数据源。读者只需要在Tomcat中配置好数据源,然后使用下列代码就可以获取到数据源变量。这是相当方便的:
- @Resource(name="dataBase") //声明数据源名称,数据源配置在Tomcat中
- javax.sql.DataSource dataSource; //注射到dataSource属性上
- public void getConnection(){ //方法中直接使用dataSource
- Connection conn = dataSource.getConnection();
- return conn;
- }
注射是利用@注解实现的。JDK5以上支持@注解。资源注射需要服务器的支持,Tomcat 6是支持的,但在某些其它Web服务器或者低版本的Tomcat可能不支持。
Servlet学习记录2的更多相关文章
- Servlet学习记录4
带进度条的文件上传 UploadServlet只实现了普通的文件上传,并附带普通文本域的提交.如果需要显示上传进度条,实时显示上传速度等,需要配合使用Ajax技术.这里仍然使用Apache的commo ...
- Servlet学习记录3
提交表单信息 Web程序的任务是实现服务器与客户端浏览器之间的信息交互.客户端提交的信息可能来自表单里的文本框,密码框,选择框,单选按钮,复选框以及文件域.这些表单信息被以参数形式提交到了服务器.Se ...
- servlet学习记录:Servlet中的service()方法
Servlet的生存时间是由init,service,destory方法构成,这里分析一下service这个方法 Servlet接口中定义了一个service()方法,而我们一般是使用HttpServ ...
- Servlet学习记录
个人认为servlet属于一种控制程序,可以处理浏览器的请求并做出对应的回应.我们经常使用的是让一个类去继承HttpServlet,然后在doget或者dopost里面写东西. 目前我个人常在doge ...
- 我的Spring学习记录(五)
在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...
- Spring 学习记录8 初识XmlWebApplicationContext(2)
主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...
- HTTP学习记录
title: HTTP学习记录 toc: true date: 2018-09-21 20:40:48 HTTP协议,HyperText Transfer Protocol,超文本传输协议,是因特网上 ...
- 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题
Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...
- 学习记录-java基础部分(一)
学习记录-java基础部分(一) 参考:GitHub上的知名项目:javaGuide : https://github.com/Snailclimb/JavaGuide/blob/master/doc ...
随机推荐
- 自己写的C#三层代码生成器
思来想去用T4生成代码要学习它的语法,C#本身能很简单地生成txt文件,为啥不直接批量替换模板方式自己写个的三层代码生成器.说干就干,2个小时搞定.当然各层还可以做的更精细,比如DAL层的Add方法I ...
- java数据结构之链表(java核心卷Ⅰ读书笔记)
1.链表 数组和ArrayList的一个重大缺陷就是:从中间位置删除一个元素要付出很大的代价,因为在这个元素删除之后,所有的元素都要向前端移动,在中间的某个位置插入一个元素也是这个原因. (小感悟:s ...
- 多个字符串有相同的hashcode(没见到大于8的时候转成红黑树)
public static void main(String[] a){ byte[] b1 = {33 , 123 ,124}; byte[] b2 = {33 , 124 , 93}; byte[ ...
- day04 迭代器&生成器&装饰器
目录 1.迭代器 2.生成器 3.推导式 4.匿名函数 5.内置函数 6.递归 7.闭包 8.装饰器 一.迭代器 特点: 1. 省内存 2. 只能向前. 不能反复 3. 惰性机制 让不同的数据类型 ...
- form表单提交数据,页面必定会刷新,ajax提交数据不会刷新,做到悄悄提交,多选删除,ajax提交实例
很多页面用到的模态对话框,如知明网站https://dig.chouti.com/的登录页都是模态对话框, 当点登录时,是用的ajax提交,因为输入错了信息,有返回消息,而页面没有刷新. jquery ...
- [蓝桥杯]PREV-27.历届试题_蚂蚁感冒
问题描述 长100厘米的细长直杆子上有n只蚂蚁.它们的头有的朝左,有的朝右. 每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒. 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行. 这些蚂蚁中,有1只蚂 ...
- Linux 调试打印时间和颜色
Linux调试打印时间和颜色 #include <sys/time.h> #include <unistd.h> void print_time(void) { struct ...
- python之路——23
复习 1.类定义 函数--方法--动态属性 必须传self 变量--类属性--静态属性 __init__方法--初始化方法2.实例化 1.使用:对象 = 类() 2.实例和对象没有区别 3.对象调用方 ...
- vscode中使用beautify插件格式化vue文件
1.点击设置,找到beautify.language并在html一栏里加上vue "beautify.language": { "js": { "ty ...
- WPF 播放声音 百度文字转声音
https://developer.baidu.com/vcast google浏览器可下载 https://www.cnblogs.com/maruko/archive/2013/04/19/WP ...