上篇说了需要重写doPost和doGet方法以处理相应的请求,那么这两个方法具体是如何处理请求并将结果返回给浏览器呢?
public class OneServlet extends HttpServlet {
public OneServlet() {
System.out.println("OneServlet 实例对象被创建!");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("OneServlet doGet is running");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
注意到在这两个方法中都有HttpServletResponse 和 HttpServletRequest 接口,因此要了解这两个接口。
先看HttpServletResponse :
测试代码:
public class OneServlet extends HttpServlet {
public OneServlet() {
System.out.println("OneServlet 实例对象被创建!");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "Hello!"; // 执行结果
PrintWriter writer = resp.getWriter(); // 从Tomcat拿到输出流
writer.write(res); // 通过输出流将结果以二进制形式写入到响应体
} // doGet执行完毕后,Tomcat将相应包推送给浏览器
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
运行服务器后,输入http://localhost:8080/myWeb/one,可以看到:
说明测试成功。
但如果我们把输出的字符串换成整型:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "Hello!"; // 执行结果
int money = 50;
PrintWriter writer = resp.getWriter(); // 从Tomcat拿到输出流
writer.write(money); // 通过输出流将结果以二进制形式写入到响应体
} // doGet执行完毕后,Tomcat将相应包推送给浏览器
那么浏览器得到的结果是:
并不是想要的结果50,原因见下图,即write方法会将整型转换为对应的ascii码写入到响应体中,要想避免这个问题就要用print(常用)。
再看如下代码,我们想把三门语言分三行输出:
public class ThreeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "java<br/>python<br/>c#"; // 我们想用<br/>标签将三门语言分行显示
PrintWriter writer = resp.getWriter();
writer.print(res);
}
}
看一下结果,明显不是我们想要的:
浏览器将收到的内容都当作了字符串,并没有识别出html标签。
在响应包中有一个属性:content-type,通过这个,浏览器可以用相应的编译器对二进制流进行编译。在默认的情况下,content-type的值为text,即浏览器会用文本编译器对二进制数据进行解析,所以才无法识别出html:
如何更改content-type呢:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "java<br/>python<br/>c#";
// 在获取输出流之前设置ContentType
resp.setContentType("test/html"); // 告诉浏览器用text和html编译器进行解析,当遇见<br/>时,html标签会将它识别出来。
PrintWriter writer = resp.getWriter();
writer.print(res);
}
注意,在测试时并没有出现想要的结果,而是自动下载了一个文件…,打开文件后正是"java<br/>python<br/>c#",原因竟是我把resp.setContentType(“test/html”);中的text写成了test…,修改后代码如下:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "java<br/>python<br/>c#";
// 在获取输出流之前设置ContentType
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.print(res);
}
运行结果:
下面接着输出一些东西:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "java<br/>python<br/>c#";
String res2 = "人类简史<br/>金雀花王朝<br/>";
// 在获取输出流之前设置ContentType
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.print(res);
writer.print(res2);
}
结果:
我们发现res2的输出结果是一堆问号。
对于文字内容,浏览器是通过响应头中context-type中的charset来解析的,默认是ISO-8859-1,它是不能解析中文的,因此要将其改成utf-8:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String res = "java<br/>python<br/>c#";
String res2 = "人类简史<br/>金雀花王朝<br/>";
// 在获取输出流之前设置ContentType
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.print(res);
writer.print(res2);
}
下面来看看响应头中location属性:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String url = "http://www.baidu.com";
resp.sendRedirect(url); // 相当于在响应头中添加location属性,其值为http://www.baidu.com
}
访问此servlet后,浏览器会收到相应包,如果发现里面有location这个属性,那么他将自动通过 地址栏 向location中指定的网站发送请求(通过地址栏访问为get方式)。
当访问此servlet时,会跳转到百度,此时在servlet的响应头中能看到location属性:
此外,要想让其带有参数访问,则只需加个?username=xxx即可:
String url = "http://www.baidu.com?username=lll";
结果:
总结:
- 将执行结果以二进制写到响应体中
- 修改content-type属性值,告诉浏览器用什么编译器解析二进制数据,(还有charset,用于解析中文)
- 设置location属性,控制浏览器向指定的服务器发送请求。