zoukankan      html  css  js  c++  java
  • JavaWeb -- 服务器传递给Servlet的对象 -- ServletConfig, ServletContext,Request, Response

    1.  ServletConfig 

    一些东西不合适在程序中写死,应该写在web.xml中,比如 文字怎么显示, 访问数据库名 和 密码, servlet要读取的配置文件 等等。。

    lServlet的配置文件中,可以使用一个或多个<init-param>标签为servlet配置一些初始化参数。
    lservlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servletinit方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
    web.xml 设置参数
      <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>
    Servlet获取参数
    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, 停服务器才销毁对象。

    lWEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用
    lServletContext对象被包含在ServletConfig对象中,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得对ServletContext对象的引用。
    l由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯ServletContext对象通常也被称之为context域对象

    应用:聊天室等

    应用一: l多个Servlet通过ServletContext对象实现数据共享。

    Demo1
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		String data = "aaaa";
    		this.getServletContext().setAttribute("data1", data);  //写入
    	}
    Demo2
    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());
    	}
    应用二: l获取WEB应用的初始化参数
    如1ServletConfig配置参数只能一个Servlet使用,用ServletContext设置参数能使整个Web应用所有Servlet访问。
    web.xml参数
    <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());
    	}
    应用三:l实现Servlet的转发
    注意Servlet转发和Http协议重定向的区别, Http重定向 消息头为Location,重定向的意思是 “我没有,你自己去找别人”,转发的意思是“我没有,我帮你去找别人”。
    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);			
    	}
    应用四:l利用ServletContext对象读取资源文件
    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 读取文件。
     

    3. Response
    控制编码输出
    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 = "u7684u4e00u662fu4e86u6211u4e0du4ebau5728u4ed6u6709u8fd9u4e2au4e0au4eecu6765";		
    		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要注意的一些细节

    a: getOutputStreamgetWriter方法分别用于得到输出二进制数据、输出文本数据的ServletOuputStreamPrintwriter对象。
    b: getOutputStreamgetWriter两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法。 
    c: Servlet程序向ServletOutputStreamPrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
    d: Serlvetservice方法结束后,Servlet引擎将检查getWritergetOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象,不需要程序猿手动close掉返回流


    4. Request

    Request 常用方法

    l获得客户机信息

    getRequestURL方法返回客户端发出请求时的完整URL
    getRequestURI方法返回请求行中的资源名部分。
    getQueryString方法返回请求行中的参数部分。
    getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
    getRemoteAddr方法返回发出请求的客户机的IP地址
    getRemoteHost方法返回发出请求的客户机的完整主机名
    getRemotePort方法返回客户机所使用的网络端口号
    getLocalAddr方法返回WEB服务器的IP地址。
    getLocalName方法返回WEB服务器的主机名
    l获得客户机请求头
    getHeader方法
    getHeaders方法
    getHeaderNames方法
    l获得客户机请求参数(客户端提交的数据)
    getParameter方法
    getParameterValuesString name)方法
    getParameterNames方法
    getParameterMap方法 
    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域

    对于域 需要有两个理解, 首先是一个容器,然后有自己的作用范围





     









     
  • 相关阅读:
    Java并发编程原理与实战九:synchronized的原理与使用
    Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
    Java并发编程原理与实战七:线程带来的风险
    Java并发编程原理与实战六:主线程等待子线程解决方案
    Java并发编程原理与实战五:创建线程的多种方式
    Java并发编程原理与实战四:线程如何中断
    Java并发编程原理与实战三:多线程与多进程的联系以及上下文切换所导致资源浪费问题
    Java并发编程原理与实战二:并行&并发&多线程的理解
    ConcurrentHashMap 产生NullPointerException
    Java并发编程原理与实战一:聊聊并发
  • 原文地址:https://www.cnblogs.com/xj626852095/p/3648160.html
Copyright © 2011-2022 走看看