Servlet基础

目录

一.由来

二.Servlet 自启动

三. HttpServletRequest 常见方法

四.请求出现乱码的原因和解决

五. HttpServletResponse

六.响应出现乱码的原因和解决

七.文件下载


一.由来

如果说DOM是javascript与HTML的桥梁,那么servlet就是前端与后端的桥梁,HttpServletRequest和HttpServletResponse就是之间的信使,好了,废话不多说!

Web服务器收到一个http请求,会针对每个请求创建一个HttpServletRequest和HttpServletResponse对象,向客户端发送数据找HttpServletResponse,从客户端取数据找HttpServletRequest.

  HTTP 协议是基于请求-响应的协议,客户端请求一个文件,服务器对该请求进行响应。HTTP 使用 TCP 协议,默认使用 80 端口。最初的 HTTP 协议版本是 HTTP/0.9,后被HTTP/1.0 替代。目前使用的版本是 HTTP/1.1,

在 HTTP 协议中,总是由主动建立连接、发送 HTTP 请求的客户端来初始化一个事务。服务器不负责连接客户端,或创建一个到客户端的回调连接(callback connection)。

二.Servlet 自启动


Servlet的生命周期是在用户访问浏览器对应的路径开始的。如果没有用户的第一次访问,就无法执行相关代码。 
这个时候,就需要Servlet实现自启动 即,伴随着tomcat的启动,自动启动初始化,在初始化方法init()中,就可以进行一些业务代码的工作了.

<servlet>
	<servlet-name>HelloServlet</servlet-name>
	<servlet-class>HelloServlet</servlet-class>
    //当 tomcat 启动的时候 servlet 也会初始化,值越小优先级越高
	<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>HelloServlet</servlet-name>
	<url-pattern>/hello</url-pattern>
</servlet-mapping>

三. HttpServletRequest 常见方法

1.HTTP请求头介绍

公共接口类HttpServletRequest继承自ServletRequest.客户端浏览器发出的请求被封装成为一个HttpServletRequest对象。所有的信息包括请求的地址,请求的参数,提交的数据,上传的文件客户端的ip甚至客户端操作系统都包含在其内。

一个 HTTP 请求包含以下三部分:

a.请求地址(URL)

b.请求头(Request headers)

c.实体数据(Entity body)

举例如下

POST /examples/default.jsp HTTP/1.1

Accept: text/plain; text/html

Accept-Language: en-gb

Connection: Keep-Alive

Host: localhost

User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)

Content-Length: 33

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

lastName=Franks&firstName=Michael

每个请求头使用 CRLF(回车换行符,“\r\n”)分隔。注意请求头的格式:

请求头名+英文冒号+请求头值+\r\n

2.常用方法

1.获得客户机信息

getRequestURL方法返回客户端发出请求时的完整URL。

getRequestURI方法返回请求行中的资源名部分。

getQueryString 方法返回请求行中的参数部分。

getRemoteAddr方法返回发出请求的客户机的IP地址

getRemoteHost方法返回发出请求的客户机的完整主机名

getRemotePort方法返回客户机所使用的网络端口号

getScheme 方法返回请求的协议           例如:http

getServerName 方法返回WEB服务器的主机名 例如:localhost

getServerPort 方法返回WEB服务器的端口 例如:8080

getLocalAddr方法返回WEB服务器的IP地址。例如:0:0:0:0:0:0:0:1

getLocalName方法返回WEB服务器的主机名 例如:localhost

getLocalPort()方法返回WEB服务器的端口 例如:8080

getMethod得到客户机请求方式

getServerPath()获取请求的文件的路径

 2.获得客户机请求头

getHeader(string name)方法 
getHeaders(String name)方法 
getHeaderNames方法  

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

getInputStream() 获取请求的输入流中的数据

getReader() 获取请求体的数据流

getParameter(name)方法 获取请求中的参数,该参数是由name指定的

getParameterValues(String name)方法 获取指定名称参数的所有值数组。它适用于一个参数名对应多个值的情况。如页面表单中的复选框,多选列表提交的值。

getParameterNames方法 返回一个包含请求消息中的所有参数名的Enumeration对象。通过遍历这个Enumeration对象,就可以获取请求消息中所有的参数名。

getParameterMap():返回一个保存了请求消息中的所有参数名和值的Map对象。Map对象的key是字符串类型的参数名,value是这个参数所对应的Object类型的值数组

request.setCharacterEncoding("utf-8");

getCharacterEncoding() 返回请求的字符编码方式

getsession()返回和客户端相关的session,如果没有给客户端分配session,则返回null

getAttributeNames()返回当前请求的所有属性的名字集合赋值:setAttribute()

getAttribute(String name) 返回name指定的属性值

RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。

Enumeration<String> names=req.getParameterNames();
String[] values =req.getParameterValues("hobby");
Map<String,String[]> maps =req.getParameterMap();

while (names.hasMoreElements()){
   System.out.println(names.nextElement());
}

for (String s:values){
  System.out.println(s);
}

Set<Map.Entry<String,String[]>> entrySet=maps.entrySet();
for (Map.Entry<String,String[]> entry:entrySet){
   System.out.println("key:"+entry.getKey()+" value:"+entry.getValue());
}

四.请求出现乱码的原因和解决

1.Get方式提交出现乱码

对于以get方式传输的数据,request即使设置了以指定的编码接收数据也是无效的,默认的还是使用ISO8859-1这个字符编码来接收数据,客户端以UTF-8的编码传输数据到服务器端,而服务器端的request对象使用的是ISO8859-1这个字符编码来接收数据,服务器和客户端沟通的编码不一致因此才会产生中文乱码的。

解决办法:在接收到数据后,先获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题。代码如下:

String name = request.getParameter("name");//接收数据

name =new String(name.getBytes("ISO8859-1"), "UTF-8") ;//获取request对象以ISO8859-1字符编码接收到的原始数据的字节数组,然后通过字节数组以指定的编码构建字符串,解决乱码问题

2.Post方式提交出现乱码

request.setCharacterEncoding("UTF-8");

请求中之所以会产生乱码,就是因为服务器和客户端沟通的编码不一致造成的,因此解决的办法是:在客户端和服务器之间设置一个统一的编码,之后就按照此编码进行数据的传输和接收。

  由于客户端是以UTF-8字符编码将表单数据传输到服务器端的,因此服务器也需要设置以UTF-8字符编码进行接收,要想完成此操作,服务器可以直接使用从ServletRequest接口继承而来的"setCharacterEncoding(charset)"方法进行统一的编码设置。使用request.setCharacterEncoding("UTF-8");设置服务器以UTF-8的编码接收数据后,此时就不会产生中文乱码问题了

五. HttpServletResponse

1.响应头介绍

HttpServletResponse继承了ServletResponse接口,并提供了与Http协议有关的方法,这些方法的主要功能是设置HTTP状态码和管理Cookie。HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法

HttpServletResponse对象可以向客户端发送三种类型的数据:

a.响应头(Response headers)

b.状态码(Protocol—Status code—Description)

c.实体数据(Entity body )

举例如下:

HTTP/1.1 200 OK

Server: Microsoft-IIS/4.0

Date: Mon, 5 Jan 2004 13:13:33 GMT

Content-Type: text/html

Last-Modified: Mon, 5 Jan 2004 13:13:12 GMT

Content-Length: 112

<html><head><title>HTTP Response Example</title></head>....</html>

2.常用方法

通过response.getWriter(); 获取一个PrintWriter 对象可以使用println(),append(),write(),format()等等方法设置返回给浏览器的html内容。

//设置响应编码有两种方式
1. response.setContentType("text/html; charset=UTF-8");
2. response.setCharacterEncoding("UTF-8");

这两种方式都需要在response.getWriter调用之前执行才能生效。
他们的区别在于
1. response.setContentType("text/html; charset=UTF-8");
不仅发送到浏览器的内容会使用UTF-8编码,而且还通知浏览器使用UTF-8编码方式进行显示。所以总能正常显示中文
2. response.setCharacterEncoding("UTF-8"); 
仅仅是发送的浏览器的内容是UTF-8编码的,至于浏览器是用哪种编码方式显示不管。 所以当浏览器的显示编码方式不是UTF-8的时候,就会看到乱码,需要手动再进行一次设置。

//设置不使用缓存
使用缓存可以加快页面的加载,降低服务端的负担。但是也可能看到过时的信息,可以通过如下手段通知浏览器不要使用缓存
response.setDateHeader("Expires",0 );
response.setHeader("Cache-Control","no-cache");
response.setHeader("pragma","no-cache");
addHeader(String name,String value)  将指定的名字和值加入到响应的头信息中

setHeader(String name,String value)  将给出的名字和值设置响应的头部

setDateHeader(String name,long date)  将给出的名字和日期设置响应的头部

encodeURL(String url)  编码指定的URL

setStatus(int sc)  给当前响应设置状态码

sendError(int sc)  使用指定状态码发送一个错误到客户端

HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。

setContentType(String ContentType) response.setContentType("text/html;charset=utf-8"); 设置响应的MIME类型 ,页面的设置文本类型,获取或设置输出流的 HTTP MIME 类型。输出流的 HTTP MIME 类型。默认值为“text/html”。

Response.getOutputStream()  字节输出流对象

Response.getWriter()   字符的输出流对象

   
 

六.响应出现乱码的原因和解决

1. java程序中默认的是中文字符----unicode

2. 系统会把在java程序中的unicode字符按照某种字符集编码的方式转换成字节数组,再通过浏览器输出,浏览器在输出的时候要进行解码,只有在这两种方式一样的情况下,才不会出现乱码。

注:(1)某种字符编码是用reponse对象去设置的,而且必须是在out.println之前使用,要不会出现错误,会抛找不到设置的字符编码而出错。

         设置编码的两种方式:

        response.setContentType("text/html;charset=utf-8");

        request.setCharacterEncoding("utf-8");

      (2)浏览器会把字节数组转换成字符

  1. 系统默认的编码方式为ISO8859-1,如果没有指定字符编码,则输出的都是乱码,而且ISO8859-1不支持中文,所以不管浏览器在解码的时候用的是什么字符集编码,在浏览器上的都是乱码。

1.使用OutputStream向客户端写入中文

String data = "中国";
OutputStream stream = response.getOutputStream();//获取一个向Response对象写入数据的流,当tomcat服务器进行响应的时候,会将Response中的数据写给浏览器
stream.write(data.getBytes("UTF-8"));//此时在html页面会出现乱码,这是因为:服务器将"中国"按照UTF-8码表进行编码,得到对应的码值假设是98,99,服务器将码值发送给浏览器.浏览器默认按照GB2312进行解码,在GB2312码表中对应的字符已不是"中国"


正确代码如下:
response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8

 String data = "中国";
 OutputStream stream = response.getOutputStream();
 stream.write(data.getBytes("UTF-8"));

2.使用PrintWriter向客户端写入中文

PrintWriter writer = response.getWriter();
writer.write("中国");
//同样会出现乱码,这是因为我们将"中国"写入response对象时,tomcat服务器为了将数据通过网络传输给浏览器,必须进行编码,由于没有指定编码方式,Tomcat 服务器默认采用ISO8859-1,当浏览器接收到数据后,根据GBK解码必然出现乱码

 正确代码如下:
response.setCharacterEncoding("UTF_8");//设置Response的编码方式为UTF-8
response.setHeader("Content-type","text/html;charset=UTF-8");//向浏览器发送一个响应头,设置浏览器的解码方式为UTF-8,其实设置了本句,也默认设置了Response的编码方式为UTF-8,但是开发中最好两句结合起来使用 ,设置响应头,控制浏览器以指定的字符编码编码进行显示,
 //response.setContentType("text/html;charset=UTF-8");同上句代码作用一样

PrintWriter writer = response.getWriter();
writer.write("中国");
  在获取PrintWriter输出流之前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding("UTF-8");设置将字符以"UTF-8"编码输出到客户端浏览器,然后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒

七.文件下载

文件下载功能的实现思路:

  1.获取要下载的文件的绝对路径

  2.获取要下载的文件名

  3.设置content-disposition响应头控制浏览器以下载的形式打开文件 response.setHeader("content-disposition",         "attachment;filename="+fileName);

  4.获取要下载的文件输入流

  5.创建数据缓冲区

  6.通过response对象获取OutputStream流

  7.将FileInputStream流写入到buffer缓冲区

//文件不在项目根目录下
File file=new File("/Users/zhouzhenlin/Desktop/6.png");
String fileName=file.getName();

FileInputStream fs=new FileInputStream(file);
byte[] buffers=new byte[1024];
resp.setHeader("content-disposition", "attachment;filename="+fileName);
OutputStream os=resp.getOutputStream();
int length=0;

while((length=fs.read(buffers))!=-1){
   os.write(buffers,0,buffers.length);
}
fs.close();
//文件放在项目根目录下
String filePath=this.getServletContext().getRealPath("/download/6.png");
        String fileName=filePath.substring(filePath.lastIndexOf("/")+1,filePath.length());

FileInputStream fs=new FileInputStream(filePath);
byte[] buffers=new byte[1024];
resp.setHeader("content-disposition", "attachment;filename="+fileName);
OutputStream os=resp.getOutputStream();
int length=0;

while((length=fs.read(buffers))!=-1){
   os.write(buffers,0,buffers.length);
}
fs.close();

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值