JavaWeb3

response

response的OutputStream输出数据

1
2
3
4
5
6
7
8
9
String data = "中国";
OutputStream out = response.getOutputStream(); //字节流
out.write(data.getByte()); //这样在浏览器显示是正确的
----------------------------------------------------------
out.write(data.getBytes(“UTF-8"); //这样浏览器反而显示乱码
//原因:浏览器拿到response解析时默认用的码表时GB2312,并不是UTF-8,所以可以修改浏览器的码表,但实际开发显然不会这样做,需要在响应头指定码表。(新版谷歌浏览器默认UTF-8且无法更换)
response.setHeader("Content-type","text/html;charset=UTF-8");
String data =……
…………

或者利用html的meta标签模拟一个HTTP响应头,来控制浏览器行为

1
out.write("<meta http-equiv='Content-type' content='text/html;charset=UTF-8'>".getBytes());

response的Writer输出数据

1
2
3
4
5
6
7
8
9
String data = "中国";
PrintWriter out = response.getWriter(); //字符流
out.write(data); //这样在浏览器显示??
----------------------------------------------------------
//原因:servlet将“中国”写入response,response默认使用ISO8859码表,在码表中找“中国”,无法找到,所以返回两个“?”对应的数字,浏览器拿到response返回的数字解析显示“?”,所以修改response码表即可。
response.setCharacterEncoding(“UTF-8");
response.setHeader("Content-type","text/html;charset=UTF-8");
String data =……
…………

response下载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
String path = this.getServletContext().getRealPath("/download/1.jpg");	//得到资源文件1.jpg在硬盘中的地址
String filename = path.substring(path.lastIndexOf("\\")+1); //截取文件名
response.setHeader("content-disposition","attachment;filename=" + filename); //告诉浏览器下载文件
//如果下载文件中是中文文件,需要经过URL编码
//response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(filename, "UTF-8");
//读资源文件
InputStream in = null;
OutputStream out = null;
try{
in = new FileInputStream(path);
int len = 0;
byte buffer[] = new byte[1024];
out = response.getOutputStream();
while((len = in.read(buffer)) > 0) (
out.write(buffer, 0, len);
)
}finally {
if (in != null) {
try(
in.close();
)catch(Exception e) {
e.printStackTrace();
}
}
if (out != null) {
try(
out.close();
)catch(Exception e) {
e.printStackTrace();
}
}
}

response控制浏览器定时刷新

1
response.setHeader("refersh",3);	//每隔3s刷新一次

实际开发中,一般这么写

1
2
3
String message = "<meta http-squiv='refresh' content='3;url=/ProjectName/index.jsp'>恭喜你,登陆成功,本浏览器将在3s后跳转到主页面";
this.getServletContext().setAttribute("message",message);
this.getServletContext().getRequestDispatcher("/message.jsp").forward(request,response);

response控制浏览器缓存

1
response.setDateHeader("expires", System.currentTimeMillis()+1000*3600);	//缓存1h

response实现请求重定向

1
2
3
4
response.setStatus(302);	
response.setHeader("location", "/ProjectName/index.jsp"); //重定向到首页
--------------------------------------------------------------------------
response.setRedirect("/ProjectName/index.jsp"); //相当于上边两句

重定向向服务器发送两次请求,通过浏览器地址栏自动改变就可以看出来,这样对服务器压力较大,所以除了登录跳转和购物下单跳转购物车一般不介意采用。

response一些细节

  1. getOutputStream()和getWriter()方法分别用于得到输出二进制数据、输出文本数据的ServletOutputStream、Printwriter对象,这两个方法互斥,调用了其中一个就不能调用另一个;

  2. Servlet程序向ServletOutputStream或Printwriter对象写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端;

  3. Servlet的service方法结束后,Servlet引擎将检查getWriter()或getOutputStream()方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关于该输出流对象;

request

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

RUL和URI

URL:用于标识某个互联网资源,如http://www.sina.com/news/1.html;

URI:用于标识某个资源,如/news/1.html;C:\abc\d.txt;

判断这两个区别的用处:权限拦截、访问次数统计等

request获取请求头和请求数据

获取请求头:request.getHeader()/request.getHeaders()/request.getHeaderNames();

获取客户端带来的数据:

首先,客户端一般有两种方式带数据

1.

1
2
//通过超链接
<a href="RequestDemo?username=xxx">点我</a>

2.

1
2
3
4
5
//通过表单
<form action="RequestDemo" method="post">
用户名:<input type="text" name="username"><br>
<input type="submit" value="提交"><br>
</form>

request获取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
String value = request.getParameter("username");
//tip:获取请求数据要先检查再使用,如先判断输入是否为空或者是否为空格
if(value != null && !value,trim().equals("")){
System.out.println(values);
}
------------------------------------------------------
//所有name和对应的value
Enumeration e = request.getParameterNames();
while(e.hasMoreElements()) {
String name = (String)e.nextElement();
value = request.getParameter(name);
System.out.println(name+"="+value);
}
------------------------------------------------------
//一个name的所有value
String[] values = request.getParameterValues(“username”);
for(int i = 0;values != null && i < values.length;i++){
System.out.println(values[i]);
}
-------------------------------------------------------
//存到Map中
//需要首先先建好一个User.java的对象
Map map = request.getParameterMap();
User user = new User();
//需要导入commons-beanutils.jar和commons-logging,jar
BeanUtils.populate(user,map);
//有异常try……catch……
System.out.println(user);
--------------------------------------------------------
//流的方式,但即使获取到也需要解析,因为获取到的格式为“uername=xxx&password=yyy”
InputStream in = request.getInputStream();
int len = 0;
byte buffer[] = new byte[1024];
while((len=in.read(buffer))>0){
System.out.println(new String(buffer,0,len));
}

request中文乱码

1
2
request.setCharacterEncoding("UTF-8");		//只对post提交有效
username = new String(username.getBytes("iso8859-1"),"UTF-8"); //解决get提交乱码

request实现请求转发

请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。

request对象提供了一个getRequestDispatcher方法,该方法返回一个 RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。

1
2
3
String data = "aaaaa";
request.setAttribute("data",data);
request.getRequestDispatcher("/1.jsp").forward(request,response);

request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其他web资源处理。

MVC:model-javabean;view-jsp;controller-servlet,流程:jsp收到请求产生数据,数据通过JavaBean封装,JavaBean不适合做输出,会存在request域,jsp再从request中取出进行输出。

细节一:

如果在调用forward方法之前,在servlet程序中写入的部分内容已经被真正的传送到了客户端,forward方法将抛出IIIegalStateException异常,例如。

1
2
3
4
5
if(true){
request.getRequestDispatcher("/1.jsp").forward(request,response);
}
request.getRequestDispatcher("/2.jsp").forward(request,response);
//解决方案:在第一个forward后加入return;

细节二:

如果在调用forward方法之前向servlet引擎的缓冲区,即response中写入了客户端,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入response的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。

细节三:

RequestDispatcher对象除了forward方法之外还有一个方法,include方法,例如。

1
2
3
4
5
//例如,每个界面的头脚都一样,单独写一个head.jsp和foot.jsp,在需要的界面引用即可
request.getRequestDispatcher("/head.jsp").include(request,response);
response.getWriter().write("aaaaa");
request.getRequestDispatcher("/foot.jsp").include(request,response);
//注意被包含的页面,也就是head.jsp和foot.jsp不要包含全局架构标签

web工程各类地址写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//1.
request.getRequestDispatcher("/index.jsp").forward(request,response);

//2.
response.sendRedirect("/ProjectName/index.jsp");

//3.
this.getServletContext().getRealPath("/index.jsp");

//4.
this.getServletContext().getResourceAsStream("/index.jsp");

//5.
/*
<a href="/ProjectName/index.jsp">点击</a>

<form action="/ProjectName/index.jsp">
</form>
*/

总结:

写地址先写一个斜杠(/),如果地址是写给服务器用的,这个斜杠就代表web应用;如果地址是写给浏览器的,这个斜杠就代表网站;

利用referer防盗链

1
2
3
4
5
6
String referer = request.getHeader("referer");		//获得访问链接
//判断如果是盗链者跳转到首页
if(referer==null || referer.startsWith("https://localhost")){
response.sendRedirect("/ProjectName/index.jsp");
return;
}

:转载文章请注明出处,谢谢~