JavaWeb -- 服务器传递给Servlet的对象 -- ServletConfig, ServletContext,Request, Response
1. ServletConfig
有一些东西不合适在程序中写死,应该写在web.xml中,比如 文字怎么显示, 访问数据库名 和 密码, servlet要读取的配置文件 等等。。
<servlet> <servlet-name>Test</servlet-name> <servlet-class>com.kevin.Test</servlet-class> <init-param> <param-name>data1</param-name> <param-value>data11.log</param-value> </init-param> <init-param> <param-name>data2</param-name> <param-value>data2.log</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Test</servlet-name> <url-pattern>/Test2</url-pattern> </servlet-mapping>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String servletConfig1 = this.getServletConfig().getInitParameter("data1");//获取指定名的参数 response.getOutputStream().write(("WebTest2.Test " + servletConfig1).getBytes()); Enumeration<String> e = this.getServletConfig().getInitParameterNames(); //获取所有参数名 while(e.hasMoreElements()) //获取所有参数 { String name = (String) e.nextElement(); String data = this.getServletConfig().getInitParameter(name); response.getOutputStream().write((" "+data).getBytes()); } }
2. ServletContext: 服务已启动就会对应每个Web应用产生一个ServletContext, 停服务器才销毁对象。
应用:聊天室等
应用一: l多个Servlet通过ServletContext对象实现数据共享。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = "aaaa"; this.getServletContext().setAttribute("data1", data); //写入 }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = (String) this.getServletContext().getAttribute("data1"); //读取 response.getOutputStream().write(data.getBytes()); }
<context-param> <param-name>data2</param-name> <param-value>context-param in web.xml</param-value> </context-param>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = (String) this.getServletContext().getInitParameter("data2");//获取ServletContext参数 response.getOutputStream().write(data.getBytes()); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = "dataaaaaaaaa"; this.getServletContext().setAttribute("data3", data); //线程不安全。实际开发不能用 RequestDispatcher rd = this.getServletContext().getRequestDispatcher("/1.jsp"); //带数据请求转发jsp rd.forward(request, response); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //注意路径是对Tomcat服务器里面的资源,而不是Eclipse项目的资源显示 InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties"); //获取字节流 String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");//获取绝对路径,能获取到文件名 Properties props = new Properties(); props.load(in); String url = props.getProperty("URL"); String username = props.getProperty("username"); String password = props.getProperty("password"); response.getOutputStream().write((url + " " + username + " " + password).getBytes()); }
如果读取资源文件的程序不是Servlet的话,就只能用类装载器去读。
String path = UserDao.class.getClassLoader().getResource("db.properties").getpath();
通过类装载器的getResource()获得一个URL,再获得其绝对路径, 再通过普通的InputStream 读取文件。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //程序以什么码表输出,就要控制浏览器用什么码表显示 response.setHeader("Content-type", "text/html;charset=UTF-8"); String data = "中国人"; OutputStream out = response.getOutputStream(); out.write(data.getBytes("UTF-8")); }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setCharacterEncoding("UTF-8"); //控制response 以UTF-8编码 response.setHeader("content-type","text/html;charset=UTF-8"); //http头, 控制浏览器以UTF-8显示 String data = "中国"; PrintWriter out = response.getWriter(); out.write(data); }
控制文件下载
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String path = this.getServletContext().getRealPath("/download/apple.png"); String filename = path.substring(path.lastIndexOf("/")+1); //截取文件名 //System.out.println(filename); response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));//用URL防止中文文件名乱码问题 InputStream in = null; OutputStream out = null; try { in = new FileInputStream(path); out = response.getOutputStream(); int len = 0; byte[] buf = new byte[1024]; while( (len=in.read(buf)) > 0 ) { out.write(buf, 0, len); } } finally { try { in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } }
输出随机认证图片,防恶意注册
private static final int width = 120; private static final int height = 40; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = image.getGraphics(); setBackGround(g); setBorder(g); drawRandomLine(g); drawRandomNum((Graphics2D)g); response.setContentType("image/jpeg"); //设置头, 浏览器以图片方式打开 response.setDateHeader("expries", -1); //设置头, 不让浏览器缓存 response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); ImageIO.write(image, "jpg", response.getOutputStream()); } private void drawRandomNum(Graphics2D g) { //添加随机汉字 // TODO Auto-generated method stub //[\u4e00 ~ \u9fa5] g.setColor(Color.BLUE); g.setFont(new Font(null, Font.BOLD, 20)); String base = "\u7684\u4e00\u662f\u4e86\u6211\u4e0d\u4eba\u5728\u4ed6\u6709\u8fd9\u4e2a\u4e0a\u4eec\u6765"; int x = 5; for(int i=0; i<4; i++) { String ch = base.charAt(new Random().nextInt(base.length())) + ""; //System.out.println(ch); int degreen = new Random().nextInt()%30; g.rotate(degreen*Math.PI/180, x, 25); //翻转汉字 g.drawString(ch, x, 25); g.rotate(-degreen*Math.PI/180, x, 25); x += 30; } } private void drawRandomLine(Graphics g) { //加干扰线 // TODO Auto-generated method stub g.setColor(Color.green); for(int i=0; i<8; i++) { int x1 = new Random().nextInt(width); int y1 = new Random().nextInt(height); int x2 = new Random().nextInt(width); int y2 = new Random().nextInt(height); g.drawLine(x1, y1, x2, y2); } } private void setBorder(Graphics g) { //设置边框 // TODO Auto-generated method stub g.setColor(Color.blue); g.drawRect(1, 1, width-2, height-2); } private void setBackGround(Graphics g) { //设置背景颜色 // TODO Auto-generated method stub g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); }
Html调用上面的Servlet, 点击即可更换随机图片
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Insert title here</title> <script type="text/javascript"> function changeImage(img) { img.src = img.src + "?" + new Date().getTime(); } </script> </head> <body> <form action=""> <pre> User :<input type="text" name="username"/> <br /> Passwd :<input type="password" name="passwd"/> <br /> CheckCode:<input type="text" name="checkcode"/> <br /> <img src="Demo4" alt="ChangeOne" onclick="changeImage(this)" style="cursor: hand"/> </pre> </form> </body> </html>
注册完成后实现 几秒跳转,转发
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub test2(request, response); //实用 } private void test2(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //利用meta标签实现refresh, 跳转到jsp显示页面 String message = "<meta http-equiv='refresh' content='3;url=http://www.baidu.com'>" + "Register successfully!! Will goto .... <a href='http://www.baidu.com'>Clicked here!!</a></meta>"; this.getServletContext().setAttribute("message", message); this.getServletContext().getRequestDispatcher("/1.jsp").forward(request, response); //转发 } private void test1(HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); response.setHeader("refresh", "3;url=/WebTest2/1.jsp"); response.getWriter().write("Register successfully!! Will goto .... " + "<a href='http://www.baidu.com'>Clicked here!!</a>"); }
1.jsp
<body> <font color="red"> <% java.util.Date d = new java.util.Date(); %> <h1> Today's date is <%= d.toString() %> and this jsp page worked! </h1> <% String message = (String)application.getAttribute("message"); out.write(message); %> </font> </body>
上面的方法是转发, 注意和下面的重定向的区别
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub /* response.setStatus(302); //实用http响应头重定向 response.setHeader("location", "/WebTest2/1.html");*/ response.sendRedirect("/WebTest2/1.html"); //API方法重定向 }
控制缓存 // 缓存时间需要在当前时间的基础上添加。
response.addDateHeader("expires",System.currentTimeMillis() + 1000*3600);
Response要注意的一些细节:
4. Request
Request 常用方法
l获得客户机信息
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub test3(request); } private void test3(HttpServletRequest request) throws IOException { //获得客户机请求参数(客户端提交的数据) Enumeration<String> e = request.getParameterNames(); while(e.hasMoreElements()) { String name = e.nextElement(); String value = request.getParameter(name); System.out.println(name + "=" + value); } String[] values = request.getParameterValues("name"); for(int i=0; values!=null && i<values.length; i++) { if(!values[i].trim().equals("")) System.out.println("name=" + values[i]); } Map<String, String[]> map = request.getParameterMap(); User user = new User(); try { BeanUtils.populate(user, map); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } System.out.println(user.getPasswd()); } private void test2(HttpServletRequest request) { //获得客户机请求头 String headValue = request.getHeader("Accept-Language"); System.out.println(headValue); Enumeration<String> e = request.getHeaders("Accept-Language"); while(e.hasMoreElements()) { String value = e.nextElement(); System.out.println(value); } e = request.getHeaderNames(); while(e.hasMoreElements()) { String name = e.nextElement(); String value = request.getHeader(name); System.out.println(name + "=" + value); } } private void test1(HttpServletRequest request) { // 获得客户机信息 System.out.println(request.getRequestURI()); System.out.println(request.getRequestURL()); System.out.println(request.getQueryString()); System.out.println(request.getRemoteAddr()); System.out.println(request.getRemoteHost()); System.out.println(request.getRemotePort()); System.out.println(request.getMethod()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub System.out.println("+++++++++++++++++++"); InputStream in = request.getInputStream(); int len = 0; byte[] buf = new byte[1024]; while( (len=in.read(buf))>0 ) { System.out.println(new String(buf, 0, len)); } }
上面User类为 , 请求数据为 ....?name=kevin&name=xiang&passwd=123456
public class User { private String[] name; private String passwd; public String[] getName() { return name; } public void setName(String[] name) { this.name = name; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; } }
Request 请求中会夹带中文, 解决乱码问题
如果是Post方式提交的请求带中文参数,可以设置编码
//post方式提交 request.setCharacterEncoding("UTF-8"); System.out.println("post username=" + request.getParameter("username"));
如果是Get方式 或 超链接方式 提交的请求带中文参数, 只能手动转码
String name = request.getParameter("username"); //Get方式提交 name = new String(name.getBytes("iso8859-1"), "UTF-8"); System.out.println("get name=" + name);
Request请求转发
和ServletContext一样Request 也可以做到请求转发,而且更实用,由于Request域不同于ServletContext域,每个请求都会有一个Request,所以用setAttribute()方法传递数据,不会有线程安全问题,具有实用性。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String data = "xxxxxx"; request.setAttribute("data", data); request.getRequestDispatcher("/1.jsp").forward(request, response);//请求转发 }
5. Web工程中各种地址的写法
首先“/” 加斜杠, 看地址使用的对象是谁。如果是服务器使用,斜杠就代表当前Web应用。 如果是浏览器使用,斜杠就代表网站,网站下面才有Web应用。
例一: 转发, 转发是给服务器使用,所以斜杠是代表当前Web应用
request.getRequestDispatcher("/1.html");
例二: 重定向, 重定向是给浏览器使用的,所以斜杠是代表网站,后面还需要接Web应用名
response.sendRedirect("/WebTest2/1.html");
书写路径时, 如果是Web工程中的资源文件用“/”斜杠, 如果是要获取硬盘上的文件,用“C:\\” 反斜杠
6. 域, ServletContext域 和 request域
对于域 需要有两个理解, 首先是一个容器,然后有自己的作用范围。