Servlet学习

本文最后更新于:5 个月前

这里是学习Servlet时的一些笔记整理

Servlet

HttpServletRequest对象

常用方法

方法 描述
getRequestURL() 获取客服端发出请求时的完整URL
getRequestURI() 获取请求行中的资源名称部分(项目名称开始)
getQueryString() 获取请求行中的参数部分
getMethod() 获取客服端请求方式
getProtocol() 获取HTTP版本号
getContextPath() 获取webapp名字(/+当前项目的名字)
getParameter() 获取指定名称参数,返回字符串(重点)
getParameterValues() 获取指定名称参数,返回字符串组
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
//获取完整路径
StringBuffer URL=request.getRequestURL();
System.out.println("URL: " + URL);
//获取请求时的部分路径
String URI=request.getRequestURI();
System.out.println("URI: " + URI);
//获取请求时的参数字符串
String queryString=request.getQueryString();
System.out.println("queryString: " + queryString);
//获取请求方式(GET和POST)
String method=request.getMethod();
System.out.println("method: " + method);
//获取当前协议版本(HTTP/1.1)
String protocol =request.getProtocol();
System.out.println("protocol: "+protocol);
//获取项目站点名
String webapp=request.getContextPath();
System.out.println("webapp: "+webapp);

//获取指定名称参数,返回字符串
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
System.out.println("name: " +name+" pwd: "+pwd);
//获取指定名称参数,返回字符串组
String[] hobbys = request.getParameterValues("hobby");
//判断是否为空
if(hobbys!=null&&hobbys.length!=0){
for(String hobby: hobbys){
System.out.println("爱好: "+hobby);
}
}

请求乱码问题

tomcat 8以上版本:

​ GET请求:不会乱码

​ POST请求:会乱码 用 request.setCharacterEncoding("UTF-8");

tomacat 7以下版本:

​ POST请求:会乱码 用 request.setCharacterEncoding("UTF-8"); //只对7的post有效

​ GET请求:会乱码 用new String (request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8“) //而8以上不乱码使用后乱码

方式一

1
request.setCharacterEncoding("UTF-8");

方式二

1
new String (request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8") 

请求转发

1.一种服务器行为,2.地址栏URL地址不变,3.从始至终只有一个请求发出,4.数据共享(后台跳前台)

1
request.getRequestDispatcher(url).forward(request,response);

request作用域

通过该对象可以在一次请求中传递数据,作用范围:在一次请求中有效,即服务器跳转有效.

可以在请求转发中使用,一个设置另一个获取

1
2
3
4
5
6
//设置域对象内容
request.setAttrivute(String name,Object value);
//获取域对象内容
request.getAttribut(String name);
//删除域对象内容
request.removeAttribute(String name);

HttpServletResponse对象

HttpServletResponse主要功能用于服务器对客户端的请求进行响应,将web服务器处理后的结果返回给客户端。

响应数据

响应时需要获取输出流,有两种形式(两种不能同时使用):

1
2
getWriter()//获取字符流(只能响应回字符)
getOutputStream()//获取字节流(能响应一切数据)
1
2
3
4
5
//字符输出流
PrintWriter writer=response.getwriter();
writer.write("hello");
//或者 writer.println("hello");
writer.write("<h2>hello</h2>");
1
2
3
4
//字节输出流
ServletOUtputStream out = response.getOutputStream();
out.write("Hello".getBytes());
out.write("<h2>Hello</h2>".getBytes());

响应乱码问题

1
2
3
4
//设置服务端的编码格式
response.setCharacterEncoding("UTF-8");
//设置客户端的编码格式
response.setHeader("content-type","text/html;charset=UTF-8")

设置客户端和服务端的编码格式,且保持一致

1
2
//同时设置客户端和服务端的编码格式
response.setContentType("text/html;charset=UTF-8");

第二种方法好一点。

注:编码格式要在所有输出流前面设置,如果设置编码格式前面有一个输出都会导致编码格式设置失效

重定向

1.是一种服务端指导客户端行为,2.存在两次请求,3.地址栏会改变,4.request对象不共享

1
2
//重定向到index.jsp
response.sendRedirect("index.jsp");

重定向与请求转发的区别

请求转发 [ request.getRequestDispatcher().forward() ] 重定向 [ response.sendRedirect() ]
一次请求,数据在request域中共享 两次请求,request域中数据不共享
服务端行为 客户端行为
地址栏不发生改变 地址栏发生改变
绝对地址定位到站点后(只能到当前站点下) 绝对地址可写到http://

Cookie对象

浏览器的一种技术,通过服务器的程序能将一些只须保存在客户端,或者客户端进行处理的数据,放在本地计算机上,提高网页的处理效率,但由于是服务端保持客户端的信息,所有安全性很差(浏览器记者密码)。

Cooike的创建和发送

通过new Cookie("key","value");来创建对象,要响应发到客户端,需先添加到response对象中,response.addCookie(cookie);此时cookie对象则随着响应发送至客户端

1
2
3
4
//创建Cookie对象
Cookie cookie = new Cookie("uame","lingqu");
//发送Cookie对象
response.addCookie(cookie);

Cookie的获取

getCookie()方法获取返回的是cookie数组,获取单个需要遍历,getName()获取Cookie的名称,getValue()获取Cookie的值。

1
2
3
4
5
6
7
8
9
10
//获取Cookie数组
Cookie[] cookies = request.getCookies();
//判断数组是否为空
if(cookies != null && cookies.length > 0){
//遍历数组
for(Cookie cookie : cookies){
System.out.println(cookie.getName());
System.out.println(cookie.getValue());
}
}

Cookie设置到期时间

我们可以手动设定cookie的有效时间,通过setMaxAge(int time);方法设定cookie的最大有效时间,单位(秒).

到期时间的取值

  • 负整数

    表示不储存cookie。maxAge的默认值就是-1,表示只在浏览器内存中存活,关闭浏览器,cookie会消失

  • 正整数

    表示cookie可储存的秒数。大于0时,会把cookie保存到硬盘上,关闭浏览器,重启客户端电脑,cookie也存活相应的时间

  • 表示删除该cookie。无论在浏览器内存中还是客户端硬盘上都会删除这个cookie。

Cookie的路径

setPath设置cookie路径,路径直接决定服务器的请求是否会从浏览器中加载某些cookie。

  • 服务器任何项目的任意资源都可获取Cookie对象

    1
    2
    3
    4
    5
    //当前项目路径为:s01
    Cookie cookie = new Cookie("xxx","xxx");
    //设置路径为"/",表示在当前服务器下任何项目都可访问到Cookie对象
    cookie.setPath("/");
    response.addCookie(cookie);
  • 当前项目下的资源可获取Cookie对象

    1
    2
    3
    4
    5
    //当前项目路径为:s01
    Cookie cookie = new Cookie("xxx","xxx");
    //设置路径为"/s01",表示在当前项目下任何项目都可访问到Cookie对象
    cookie.setPath("/s01");//默认情况,可不设置path的值
    response.addCookie(cookie);
  • 指定项目下的资源可获取Cookie对象

    1
    2
    3
    4
    5
    //当前项目路径为:s01
    Cookie cookie = new Cookie("xxx","xxx");
    //设置路径为"/s02",表示在s02项目下才可访问到Cookie对象
    cookie.setPath("/s02");//只能在s02项目下获取Cookie,就算cookie是s01产生的,s01也不能获取它
    response.addCookie(cookie);
  • 指定目录下的资源可获取Cookie对象

    1
    2
    3
    4
    5
    //当前项目路径为:s01
    Cookie cookie = new Cookie("xxx","xxx");
    //设置路径为"/s01/cook",表示在s01/cook目录下才可访问到Cookie对象
    cookie.setPath("/s01/cook");
    response.addCookie(cookie);

注:当访问的路径包含了cookie的路径时,则该请求将带上该cookie;如果访问路径不包含cookie路径,则该请求不会携带该cookie。

HttpSession对象

每个客户端都是一个session。Session的作用就是为了标记一次会话,或者确认一个用户;并且在一次会话(一个用户的多次请求)期间共享数据。我们可以通过request.getSession()方法,来获取当前会话session对象。

当获取session对象时,会先判断session对象是否存在,如果存在,则获取session对象;如果不存在,就创建session对象

1
2
3
4
5
6
7
8
9
10
11
//获取session对象
HttpSession session = request.getSession();
//获取session会话标识符
String id = session.getId();
System.out.println(id);
//获取session的创建时间
System.out.println(session.getCreationTime());
//获取最后一次访问时间
System.out.println(session.getLastAccessedTime());
//判断是否是新的session对象
System.out.println(session.isNew());

标识符JSESSIONID

​ 每当一次请求到达服务器,如果开启了会话(访问了session),服务器第一步会查看是否从客户端回传一个名为JSESSIONID的cookie,如果没有则认为这是一次新的会话,会创建一个新的session对象,并用唯一的sessionld为此次会话做一个标志。如果有JESSIONID这个cookie回传,服务器则会根据JSESSIONID这个值去查看是否含有id为]SESSION值的session对象,如果没有则认为是一个新的会话,重新创建一个新的session对象,并标志此次会话;如果找到了相应的session对象,则认为是之前标志过的一次会话,返回该session对象,数据达到共享。
​ 这里提到一个叫做JSESSIONID的cookie,这是一个比较特殊的cookie,当用户请求服务器时,如果访问了sessionI则服务器会创建一个名为JSESSIONID,值为获取到的session (无论是获取到的还是新创建的)的sessionld的cookie对象,并添加到 response对象中,响应给客户端,有效时间为关闭浏览器。
​ 所以Session的底层依赖Cookie来实现。

session域对象

Session用来表示一次会话,在一次会话中数据是可以共享的,这时session作为域对象存在,可以通过setAttribute(name,value)方法向域对象中添加数据,通过getAttribute(name)从域对象中获取数据,通过removeAttribute(name)从域对象中移除数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//获取Session对象
HttpSession session = request.getSession();

//设置session域对象
session.setAttribute("uname","admin");
session.setAttribute("upwd","123456");

//移除session对象
session.removeAttribute("upwd");

//request对象
request.setAttribute("name","zhangsan");

//请求转发到jsp页面(Session对象和request对象都可以传值)
//req.getRequestDispatcher("index.jsp").forward(req,resp);
//重定向到jsp页面(Session可以传值)
response.sendRedirect("index.jsp");

Session对象的销毁

  • 默认时间到期

    tomcat中session默认存活时间为30min,即你不操作界面的时间,一旦有操作,session会重新计时

    1
    2
    3
    4
    //默认的最大不活动时间,单位(分钟)
    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>
  • 自己设定到期时间

    通过session.setMaxInactiveInterval(int)来设置session的最大不活动时间,单位(秒)。

    1
    2
    3
    4
    5
    6
    //获取session对象
    HttpSession session = request.getSession();
    //获取最大不活动时间
    session.getMaxInactiveInterval();
    //设置session的最大不活动时间
    session.setMaxInactiveInterval(15); //15秒
  • 立即销毁

    可以通过session.invalidate()方法让session立刻失效

    1
    2
    //销毁session对象
    session.invalidate();
  • 关闭浏览器

    从前面的JESSIONID可知道,session的底层依赖cookie实现,并且该cookie的有效时间为关闭浏览器,从而session在浏览器关闭时也相当于失效了(因为没有JSESSION再与之对应)。

  • 关闭服务器

    当关闭服务器时,session 销毁。Session失效则意味着此次会话结束,数据共享结束。

ServletContext对象

每一个web应用都有且仅有一个ServletContext对象,又称Application对象,从名称中可知,该对象是与应用程序相关的。在WEB容器启动的时候,会为每一个WEB应用程序创建一个对应的ServletContext对象。

该对象有两大作用,第一、作为域对象用来共享数据,此时数据在整个应用程序中共享;第二、该对象中保存了当前应用程序相关信息。例如可以通过getServerInfo()方法获取当前服务器信息,getRealPath(Stringpath)获取资源的真实路径等。

ServletContext对象的获取

获取ServletContext对象的途径有很多。比如:

  • 通过request对象获取

    1
    ServletContext servletContext = request.getServletContext() ;
  • 通过session对象获取

    1
    ServletContext servletContext = request.getSession(). getservletContext();
  • 通过servletConfig 对象获取在Servlet标准中提供了ServletConfig 方法

    1
    ServletContext servletContext3 = getServletConfig().getServletContext();
  • 直接获取

    1
    ServletContext servletContext4 = getServletContext();
  • 常用方法

    1
    2
    3
    4
    5
    6
    //1、获取当前服务器的版本信息
    String servletInfo = request.getServletContext().getServerInfo();
    System.out.println("当前服务器的版本信息: "+ servletInfo);
    //获取项目真实路径
    String realPath = request.getServletContext().getRealPath("/");
    System.out.println("项目真实路径: "+realPath);

ServletContext域对象

ServletContext 也可当做域对象来使用,通过向ServletContext 中存取数据,可以使得整个应用程序共享某些数据。当然不建议存放过多数据,因为ServletContext 中的数据一旦存储进去没有手动移除将会一直保存。

1
2
3
4
5
6
7
8
9
//获取servletcontext对象
ServletContext servletContext = request.getServletContext();

//设置域对象
servletContext.setAttribute("name" , "zhangsan") ;
/获取域对象
String uname = (String) servletContext.getAttribute("name") ;
//移除域对象
servletContext.removeAttribute("uname") ;

Servlet的三大域对象

request域对象

在一次请求中有效。请求转发有效,重定向失效。

session域对象

在一次会话中有效。请求转发和重定向都有效,session销毁后失效。

servletContext域对象

在整个应用程序中有效。服务器关闭后失效。

文件的上传和下载

文件上传

前台页面

在做文件上传的时候,会有一个上传文件的界面,首先我们需要一个表单,并且表单的请求方式为POST;其次我们的form表单的enctype必须设为”multipart/form-data”,即enctype="multipart/form-data",意思是设置表单的类型为文件上传表单。默认情况下这个表单类型是"application/x-www-form-urlencoded",不能用于文件上传。只有使用了multipart/form-data 才能完整地传递文件数据。

1
2
3
4
5
6
7
8
9
10
11
<!--
文件上传表单
1.表单提交类型method="post"
2.表单类型enctype="multipart/form-data"
3.表单元素类型文件域设置name属性值
-->
<form method="post" action="uploadServlet" enctype="multipart/form-data">
姓名: <input type="text" name="uname" > <br>
文件: <input type="file" name="myfile" > <br>
<button type="submit">提交</button>
</form>

后台设置

使用注解@MultipartConfig将一个Servlet标识为支持文件上传。Servlet将 multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。

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
package Context;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
@WebServlet("/uploadServlet")
@MultipartConfig //如果是文件上次必须加
public class Servlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("文件上传...");
//设置请求编码
request.setCharacterEncoding("UTF-8");
//获取普通参数
String name = request.getParameter("uname");
System.out.println("uname: "+name);

//获取part文件
Part part = request.getPart("myfile");//表单中文件的属性值
//通过part对象得到文件上传名
String filename=part.getSubmittedFileName();
System.out.println("filename"+filename);
//得到文件存放的路径
String filePath = request.getServletContext().getRealPath("/");

System.out.println("文件存放的路径:"+ filePath);
//上次文件到指定目录
part.write(filePath+"/"+filename);
}
}

文件下载

超链接下载

当我们在HTML或JSP页面中使用a标签时,原意是希望能够进行跳转,但当超链接遇到浏览器不识别的资源时会自动下载;当遇见浏览器能够直接显示的资源,浏览器就会默认显示出来,比如txt、png、jpg等。当然我们也可以通过download 属性规定浏览器进行下载。但有些浏览器并不支持。

  • 默认下载

    1
    2
    <!--当超链接遇到浏览器不识别的资源时,会自动下载-->
    <a href="test.zip">超链接下载</ a>
  • 指定download 属性下载

    1
    2
    <!--当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性可进行下载-->
    <a href="test.txt" down1oad>超链接下载</ a>

    download属性可以不写任何信息,会自动使用默认文件名。如果设置了download属性的值,则使用设置的值做为文件名。当用户打开浏览器点击链接的时候就会直接下载文件。

后台实现下载

  • 实现步骤
    1. 需要通过response.setContentType方法设置Content-type头字段的值,为浏览器无法使用某种方式或激活某个程序来处理的MIME类型,例如"application/octet-stream""application/x-msdownload"等。
    2. 需要通过response.setHeader方法设置Content-Disposition头的值为"attachmentfilename=文件名"
    3. 读取下载文件,调用response.getOutputStream方法向客户端写入附件内容。
1
2
3
4
<form action="downdload" >
文件名:<input type="text" name="fileName" placeholder="请输入文件信息">
<button>下载</button>
</form>

在web文件夹里新建了个download文件夹,将可下载的文件放在download文件夹里

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package Context;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@WebServlet("/downdload")
public class donmlode extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//获取参数(文件名)
String fileName = request.getParameter("fileName");
//非空判断 trim():去除字符前后的空格
if(fileName == null || "".equals(fileName.trim())){
response.getWriter().write("请输入要下载的文件名");
response.getWriter().close();
return;
}
//获取图片存放的位置
String path =request.getServletContext().getRealPath("/download/");
//通过路径得到一个file对象
File file = new File(path+fileName);
//判断文件是否存在并且是个标准文件
if(file.exists()&&file.isFile()){
//设置响应类型(浏览器无法使用某种方式或激活某个程序来处理的 MIME类型
response.setContentType("application/x-msdownload");
//设置响应头
response.setHeader("Content-Disposition","attachment;filename=" + fileName);
//得到file文件输入流
InputStream in = new FileInputStream(file);
//得到字节输出流
ServletOutputStream out =response.getOutputStream();
//定义byte数组
byte[] bytes = new byte[1024];
//定义数组
int len=0;
//循环输出
while((len = in.read(bytes)) != -1){
//输出
out.write(bytes,0,len);
}
//关闭资源
out.close();
in.close();
}else {
response.getWriter().write("文件不存在,请重试");
response.getWriter().close();
}
}
}

注:需要下载的文件的文件名不能以数字开头否则找不到文件


Servlet学习
https://changzer.gitee.io/2021/06/10/后端——Servlet学习/
作者
长泽
发布于
2021年6月10日
许可协议