response、request对象-中文问题,web开发中的地址问题,生成验证码,表单获取信息,url地址编码,request的请求转发

1、简介

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。
request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。

2、response


(1)、输出中文数据:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="中国";
response.setHeader("Content-Type","text/html;charset=UTF-8");
ServletOutputStream out = response.getOutputStream();
out.write(data.getBytes("UTF-8"));
}
模拟头:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="中国";
ServletOutputStream out = response.getOutputStream();
out.write("<meta http-equiv='Content-type' content='text/html;charset=UTF-8'>".getBytes());
out.write(data.getBytes("UTF-8"));
}

content="text/html" 通过查询tomcat中的web.xml的文件中查询输出类型!
输出文本最好用字符流,不要用字节流(stream)!
public void test3(HttpServletResponse response) throws IOException {
	//用字符流输出数据
	String data="中国";

	//response.setHeader("Content-Type","text/html;charset=UTF-8");
	response.setContentType("text/html;charset=UTF-8");
	//response.setCharacterEncoding("UTF-8");
	PrintWriter out = response.getWriter();

	out.write(data);
}
response.setContentType("text/html;charset=UTF-8");
起到了注释掉的两行代码的作用

用OutputStream输出1,客户端看到的是什么?      1经过查码表得到的字符

(2)、文件下载:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String realPath = this.getServletContext().getRealPath("/download/1.jpg");
	String name = realPath.substring(realPath.lastIndexOf("\\")+1);
	InputStream in =new FileInputStream(realPath);

	response.setHeader("Content-Disposition","attachment;filename="+name);

	byte buffer[]=new byte[1024];
	int len=0;
	OutputStream out = response.getOutputStream();
	while((len = in.read(buffer)) >0 ){
		out.write(buffer,0,len);
	}

	in.close();
	out.close();
}

如果 文件名是中文的话,而http里面只能是ascii码,因此需要进行提前的转换
URLEncoder类
response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(name,"UTF-8"));

用字符流处理字节流数据会丢东西!!!字节流可以处理任何数据,字符流只能处理字符数据!!

(3)、生成随机图片:

BufferImage         TYPE_INT_RGB
数字验证码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//通知浏览器以什么样的方式接收图片
	response.setHeader("Content-Type","image/jpeg");
	//设置头控制浏览器不要缓存图片数据
	response.setHeader("expires","-1");
	//在内存中创建一副图片
	BufferedImage bi = new BufferedImage(80,30, BufferedImage.TYPE_INT_RGB);
	//得到图片
	Graphics2D graphics = (Graphics2D) bi.getGraphics();
	//修改背景颜色
	graphics.setColor(Color.GRAY);
	graphics.fillRect(0,0,80,30);
	//向图片上写数据
	graphics.setColor(Color.RED);
	graphics.setFont(new Font("宋体",Font.BOLD,20));
	graphics.drawString(makeNum(),0,20);
	//将图片写给浏览器
	ImageIO.write(bi,"jpg",response.getOutputStream());
}

private String makeNum() {
	Random r = new Random();
	String num = r.nextInt(9999999)+"";
	StringBuffer buffer = new StringBuffer();
	for (int i=0;i<7-num.length();i++){
		buffer.append("0");
	}
	return buffer.toString()+num;
}

(4)、定时刷新:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	response.setCharacterEncoding("UTF-8");
	response.setHeader("refresh","5");
	response.setHeader("Content-Type","text/html;charset=UTF-8");
	response.getWriter().write("我是中国人");

}

(5)、请求重定向(尽量不用,主要用于登陆进入主页):

一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。
  • 浏览器发送两次请求
  • 浏览器地址会发生改变
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//请求重定向
	/*response.setStatus(302);
	response.setHeader("location","/index.jsp");*/
	response.sendRedirect("/index.jsp");
}

(6)、WEB开发中的地址问题:

  • 一定要“/”开头,相对地址
  • "/"到底是从哪里开始,看是给谁用的,如果给服务器用则代表web工程;如果是给浏览器用则代表webapps
  • \\用于电脑硬盘上的地址,/用于url地址
负载均衡:DNS轮询;负载均衡服务器

(7)、注意事项:

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

3、request

获取客户端的数据就是利用request对象
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

(1)、获得客户机信息:

  • getRequestURL方法返回客户端发出请求时的完整URL。
  • getRequestURI方法返回请求行中的资源名部分。
  • getQueryString 方法返回请求行中的参数部分。
  • getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
  • getRemoteAddr方法返回发出请求的客户机的IP地址
  • getRemoteHost方法返回发出请求的客户机的完整主机名
  • getRemotePort方法返回客户机所使用的网络端口号
  • getLocalAddr方法返回WEB服务器的IP地址。
  • getLocalName方法返回WEB服务器的主机名
  • getMethod()返回客户机的请求方式
(a)、URL与URI

url是uri的子集,uri表示任何资源地址,url仅表示网络地址
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//url是uri的子集,uri表示任何资源地址,url仅表示网络地址
	System.out.println(request.getRequestURL());//得到请求url地址
	System.out.println(request.getRequestURI());//得到请求的资源
}
(b)、getQueryString
http://localhost:8080/Request1? name=flx

(2)、获得客户机请求头:

  • getHeader方法 :request.getHeader("Accept-Encoding") 查看支持何种压缩数据
  • getHeaders方法 
  • getHeaderNames方法 

(3)、获得客户机请求参数(客户端提交的数据):

  • getParameter方法
  • getParameterValues(String name)方法
  • getParameterNames方法 
  • getParameterMap方法//常用于框架
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String name = request.getParameter("name");
	System.out.println(name);

	String[] names = request.getParameterValues("name");
	for(int i =0 ; names!=null&& i<names.length;i++){
		System.out.println(names[i]);
	}

	Enumeration<String> parameterNames = request.getParameterNames();
	while(parameterNames.hasMoreElements()){
		String s = parameterNames.nextElement();
		String value = request.getParameter(s);
		System.out.println(s+":"+value);
	}

	System.out.println("-----------------------------------------------");
	//用于框架
	Map<String, String[]> parameterMap = request.getParameterMap();
	for(Map.Entry<String, String[]> me: parameterMap.entrySet()){
		String n = me.getKey();
		String[] value = me.getValue();
	}
}

我们在web服务器中收集用户的信息,就用表单的形式:
text、password、radio、checkbox、file、select、textarea、 hidden
而image,button是给js编程使用的!!
实例:
fomr.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="Request4" method="post">
        用户名<input type="text" name="username"><br>
        密码<input type="password" name="password"><br>
        性别<input type="radio" value="male" name="gender">男
        <input type="radio" value="femal" name="gender">女<br>
        城市
        <select name="city">
        <option value="BJ">北京</option>
        <option value="SH">上海</option>
        <option value="CQ">重庆</option>
        <option value="TJ">天津</option>
        </select><br>
        爱好
        <input type="checkbox" value="music" name="hobby">音乐
        <input type="checkbox" value="sport" name="hobby">运动
        <input type="checkbox" value="reading" name="hobby">看书
        <input type="checkbox" value="shopping" name="hobby">购物<br>
        备注<textarea rows="5" cols="60" name="beizhu"></textarea><br>
        照片<input type="file" name="file"><br>
        <input type="hidden" value="sss" name="name">
        <input type="submit" value="提交">
    </form>
</body>
</html>
Request4
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	System.out.println(request.getParameter("username"));
	System.out.println(request.getParameter("password"));
	System.out.println(request.getParameter("gender"));
	System.out.println(request.getParameter("city"));

	String[] hobbies = request.getParameterValues("hobby");
	for(int i = 0 ;hobbies!=null&&i<hobbies.length;i++){
		System.out.println(hobbies[i]);
	}
	System.out.print(request.getParameter("name"));
	System.out.print(request.getParameter("beizhu"));
}
其中文件的上传和隐藏还没有详细讲述,会在以后说明!

注意:
①要对传送过来的数据进行检查,不能为空(a、“”  b、Null  c、"      "三种情况):
if (username == null || username.trim().equals("")){
//为空操作
}else
{//不为空操作            
}
②POST提交内容为中文事项

由于,html网页是自己编写的,码表是可以进行自行设置的,因此只需要在servlet部分设置request对应的码表即可!

request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
System.out.println(username);

response.setContentType("text/html;charset=GB2312");
PrintWriter writer = response.getWriter();
writer.write(username);
显示正常
③GET提交内容为中文事项

设置request方式的编码无效,用户想不乱吗只能手工转换
String username = request.getParameter("username");
byte[] bytes = username.getBytes("iso8859-1");
username = new String(bytes,"UTF-8");
System.out.println(username);
转码过程等同于:
username=new String(username.getByte("iso8859-1"),"UTF-8");

也可以改服务器的配置文件,但是极度不建议!
URIEncoding

This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless theorg.apache.catalina.STRICT_SERVLET_COMPLIANCE system property is set to true in which case ISO-8859-1 will be used.

useBodyEncodingForURI

This specifies if the encoding specified in contentType should be used for URI query parameters, instead of using the URIEncoding. This setting is present for compatibility with Tomcat 4.1.x, where the encoding specified in the contentType, or explicitly set using Request.setCharacterEncoding method was also used for the parameters from the URL. The default value is false.

Notes: 1) This setting is applied only to the query string of a request. Unlike URIEncoding it does not affect the path portion of a request URI. 2) If request character encoding is not known (is not provided by a browser and is not set by SetCharacterEncodingFilter or a similar filter using Request.setCharacterEncoding method), the default encoding is always "ISO-8859-1". The URIEncoding setting has no effect on this default.


<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
URIEncoding="UTF-8"  过于固定
useBodyEncodingForURI="true"   request设置为什么编码就利用什么编码
貌似get方式的默认编码就是utf-8,post用iso8859-1

url地址后面如果跟了中文数据,一定要经过url编码

4、request的请求转发

(1)、forward方法实现转发:
前面学过了利用Context对象来进行转发,现在也可以利用request来进行转发。
request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。
请求转发的应用场景:MVC设计模式

//转发方式1---context
this.getServletContext().getRequestDispatcher("/test.jsp").forward(request,response);

//转发方式2---request
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/test.jsp");
requestDispatcher.forward(request,response);
两种转发方式相同的效果,没有区别

MVC的设计:servlet交给jsp
不能用context作为容器,要用request作为容器:
context是公共容器,多线程访问会造成覆盖;而每个线程都有自己的request,不会相互干扰

request对象同时也是一个 域对象(容器的作用范围:请求范围(servletcontext域:web应用范围))开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。
  • setAttribute方法 
  • getAttribute方法  
  • removeAttribute方法
  • getAttributeNames方法
request7  data="abc"
request.setAttribute("data",data);
this.getServletContext().getRequestDispatcher("/test.jsp").forward(request,response);


test.jsp
<h1>
  <%
    String data = (String) request.getAttribute("data");
    out.write(data);
  %>
</h1>

注意:
forward方法用于将请求转发到RequestDispatcher对象封装的资源。
如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。 
如果在调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。 

(2)、请求重定向与请求转发的区别:
  • 请求重定向浏览器发出两次请求,两个request和response,浏览器地址栏发生变化;
  • 请求转发浏览器只发送了1次请求,但是服务器有两次响应,只创建一个request和一个response,浏览器的地址没有发生变化。
一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理,称之为 请求转发
一个web资源收到客户端请求后,通知浏览器去访问另外一个web资源,称之为 请求重定向

  • RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。 
  • 如果传递给HttpServletResponse.sendRedirect 方法的相对URL以“/”开头,它是相对于整个WEB站点的根目录;如果创建RequestDispatcher对象时指定的相对URL以“/”开头,它是相对于当前WEB应用程序的根目录。 
  • 调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。
  • HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。 
  • RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。 
(3)、include方法实现转发
  • RequestDispatcher.include方法用于将RequestDispatcher对象封装的资源内容作为当前响应内容的一部分包含进来,从而实现可编程的服务器端包含功能。
  • 被包含的Servlet程序不能改变响应消息的状态码和响应头,如果它里面存在这样的语句,这些语句的执行结果将被忽略。
应用场景: 非常有用!
一个网站一般的网头(公司logo),网脚(联系方式)都是固定的,主要是网体不同,因此网头,网脚可以写成一个模板,被其他网页调用!
HeadServlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	response.getWriter().write("我是网头");
}
FootServlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	response.getWriter().write("我是网脚");
}
Request8:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	response.setContentType("text/html;charset=UTF-8");
	request.getRequestDispatcher("HeadServlet").include(request,response);
	response.getWriter().write("<br>abc<br>");
	request.getRequestDispatcher("FootServlet").include(request,response);

}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值