一、Servlet规范中核心接口和类的类图
二、HttpServletResponse
1、使用字节流输出中文数据
response.getOutputStream().write("中国".getBytes("UTF-8"));
浏览器会采用本地默认编码解码,会出现乱码问题。
解决办法:
a、更改浏览器的编码(不可取)
b、response.setHeader("Content-Type", "text/html;charset=UTF-8");//通知浏览器以UTF-8进行解码
c、response.getOutputStream().write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes("UTF-8"));
response.getOutputStream().write(data.getBytes("UTF-8"));
d、response.setContentType("text/html;charset=UTF-8");作用等同b的作用
//b、通知浏览器以utf-8进行编码 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "这是要输出的中文"; response.setHeader("Content-Type", "text/html;charset=utf-8"); response.getOutputStream().write(data.getBytes("utf-8")); }
//c、response.getOutputStream().write("<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>".getBytes("UTF-8")); public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "这是要输出的中文"; //此处响应的信息全部是英文,所以不会出现乱码问题;通知浏览器以utf-8进行解码 response.getOutputStream().write( "<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>" .getBytes("UTF-8")); response.getOutputStream().write(data.getBytes("utf-8")); }
//response.setContentType("text/html;charset=utf-8");作用等同于b public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "这是要输出的中文"; response.setContentType("text/html;charset=utf-8"); response.getOutputStream().write(data.getBytes("utf-8")); }
2、使用字符流输出中文数据
PrintWriter out = response.getWriter();默认输出字符时查 ISO-8859-1码表,可以通过response.setCharacterEncoding("UTF-8")更改它查询的码表
输出中文时,不要忘记通知客户端解码的码表。
response.setContentType("text/html;charset=UTF-8"):有两个作用
a、通知输出字符流查UTF-8码表
b、告知客户端查UTF-8进行解码
//使用字符流输出中文及乱码问题,通过setCharacterEncoding方法更改输出流查询的码表 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "这里是中文显示"; //使用PrintWriter,默认使用ISO-8859-1进行编码,而ISO-8859-1不支持中文显示 //这里通知输出流使用utf-8进行编码 response.setCharacterEncoding("utf-8"); //这里通知浏览器使用utf-8进行解码 response.setHeader("Content-Type", "text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.write(data); }
// 使用字符流输出中文及乱码问题 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "这里是中文显示"; // 使用PrintWriter,默认使用ISO-8859-1进行编码,而ISO-8859-1不支持中文显示 response.setContentType("text/html;charset=utf-8");// 有两个作用 // a、通知输出字符流查UTF-8码表 // b、告知客户端查UTF-8进行解码 PrintWriter writer = response.getWriter(); writer.write(data); }
总结:
response.setContentType:
字节流:只通知客户端解码码表
字符流:输出时查的码表;通知客户端解码码表
三、HttpServletResponse应用案例
1、文件下载:中文文件名的下载
//中文文件名文件的下载 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取资源路径 String path = getServletContext().getRealPath("/蒂法.jpg"); System.out.println(path); //构建输入流 InputStream in = new FileInputStream(path); //获得文件名 String filename = path.substring(path.lastIndexOf("\\")+1); //通知客户端以下载文件方式打开 response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename, "utf-8")); //构建输出流 OutputStream out = response.getOutputStream(); //输出模板 byte[] buf = new byte[1024]; int len = -1; while((len = in.read(buf))!= -1){ out.write(buf,0,len); } out.close(); in.close(); }
2、生成随机验证码图片
private static int WIDTH = 120; private static int HEIGHT = 25; //生成随机验证码图片 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //此处控制该页面不缓存 response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); //获取内存中的画布 BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); //获得画笔 Graphics g = image.getGraphics(); //画边框 g.setColor(Color.GRAY); g.drawRect(0, 0, WIDTH, HEIGHT); //填充背景色 g.setColor(Color.YELLOW); g.fillRect(1, 1, WIDTH-2, HEIGHT-2); //画干扰线 g.setColor(Color.GREEN); Random r = new Random(); for(int i=0;i<9;i++) g.drawLine(r.nextInt(WIDTH), r.nextInt(HEIGHT), r.nextInt(WIDTH), r.nextInt(HEIGHT)); //画数字(字符串形式) g.setColor(Color.RED); g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 20)); int x = 20; for (int i = 0; i < 4; i++) { String num = r.nextInt(10) + ""; g.drawString(num, x, 20); x += 20; } //输出图片 ImageIO.write(image, "jpeg", response.getOutputStream()); }
效果图:
3、定时刷新
//定时刷新 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.setHeader("Refresh", "3;URL=/review_day05/index.html"); response.getOutputStream().write("页面正在跳转中,请稍后...如果5秒内没有反应,请点击<a href='/day05/index.html'>这里</a>".getBytes("utf-8")); }
4、控制静态资源的缓存时间
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "控制缓存时间"; //此处控制缓存的持续时间 response.setDateHeader("Expires", System.currentTimeMillis()+1*60*60*1000); response.getOutputStream().write(data.getBytes()); }
四、HttpServletResponse的一些细节
1、在同一个Servlet中,response的字节流和字符流互斥。
2、response通过字节流或字符流输出的数据不是直接打给浏览器的,是存在自己的缓存中了。
3、response使用的字节流和字符流不用手工关闭。
五、HttpServletRequest
1、请求头的获取
public class RequestDemo1 extends HttpServlet { // 获取请求头 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter out = response.getWriter(); // 返回客户端发出请求时的完整URL String url = request.getRequestURL().toString(); // 返回请求行中的资源名部分 String uri = request.getRequestURI(); // 返回请求行中的参数部分 String queryString = request.getQueryString(); // 返回发出请求的客户机的IP地址 String remoteAddr = request.getRemoteAddr(); // 返回发出请求的客户机的完整主机名 String remoteHost = request.getRemoteHost(); // 返回客户机所使用的网络端口号 int port = request.getRemotePort(); // 返回WEB服务器的IP地址 String localAddr = request.getLocalAddr(); // 返回WEB服务器的主机名 String localName = request.getLocalName(); // 得到客户机请求方式 String requestMethod = request.getMethod(); out.write("url=" + url + "<br/>"); out.write("uri=" + uri + "<br/>"); out.write("queryString=" + queryString + "<br/>"); out.write("remoteAddr=" + remoteAddr + "<br/>"); out.write("remoteHost=" + remoteHost + "<br/>"); out.write("port=" + port + "<br/>"); out.write("localAddr=" + localAddr + "<br/>"); out.write("localName=" + localName + "<br/>"); out.write("requestMethod=" + requestMethod + "<br/>"); }
2、请求参数的获取(内省;BeanUtils框架基本使用)
//请求参数的获取 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { OutputStream out = response.getOutputStream(); out.write("----------获取指定名称的头值-----------<br/>".getBytes()); String value = request.getHeader("Accept-Encoding"); out.write((value+"<br/>").getBytes()); out.write("----------获取所有的头和值-----------<br/>".getBytes()); Enumeration<String> e = request.getHeaderNames(); while(e.hasMoreElements()){ String name = e.nextElement(); out.write((request.getHeader(name)+"<br/>").getBytes()); } out.write("----------获取同名的头和值-----------<br/>".getBytes()); e = request.getHeaders("Accept-Encoding"); while(e.hasMoreElements()){ value = e.nextElement(); out.write((value+"<br/>").getBytes()); } }
3、各种表单输入域的获取
表单:type是radio或checkbox,即使页面有对应名称的选择项,只要一个都不选,什么值都不会传递给服务器,是null
如果选了其中的任何一个选项,则把该项的value的取值传递给服务器。如果根本没有value属性,则传递on给服务器。
//post请求参数的获取及乱码处理 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 告知服务器程序,请求中的参数值的编码是什么: // request.setCharacterEncoding("UTF-8"),但,该方法只适用于POST请求方式。 request.setCharacterEncoding("utf-8"); User user = null; response.getOutputStream().write( "获取请求参数的值,get和post方法通用<br/>".getBytes()); // 这里能够获取多个同名的请求参数,如果只有一个参数,则String数组中只存一个元素;否则,多个元素 String[] username = request.getParameterValues("username"); String password = request.getParameter("password"); String code = request.getParameter("code"); response.getOutputStream().write(("封装前:" + user + "<br/>").getBytes()); user = new User(username, password, code); response.getOutputStream().write(("封装后:" + user + "<br/>").getBytes()); }
//get请求参数的获取及乱码处理 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // GET请求方式:客户端发送的数据都是ISO-8859-1,需要重新编码 User user = null; response.getOutputStream().write( "获取请求参数的值,get和post方法通用<br/>".getBytes()); // 这里能够获取多个同名的请求参数,如果只有一个参数,则String数组中只存一个元素;否则,多个元素 String[] username = request.getParameterValues("username"); String password = request.getParameter("password"); String code = request.getParameter("code"); response.getOutputStream().write(("封装前:" + user + "<br/>").getBytes()); user = new User(username, password, code); byte[] b = (user + "").getBytes("ISO-8859-1");// 客户端传递过来的字节数组 String str = new String(b, "utf-8"); System.out.println(str); response.getOutputStream().write(str.getBytes()); }
//使用BeanUtils框架获取表单域 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Student s= new Student(); try { BeanUtils.populate(s, request.getParameterMap()); } catch (Exception e) { e.printStackTrace(); } response.getOutputStream().write((s+"").getBytes()); }
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>student</title> </head> <body> <form action="/review_day05/servlet/RequestDemo3" method="post"> 姓名:<input type="text" name="username"/><br/> 密码:<input type="password" name="password"/><br/> 性别:<input type="radio" name="gender" value="1" checked="checked"/>男 <input type="radio" name="gender" value="0"/>女<br/> 婚否:<input type="checkbox"/><br/> 爱好:<input type="checkbox" name="hobby" value="eat"/>吃饭 <input type="checkbox" name="hobby" value="sleep"/>睡觉 <input type="checkbox" name="hobby" value="dota"/>打DOTA <br/> 家乡:<select name="city"> <option value="DY">东营</option> <option value="JN">济南</option> <option value="QD">青岛</option> </select><br/> 简介:<textarea rows="3" cols="40" name="description"></textarea><br/> <input type="hidden" name="id" value="100"/> <input type="submit" value="提交"><br/> </form> </body> </html>
请求参数值的中文乱码问题:
浏览器当前使用什么编码,就以什么编码发送数据。
浏览器什么什么编码,是根据访问的资源而定。建议统一用UTF-8
告知服务器程序,请求中的参数值的编码是什么:request.setCharacterEncoding("UTF-8"),但,该方法只适用于POST请求方式。
GET请求方式:客户端发送的数据都是ISO-8859-1,需要重新编码
new String(name.getBytes("ISO-8859-1"),"UTF-8");