1.Servlet的参数可以在web.xml中通过init-param元素来配置
2.参数的读取需要借助ServletConfig对象(该对象由容器创建)
3.每一个Servlet都有对应的ServletConfig对象,彼此间不共享
由于Servlet对象在内存中有一个,所有定义Servlet的实例变量,在用户访问时会有线程竞争问题。
解决办法:
1.同步处理。(不建议使用)
2.搞出多个Servlet实例。(不建议使用)
SingleThreadModel接口:如果某个Servlet实现了该接口,容器有可能会采用1或2的方式来应对。(不同服务器实现不同)
Tomcat是采取了2方案。废弃的接口
3、原则:尽量把变量定义为局部变量。对于没法定义为局部变量的变量,应做同步处理,但同步代码块应尽可能的小。
使用ServletConfig可以获取WEB-INF 配置文件init-param里面的值(非全局,只能获取当前Servlet里面的配置数据);
1.获取指定参数名字的值
//注意:init-param只能放在servlet-class配置标签后面
String value = getServletConfig().getInitParameter("ppp");
2.获取所有参数名字
//获取顺序:按自然排序获取名字
Enumeration names= getServletConfig()
.getInitParameterNames();
while(names.hasMoreElements()){
String name =(String) names.nextElement();
}
1、ServletContext概念
应用活多长,ServletContext对象就活多长(生命周期)
容器在加载应用时就会创建ServletContext对象,它代表当前JavaWeb应用(全局)。
本身是一个域对象:该对象内部维护了一个Map
访问域对象数据的方法:
ObjectgetAttribute(String name):通过名称获取对象。
voidsetAttribute(String name,Object obj):忘Map中塞一个对象。name在 Map中不存在是添加,存在是替换
voidremove(String name)
getAttributeNames():获取Map中的所有key值
2、作用
1、实现各个Servlet间的数据共享。(数据共享)
2、获取应用的全局参数配置(参数配置)
在web.xml里面配置
3、 从web-xml配置文件中获得值的方法:
//这个getServletContext方法在GenericServlet类中
String value = getServletContext().getInitParameter("name");
1、ServletContext的getRealPath(Stringpath):根据path获取绝对路径。path必须以/ 开始,相对于当前应用的绝对路径
特点:用户JavaWeb环境下,JavaWeb环境下可以读取到当前应用中的任何资 源。
2、ResourceBundle:构造实例时,传入基名。(国际化的类)
特点:可以用在非web环境下,只能读取properties的资源文件;只能加载类 路径下的资源文件;
3、ClassLoader:
特点:可以用在非web环境下,只能加载类路径下的资源文件;读取类路径 下的所有资源文件。
具体实例代码:
1.ServletContext读取类路径下的property资源文件
Stringpath = getServletContext().getRealPath
("/WEB-INF/classes/com/itheima/servlet/db11.properties");
Properties pro = new Properties();
pro.load(new FileInputStream(path));
String value = pro.getProperty("url");
2.用ResourceBundle读取资源文件
//注意ResourceBundel的路径,没有/,没有后缀名,因为他知道是Properties文件,
//并且把Properties当成类的读取方式来读取(如果有包,包名用.分隔),具体如下
ResourceBundle rb = ResourceBundle.getBundle
("com.itheima.servlet.db11");
String value = rb.getString("url");
3.用类加载器的URL类读取资源文件
ClassLoader cl = MyServlet3.class.getClassLoader();
//以相对路径的方法来读取文件
//如果路径中有空格,tomcat就会把空格翻译为%20,就会出错,这就是为什么安装
//时为什么不能有空格路径
URL url = cl.getResource
("com/itheima/servlet/db11.properties");
//url的getPath方法获取的是绝对路径
String path = url.getPath();
Properties pro = new Properties();
pro.load(new FileInputStream(path));
String value = pro.getProperty("url");
4.用类加载器的getResourceAsStream方法读取资源文件(获取资源的比较常用的方法)
ClassLoader cl = MyServlet3.class.getClassLoader();
//调用ResourceAsStream(以流的形式拿出资源);
InputStream fis = cl.getResourceAsStream
("com/itheima/servlet/db11.properties");
Properties pro = new Properties();
pro.load(fis);
String value = pro.getProperty("url");
字节流输出中文数据的乱码问题
使用response.getOutputStream()获得字节流。
sendRedirect是在httpServletResponse这个接口定义的,不是在ServletResponse定义的
字节流以UTF-8编码输出中文数据getBytes("UTF-8"),而浏览器用默认编码(GBK)解码,这时就会有乱码
解决:
1.浏览器选择“查看”菜单选择UTF-8,解决乱码问题。(不可取)
2.指示浏览器查看码表.response.setHeader("Content-Type","text/html;charset=UTF-8");
3.向客户端收到的html内容中增加标记:
4.发送时用Reponse. setCharacterEncoding(“utf-8”)
5、调用response.setContentType("text/html;charset=UTF-8"):告知客户端使用的编码
Tips: GBK包含ascll码
获取Servlet字符输出流方法response.getWriter():
Servlet的字符输出流输出时查的码表为iso-8859-1(Servlet规范指定的)
字符流和字节流互斥。在同一个Servlet中,只能用其中的一个流。
容器会自动关闭response开启的流。
字符流乱码解决办法:
两步:
1.设置输出字符数据时查的码表:response.setCharacterEncoding(“utf-8”)
2.通知客户端以什么码表进行解码。
response.setHeader(“Content-type”,”text/html;charset=utf-8”)
response.setContentType("text/html;charset=UTF-8")能提供上述两步功能(字符流)。
所以使用字符流时调用setContentType()方法能轻松解决乱码问题
1.常用的方法
request.getRequestURL()//获取请求url地址:http://localhost:8080/day05/servlet/RequestDemo1
request.getRequestURI()//获取请求的资源地址:/day05/servlet/RequestDemo1
request.getQueryString()//get方式的数据:username=admin&password=123
request.getRemoteAddr()//客户端的IP地址
request.getRemoteHost()//客户端的主机名称
request.getRemotePort()//客户端的端口号 1024~65535之间的任意一个没有被占用的端口
request.getMethod()//请求方式:get或post
request.getContextPath()// 当前应用的名称 /day05
2.获取请求头的值
//获取所有的请求头名称和值
privatevoid test3(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
Enumeration enumers = request.getHeaderNames();
while(enumers.hasMoreElements()){
StringheaderName = (String)enumers.nextElement();
System.out.println(headerName+"="+request.getHeader(headerName));
}
}
//获取重名头的值
privatevoid test2(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
Enumerationenumers = request.getHeaders("Accept-Encoding");
while(enumers.hasMoreElements()){
Stringvalue = (String)enumers.nextElement();
System.out.println(value);
}
}
//获取单一的头
privatevoid test1(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
String value =request.getHeader("Accept-Encoding");
System.out.println(value);
}
3.获取正文所有内容
//方法:请求的输入流
OutputStream out = response.getOutputStream();
InputStream is = request.getInputStream();
int length = -1;
byte[] by =new byte[1024];
while((length=is.read(by))!=-1){
out.write(by,0,length);
}
4.封装javaBean
//将页面数据封装到JavaBean中:利用BeanUtils框架(需要jar包)
User user = new User();
//注意事项!这里的map的value值是String[]类型,因为同一个名字可以有多个值
Map
BeanUtils.populate(user, map);
//将页面数据封装到JavaBean中(第一种)
User user = new User();
//获得页面所有属性的名字
Enumeration
while(names.hasMoreElements()){
String name =names.nextElement();
String value =request.getParameter(name);
//获得属性描述器,内省
PropertyDescriptorpd = new
PropertyDescriptor(name,User.class);
Method method = pd.getWriteMethod();
method.invoke(user, value);
}
//将页面数据封装到JavaBean中(第二种)
User user = new User();
//获取页面所有属性的Map
Map
//注意事项!这里的map的value值是String[]类型,因为同一个名字可以有多个值
for(Map.Entry
String name = entry.getKey();
String[] value = entry.getValue();
PropertyDescriptor pd = new
PropertyDescriptor(name,User.class);
Method method = pd.getWriteMethod();
method.invoke(user, value);
}
doGet(){
//获取图片绝对路径
String path = getServletContext().getRealPath("/美女.jpg");
//获取图片名绝对路径名称:G:xxx\xxx\美女.jpg
String name = path.substring(path.lastIndexOf("\\")+1);
FileInputStream fis = new FileInputStream(path);
//如果显示图片,就需要设置Content-Type为application/octet-stream
response.setHeader("Content-Type","application/octet-stream");
响应消息头要遵循html的规则,必须把不安全的东西重新编码(加密变成安全字符集里面
的字符),因为中文也为不安全的字符集,所以就需要使用URLEncoder类把String类型变成application/x-www-form-urlencoded型(表单默认类型,安全字符集),如果不重新编码,就会有中文乱码问题
下载文件是浏览器会自动帮你对安全字符集解码
response.setHeader
("Content-Disposition","attachment;filename="
+URLEncoder.encode(name),"utf-8"));
int length = - 1;
byte[] b =new byte[1024];
while((length =fis.read(b))!=-1){
response.getOutputStream().write(b,0,length);
}
}