一.servlet的生命周期
-
相关的方法:init,service,destroy
-
Servlet在第一次被访问时会实例化,那么就会执行Servlet中的init方法(只会执行一次).
-
从客户端发送来的请求,就会执行Servlet中的service方法(在service方法的内部根据请求的方式不同调用不同doXXX方法)
-
当Servlet从服务器中移除或者服务器关闭的时候Servlet对象被销毁,此时执行destroy方法
测试代码:
public class SaveTime implements Servlet {
@Override
public void destroy() {
System.out.println("我是销毁");
}
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("这是初始化");
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
System.out.println("这是运行");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
二.设置在启动时加载
-
为什么使用:
因为Servlet对象是在第一次被访问的时候被创建的,init方法执行,假设在init方法中做了一些比较耗时的操作(比如:加载了一些配置文件并且解析可能需要花费3秒钟),就会使得第一次访问这个Servlet需要等待.
-
启动加载:
通过一个配置将Servlet的实例化的过程放在服务器启动的时候(让服务器启动的时候创建Servlet的对象) -
示例代码:
<servlet>
<servlet-name>SaveTime</servlet-name>
<servlet-class>com.itheima.demo01.SaveTime</servlet-class>
<load-on-startup>2</load-on-startup>
<!--中间的参数是优先级,不能写1,因为默认的配置文件加载的优先级是1-->
</servlet>
<servlet-mapping>
<servlet-name>SaveTime</servlet-name>
<url-pattern>/SaveTime</url-pattern>
</servlet-mapping>
三.Servlet的访问路径的配置
- 匹配方式
<url-pattern></url-pattern>
完全路径匹配:以 / 开始 示例:/SaveTime
目录匹配:以 / 开始,以 /*结束 示例:/* 、/aaa/*、/aaa/bbb/*
扩展名匹配:以*开始 示例:*.action
- 优先级:完全路径匹配 > 目录匹配 > 扩展名匹配
四.ServletConfig对象
- 主要的功能:
getInitParameter或者getInitParameterNames: 都可以获得Servlet的初始化参数
getServletContext: 获得ServletContext对象
getServletName: 获得Servlet的名称
代码:
初始化配置:
<servlet>
<servlet-name>ServletConfigTest</servlet-name>
<servlet-class>com.itheima.demo01.ServletConfigTest</servlet-class>
<!-- 配置初始化参数 -->
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
实现代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获得ServletConfig对象
ServletConfig config = this.getServletConfig();
//调用getServletName方法,返回实例的名称
String servletName = config.getServletName();
System.out.println(servletName);
//使用ServletConfig的getInitParameter方法,得到配置文件中的初始化内容
String parameter = config.getInitParameter("username");
String initParameter = config.getInitParameter("password");
System.out.println("账号:"+parameter);
System.out.println("密码:"+initParameter);
//获得所有初始化参数的名称
Enumeration<String> initParameterNames = config.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String string = (String) initParameterNames.nextElement();
System.out.println(config.getInitParameter(string));
}
}
五.ServletContext对象
- 注意
ServletContext: Servlet的上下文对象,ServletContext对象对Servlet之前和之后的内容都知道。这个对象一个web项目只有一个。在服务器启动的时候为每个web项目创建一个单独的ServletContext对象。 - 作用:
1. 用来获取web项目信息
getMimeType:获取文件的MIME类型
getContextPath:获取web项目请求工程名
2.读取web项目下的文件
在使用传统的IO流读取文件会出现问题,找不到,原因:路径中使用的是相对路径,相对的是JRE环境 - 代码实现:
public class ServletContentTest02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//传统的io流,不可以使用
methon01();
//这种方法可以调用方法获取输入流
method02();
Properties properties = new Properties();
//创建ServletContext对象
ServletContext servletContext = this.getServletContext();
//调用getRealPath方法,获取文件直接路径
String realPath = servletContext.getRealPath("/WEB-INF/classes/db.properties");
//使用properties的load方法来加载一个文件输入流,可以直接拿到数据
properties.load(new FileInputStream(realPath));
//从properties中获取key相应的value
String driverClassName = properties.getProperty("driverClassName");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClassName);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
//这种方法可以调用方法获取输入流
public void method02() throws IOException {
Properties properties = new Properties();
ServletContext servletContext = this.getServletContext();
//调用getResourceAsStream方法获取输入流
InputStream resourceAsStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
properties.load(resourceAsStream);
String driverClassName = properties.getProperty("driverClassName");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClassName);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
//传统的io流,不可以使用
public void methon01() throws IOException, FileNotFoundException {
Properties properties = new Properties();
properties.load(new FileInputStream("src.db.properties"));
String driverClassName = properties.getProperty("driverClassName");
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(driverClassName);
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.ServletContext对象之作为域对象存取数据
域对象:指的是将数据存入到域对象中,这个数据就会有一定的作用范围。域指的是一定的作用范围。
范围:整个web应用。
实现:getAttribute()获取域对象的值
public class ServletContentTest03 extends HttpServlet {
@Override
public void init() throws ServletException {
this.getServletContext().setAttribute("username", "小乔");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object attribute = this.getServletContext().getAttribute("username");
System.out.println(attribute);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
六.Response
从浏览器输入一个地址访问服务器(将这个过程称为是请求)。服务器接收到请求,需要进行处理,处理以后需要将处理结果显示回浏览器端(将这个过程称为是响应)。
响应行:
//设置状态码,响应行
response.setStatus(400);
//设置响应头:一个key对应一个value
response.setHeader("content-Type", "text/plain");
//添加:一个key对应多个value
response.addHeader("content-Type", "text/html");
//重定向(括号里写入的是将要跳转的路径)
response.sendRedirect("");
七.Request
主要方法:见代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求方式:"+request.getMethod());
System.out.println("客户机ip地址:"+request.getRemoteAddr());
System.out.println("请求参数的字符串:"+request.getQueryString());
System.out.println("请求路径的URL:"+request.getRequestURI());
System.out.println("请求路径的URL:"+request.getRequestURL());
// 获得请求头的信息
System.out.println("获得客户机浏览器类型:"+request.getHeader("User-Agent"));
}
使用request来获取表单提交信息:
表单:
<body>
<form action="RequestTest02" method="get" >
账号:<input type="text" name="username" />
密码:<input type="password" name = password>
<input type="radio" name="sex" value="man" />男
<input type="radio" name="sex" value="woman"/>女
<input type="checkbox" name="like" value="swim"/>游泳
<input type="checkbox" name="like" value="palycomputer"/>玩电脑
<input type="checkbox" name = "like" value="char"/>聊天
籍贯:<select name="city">
<option value="beijing">北京市</option>
<option value="shanghai">上海市</option>
<option value="shenzhen">广州市</option>
</select><br/>
自我介绍:<textarea name="info"></textarea><br/>
<input type="submit" value="登陆"/>
</form>
</body>
Servlet中:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取表单提交的信息
String username = request.getParameter("username");
String password = request.getParameter("password");
String sex = request.getParameter("sex");
String city = request.getParameter("city");
//获取多个值
String[] hobby = request.getParameterValues("like");
String info = request.getParameter("info");
System.out.println("用户名:"+username);
System.out.println("密码:"+password);
System.out.println("性别:"+sex);
System.out.println("籍贯:"+city);
System.out.println("爱好:"+Arrays.toString(hobby));
System.out.println("自我介绍:"+info);
}
八.乱码问题
Response
对象响应的中文乱码处理
- 使用字节流响应中文
产生的原因:
其实这个乱码的产生与中文转成字节数组及浏览器打开方式(打开的时候采用的默认字符集)有关
解决:
将中文转成字节数组的时候和浏览器默认打开的时候采用的字符集一致即可。
乱码处理:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//使用字节流输出
ServletOutputStream outputStream = response.getOutputStream();
//设置浏览器默认打开的时候采用的字符集
response.setHeader("Content-Type", "text/html;charset=UTF-8");
//设置中文转换成字节数组,然后输出
outputStream.write("哈哈".getBytes("UTF-8"));
}
- 使用字符流响应中文
原因:
字符流是有缓冲区的,response获得字符流,response设计默认的缓冲区编码是ISO-8859-1。这个字符集不支持中文的。
解决:
设置response获得字符流缓冲区的编码和设置浏览器默认打开时候采用的字符集一致即可。
符集一致即可。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置浏览器默认打开的时候采用的字符集
response.setHeader("Content-Type", "text/html;charset=UTF-8");
//设置response获得字符流缓冲区的编码
response.setCharacterEncoding("UTF-8");
response.getWriter().print("哈哈");
}
字符流向页面响应中文,有一种简化的方式:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//简化
response.setContentType("text/html;charset=UTF-8");
response.getWriter().print("哈哈");
}
Request
对象接收表单请求参数的中文乱码处理
具体的原因和解决办法,见代码注释:
public class Demo06 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//产生乱码原因:
//get方法在提交数据会拼接在请求行的url之后,在这里就已经进行了一次编码
//解决:
//将存在request缓冲区中的数据按照ISO-8859-1的方式获取到,再使用UTF-8的方式进行解码
String parameter = request.getParameter("username");
//编码
String encode = URLEncoder.encode(parameter,"ISO-8859-1");
//解码
String decode = URLDecoder.decode(encode, "UTF-8");
//2.简化方式,一句搞定
String string = new String(parameter.getBytes("ISO-8859-1"), "UTF-8");
System.out.println(string);
System.out.println(decode);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//产生乱码原因:
//post方式提交的数据是放在请求体中,request对象接收到数据后,放入request的缓冲区中,缓冲区中有编码(默认的是ISO-8859-1:不支持中文)
//解决:
//只需要更改缓冲区的编码就可以了
//设置缓冲区的编码
request.setCharacterEncoding("UTF-8");
String parameter = request.getParameter("username");
System.out.println(parameter);
}
}