Servlet技术学习_上

Servlet细节问题:

1.一个<servlet>可以对应多个<servlet-mapping>,从而一个Servlet可以有多个访问路径;

2.url-partten中的路径可以使用*匹配符进行匹配,但只能以/开头/*结尾或*.后缀,优先级判断的标准是:①选最像的;②*.后缀的匹配级别最低。

3.<servlet>可以配置<load-on-startup>标签来指定Servlet的启动次序,当不配置或配置参数为负数时,表示只有在该Servlet首次被访问时才回去创建此Servlet,配置为0或正数时,表示在web应用被加载时,该ServletServlet容器所创建,值越小越先被加载创建。

4.缺省的Servlet:一个Servlet<url-pattern>被配置为正斜杠(/),这个Servlet就成了缺省的Servlet,其他Servlet都不处理的请求,有缺省的Servlet处理;

 

静态资源的访问就是由缺省的Servlet来执行的,而此缺省的Servlet是由tomcat提供的,在web.xml中可以看到它的配置信息,此处的web.xml是指Servlet容器中的conf/web.xmlServlet容器中的所有的web应用的WEB-INF/web.xml都继承了conf/web.xml的配置信息。

 Servlet技术学习_上_第1张图片

设置404页面500页面也是有缺省的Servlet来执行的;通常我们不会去配置缺省的Servlet

5.线程安全问题

由于默认情况下Servlet在内存中只有一个对象,当多个浏览器访问Servlet时就有可能产生线程安全问题,目前解决的办法有以下:

①加锁(效率较低)

②实现SingleThreadMode接口(不能真正的解决线程安全问题,已经废弃使用)

③在Servlet中尽量少用类变量,将会造成造成线程安全问题的代码加锁,尽量的使被锁住的内容少,减少客户端等待的时间,提高Servlet的响应速度。

 

ServletConfig(代表当前的Servlet的配置对象)

String getServletName()  获得当前Servletweb.xml中配置的名字,<servlet-name>的值;

String getInitParameter(String name)  根据name,获取当前Servletweb.xml中的初始化参数值,name是初始化参数的<param-name>

Enumeration getInitParameterNames()  获取当前Servletweb.xml中的所有初始化参数的名称;

ServletContext getServletContext()  获取代表当前web应用的ServletContext对象

 

ServletContext(代表当前web应用)

Web应用被创建时会创建唯一一个ServletContext对象。

ServletContext对象的主要作用:

1.作为域对象可以在整个web应用范围内共享数据。

作用范围:整个web应用范围内;

生命周期:当服务器加载web应用时就会创建ServletContext对象,当web应用被移除时ServletContext对象被销毁;

 

         void setAttribute(String key, Object obj)  设置一个域属性

         Object getAttribute(String key)   根据key值查找到对应的域属性

         void removeAttribute(String key)   删除key对应的域属性

 

 

2.获取web应用的初始化参数

String getInitParameter(String name)  根据name,获取当前web应用在web.xml中的初始化参数值;

Enumeration getInitParameterNames()  获取当前web应用在web.xml中的所有初始化参数的名称

 

3.实现Servlet的重定向和转发

重定向: 302 + Location,两次请求两次响应

请求转发:一次请求一次响应

 

①请求重定向

方法一:(HttpServletResponse response)

response.setStatus(302);

response.setHeader(Location/HelloWorld/index.html);

 

方法二:

response.sendRedirect(/HelloWorld/index.html);

 

②请求转发

RequestDispatcher dispatcher 

          = this.getServletContext().getRequestDispatcher(/HelloWorld/registerServlet);

dispatcher.forward(request, response);

【说明】从上面请求转发的过程中看到,请求转发并没有创建新的HttpServletRequestHttpServletResponse对象,而是将之前接收到的requestresponse转发给其他Servlet

 

4.Servlet容器的相关信息(ServletContext context

context.getMajorVersion()   获得容器支持的Java Servlet API的主版本号

context.getMinorVersion()   获得容器支持的Java Servlet API的次版本号

context.getServletInfo()    获得Servlet容器名称和版本号

5.访问Servlet中的文件系统

getRealPath(String name)  获得在/WEB-INFO下,名称为name的文件的绝对路径。

getMimeType(String file)   获得指定文件的MIME类型(e.g. Text/html

getContextPath()   获得web应用的URL入口

 

 

ServletRequest(从对象中获得来自客户端的请求信息)

常用接口:

getContentLength()  获得请求正文的长度,未知则返回-1

getContentType()   获得请求正文的编码方式

getInputStream()   读取请求中的输入流

getLocalAddr()   获得服务器的IP地址

getLocalName()   获得主机(Host)名

getLocalPort()   获得服务器FPT端口

getParameter(String name)   根据参数名获得请求URL中的请求参数值

getProtocol()   获得通信协议及版本号(e.g. HTTP 1.1

getReader()   BufferReader

getRemoteAddr()   获得客户端的IP地址

getRemoteHost()   获得客户端主机名

getRemotePort()   获得客户端FTP端口号

 

HttpServletRequest(继承自ServletRequest

常用接口:

getContentPath()   获得客户端访问服务器web应用的入口,

e.g. Url=http://localhost:8080/HelloWorld/infoServlet时,URL入口为/HelloWorld

getCookies()

getHeader(String key)   从request中获得key的请求头信息

getHeaderNames()   获得请求头中所有的的key,返回一个Enumeration对象

getMethod()   获得请求的方式(GETPOST)

getRequestURI()   获取请求url中的URI

getQueryString()   获取请求URL中的请求参数部分

 

ServletResponse

常用接口:

setCharacterEncoding(String charset)   设置服务器的编码方式,默认为IOS8859-1

setContentLength()       设置响应正文的长度

getCharacterEncoding()   获得服务器的编码格式

getContentType()       获得服务器的MIME类型

setBufferSize(int size)   设置存放响应的缓存的大小

getBufferSize()   获得服务器存放响应的缓存的大小

reset()    清空缓存区正文、响应内容(全部清空)

resetBuffer()    只清空缓存区正文内容

flushBuffer()    强制性的将缓存区的内容发给浏览器

isCommitted()   若为true表示缓存区数据已经发给了浏览器,若返回false表示缓存区数据未发送

getOutputStream()   从response中获得字节流,用于向响应缓存区写入数据

getWriter()         从response中获得字符流,用于向响应缓存区写入数据

【说明】一下几种情况,缓存数据会被提交给浏览器:

①缓存区数据已经满;

②调用responseflushBuffer()方法

③调用ServletOutputStream()/PrintWriter对象的flush()close()方法。

【注意】

Servlet在调用完service()之后,会自动关闭ServletOutputStream/PrintWriter,从而保证数据发送给浏览器。

 

HttpServletResponse(通过该对象生成响应)

常用接口:

setHeader(String key, String value) 设置响应头信息

 

Servlet相关问题:

1.控制服务器和浏览器的编码

①方法一

response.getOutputStream().write(中国.getBytes(utf-8)); // 服务器端指定编码格式通过设置HTTP响应头设置浏览器的解码方式为utf-8

response.setHeader(Content-Type , text/html;charset=utf-8);

//上面设置HTTP响应头信息的过程也可以通过下面的方式

response.setContentType(utf-8);

②方法二

// 设置服务器的编码方式

response.setCharacterEncoding(utf-8);

response.getWriter().write(中国);

// 设置完服务器的编码格式,与方法一一样,需要通过HTTP响应头设置浏览器的解码方式

response.setHeader(Content-Typetext/html;charset=utf-8);

// 或者response.setContentType(utf-8);

 

【注意】

a).ISO8859-1中没有对中文进行编码,使用ISO8859-1编码中文,则会全部编译为?号;

b).为了保证浏览器不出现中文乱码的情况,需要保证服务器的编码使用的码表和浏览器的解码的码表相同;

c)response.getOutputStream()将保存Http响应的缓存区设置为字节流型,缓存的内容是以字节流的形式保存的,response.getWriter()是将缓存设置为字符流型,将缓存内容以字符流的形式保存下来,因此对于同一个response,上面两种方法不能同时出现;

需要说明的是,在请求转发的时候,由于转发的是同一个response,所以同样需要保证转发response和接受responseServlet使用相同的方法写缓存。

 

2.图片显示和下载文件

InputStream in = new FileInputStream(iMxd.png);

OutputStream out = response.getOutputStream();

byte[] b = new byte[1024];

int i = 0;

while((i = in.read(b)) != -1)

{

     out.write(b,0,i);

}

in.close();

【说明】

①上面的程序中无需关闭OutputStreamServlet会自动关闭;

②通过上面的程序会在响应缓存区存储一张图片,通过字符流发送到浏览器,浏览器在接收到图片流之后会将图片显示在网页上,不会是下载图片的操作;若要改成下载图片而不是现实图片,可以通过设置响应头信息来实现:

  response.setHeader(“Content-Disposition”,“attachment;filename=iMxd.png”);

通过设置响应头中的Content-Disposition来指定浏览器下载图片,当图片名称为中文时,下载之后的文件名称会出现乱码等问题,可以通过下面的方式来解决这个问题:

response.setHeader(Content-Disposition,attachment;filename= + URLEncoder.encode(中国.png));

 

    URLEncoderencode实现URL编码

 

    URLDecoderdecode实现URL解码

 

3.Response控制定是刷新页面

response.setHeader(Refresh,1);

// 上面给响应头添加了刷新页面的信息,浏览器介绍到信息之后,会每隔一秒重新请求一次服务器,并同时刷新页面

 

response.setHeader(Refresh,3;url=/HelloWorld/index.html);

// 上面的程序将在三面之后跳转到/HelloWorld/index.html

 

Html中模拟Refresh响应头:

<head>

<meta http-equiv=Refresh

  content=3;url=/HelloWorld/index.html >

</head>

 

4.Response控制浏览器不进行缓存

若浏览器对访问资源页面进行了缓存,当浏览器再次访问相同资源时,浏览器会显示本地中已经缓存的信息,而不会在服务器中重新请求信息的数据,这样就造成了访问资源数据不是实时的。

因此对于实时信息不应该做缓存。

response.setIntHeader(Expires, -1);

response.setHeader(Cache-Controlno-cache);

response.setHeader(Pragmano-cache);

// 由于历史原因,不同的浏览器支持的响应头信息太完全一致,上面的三行头信息的设置可以保证所有浏览器不缓存内容

 

// 若要进行资源的缓存,则:

response.setDateHeader(Expires, System.currentTimeMillis() + 1000 * 60*60 * 24 * 30);

【说明】

通过响应头通知浏览器进行缓存,需要设置缓存的时间,上面的代码设置保存1个月,此时间是从197011000秒开始计算,一直到未来的某个时间点,设置在这段时间内缓存资源,不在此段时间内则删除资源,System.currentTimeMillis()是得到了从上面起点时间(197011000秒)到当前的毫秒数,再加上一个月的毫秒数。

【注意】

需要注意的是1000*60*60*24*30已经超出了int类型的范围,会起到减的效果,因此一般是转化为Long型,1000l*60*60*24*30(在1000后面加l)。

 

5.请求重定向

请求重定向会进行两次访问两次响应,当浏览器访问服务器某一Servlet时,若此Servlet无对应的资源,会响应浏览器,通过302通知浏览器去访问其他url,浏览器拿到新的url之后,无需用户操作浏览器,自动重定向新的url,访问服务器,产生了新的访问和响应。

重定向有两种方法:

方法一:

response.setStatus(302);

response.setHeader(Location/HelloWorld/index.html);

 

方法二:

response.setRedirect(/HelloWorld/index.html);

 

 

你可能感兴趣的:(Servlet技术学习_上)