1. Servlet简介
1.1. 什么是Servlet
(1) servlet是运行在Web服务器中的小型Java程序。
(2) servlet通常通过HTTP(超文本传输协议)接收和响应来自Web客户端的请求。1.2. 实现Servlet
(1) 实现Servlet接口
如果实现接口,需要把接口里面的方法都实现。 (2) 继承GenericServlet, HttpServlet类 如果继承类,不需要把类中的方法都实现。 (3) 需要web服务器知道Java程序不是一个普通的java程序,而是一个servlet 通过配置进行操作,在web项目中,web.xml里面进行配置。1.3. Servlet的入门程序
写一个servlet,实现向页面输出内容hello servlet
第一步,创建一个类,使用这个类继承GenericServlet类; 第二步,实现类里面的service(ServletRequest req,ServletResponse res); * ServletRequest代表请求 * ServletResponse代表响应 第三步,在Servlet中使用ServletResponse对象向页面输出内容。调用getWriter()方法; 第四步,在web项目中的web.xml进行配置,让服务器知道是一个servletservletDemo1 com.gaogao.servlet.ServletDemo1 servletDemo1 /hello
2. Servlet的执行过程
(1) 根据在浏览器地址栏输入的地址,找web.xml中相同的url-pattern;
(2) 找到了url-pattern,对应的servlet-name; (3) 根据找到的servlet-name到另外一个标签里面(servlet)相同名称的servlet-name; (4) 在servlet标签里面找到了相同名称的servlet-name,找servlet的包类路径servlet-class; Servlet其实是利用反射原理,让servlet里面的service()方法执行。servlet的生命周期:从servlet创建到servlet销毁的过程。
在servlet接口里面有五个方法,其中有三个方法是与生命周期相关的方法: (1) init()方法,在servlet创建时候执行这个方法,执行一次,servlet在第一次访问时候创建。 (2) service()方法,在每次访问servlet时候会执行这个方法,执行多次。 (3) destroy()方法,销毁servlet时候执行这个方法,执行一次。4. Servlet开发细节的问题
4.1. HttpServletRequest和ServletRequest关系&HttpServletResponse和ServletResponse关系
servletRequest和serlvetResponse不带协议 HttpServletRequest和HttpServletResponse带协议 sun公司设计时候,认为未来互联网的发展有很多的协议,目前只有http协议。4.2. GenericServlet类两个init方法
查看源码,发现有参数init方法最终也要调用init没有参数的方法,直接使用init没有参数的方法就可以了。
4.3. HttpServlet类里service和doxxx关系
根据提交的方式,调用不同的doXX的方法,比如提交方式是get,调用doGet方法,比如提交方式是post,调用doPost方法;
一般在开发中,直接写doGet和doPost方法就可以了; 一般在创建servlet时候,直接继承HttpServlet实现servlet。4.4. 服务器启动时候创建servlet
通过配置文件进行配置,在servlet标签里面写标签:
正整数的值
4.5. 简化编程
当通过get提交方式时候,实现从1加到100;
当通过post提交方式时候,实现从1加到100; 无论什么提交方式,代码都能执行到,在dopost方法里面调用doget方法。5. url-pattern的配置
5.1. 配置有三种方式
第一种方式:完全路径匹配,写法 :/aa
,/hello
/aa/*
第三种方式:扩展名匹配,写法: *.do
, *.action
5.2. 优先级
完全路径匹配 > 目录匹配 > 扩展名匹配
5.3. 练习
对于如下的一些映射关系:
Servlet1 映射到/abc/*
Servlet2 映射到/*
Servlet3 映射到 /abc
Servlet4 映射到 *.do
问题: 1、当请求URL为"/abc/a.html"
,"/abc/*"
和"/*"
都匹配,哪个servlet响应? Servlet1 2、当请求URL为"/abc"
时,"/abc/*"
和"/abc"
都匹配,哪个servlet响应? Servlet3 3、当请求URL为"/abc/a.do"
时,"/abc/*"
和"*.do"
都匹配,哪个servlet响应? Servlet1 4、当请求URL为"/a.do"
时,"/*"
和"*.do"
都匹配,哪个servlet响应? Servlet2 5、当请求URL为"/xxx/yyy/a.do"
时,"/*"
和"*.do"
都匹配,哪个servlet响应? Servlet2 6. 开发中路径的问题
6.1. 相对路径
在html文件中引入图片:
第一种:图片和html在同一个目录下面,直接写图片的名称 第二种:图片在html的上层目录, 写 ../ 表示上层目录 第三种:图片在html的下层目录, 直接写目录名称和图片名称6.2. 绝对路径(一般开发中都使用)
第一种写法:http://ip地址+端口号/文件的路径
<img src="http://127.0.0.1/day07-3/path02/a.jpg"/>
第二种写法:直接写 /项目名称/文件路径
<img src="/day07-3/path01/cc/c.jpg"/>
7. 请求重定向和请求转发
7.1. 请求重定向
(1) 使用的是客户端路径
(2) 重定向请求两次,使用的是客户端路径,携带项目名称,比如/day07/demo3 请求重定向可以使用一下两种方式: a) 设置状态码302+头信息Location实现重定向操作 b) 使用response.sendRedirect()实现重定向操作public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException { //得到输入的用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //根据用户名和密码判断,(用户名admin、密码123456),判断正确则向页面输出login success内容 if("admin".equals(username) && "123456".equals(password)) { //向页面输出内容 response.getWriter().write("login success"); } else { //重定向到登录页面 //设置状态码// response.setStatus(302); //使用头Location完成重定向// response.setHeader("Location", "/day08-1/login.html"); //简写方式 response.sendRedirect("/day08-1/login.html"); } } public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
定时跳转的案例
public class RefreshServlet extends HttpServlet { /** * 定时跳转 */ public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException { //使用头信息Refresh实现,表示5秒后跳转到指定的url路径 response.setHeader("Refresh", "5;url=/day08-1/login.html"); //提示 response.setContentType("text/html;charset=utf-8"); response.getWriter().write("将在5秒之后跳转到登录页面"); } public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException { doGet(request, response); }}
7.2. 请求转发
(1) 使用的是服务端路径
(2) 转发请求一次,使用的是服务器端路径,不需要携带项目名称,比如/demo4 示例代码:public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException { //获取表单提交的用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); //判断 用户名 admin,密码 123456 if("admin".equals(username) && "123456".equals(password)) { //登录成功 response.getWriter().write("login success"); } else { //登录失败,给request设置域属性msg,并且转发到登录页面,并且将错误信息传递过去 request.setAttribute("msg", "用户名或者密码错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); } } public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { doGet(request, response); }}
8. ServletConfig对象
8.1. 获取ServletConfig对象
直接使用方法创建对象getServletConfig()。
8.2. 得到当前运行的servlet的名称
(1)web.xml中<servlet-name>ConfigDemo1</servlet-name>
8.3. 创建servletContext对象
(1)ServletContext getServletContext()
(2)一般都使用getServletContext()方法8.4. 获取初始化参数
(1)在web.xml中进行配置初始化参数
在servlet标签里面进行配置 (2)String getInitParameter(String name) :根据名称得到值(参数是初始化参数名称) 代码://得到servletconfig对象ServletConfig config = getServletConfig();//getInitParameter(String name)String username = config.getInitParameter("username");String password = config.getInitParameter("password");
(3)Enumeration getInitParameterNames() :得到所有的初始化参数的名称
代码://得到servletconfig对象ServletConfig config = getServletConfig();//得到所有的初始化参数名称EnumerationenumrEnumeration =config.getInitParameterNames();//得到每个参数的名称while(enumrEnumeration.hasMoreElements()) { String name = enumrEnumeration.nextElement(); //根据name得到值 String value = config.getInitParameter(name); System.out.println(name+" :: "+value);}
9. ServletContext对象
9.1. 创建ServletContext对象
第一种方式,使用ServletConfig对象里面的方法 getServletContext()
第二种方式,直接使用 getServletContext()9.2. 获取全局的初始化参数
(1)配置全局初始化参数
url localhost
(2)String getInitParameter(String name),根据名称得到全局初始化参数的值:
//得到servletContext对象ServletContext context = getServletContext();//根据名称得到全局初始化参数的值String url = context.getInitParameter("url");String name = context.getInitParameter("name");
(3)Enumeration getInitParameterNames(),得到所有的全局初始化参数的名称:
//得到servletContext对象ServletContext context = getServletContext();//使用方法得到所有的全局初始化参数的名称EnumerationenumrEnumeration = context.getInitParameterNames();//得到每个全局初始化参数的名称while(enumrEnumeration.hasMoreElements()) { String name = enumrEnumeration.nextElement(); String value = context.getInitParameter(name); System.out.println(name+" :: "+value);}
9.3. servletContext域对象
在启动tomcat服务器时候,会为每个项目创建一个servletContext对象,在这个项目里面如果通过servlet1向servletContext里面设置一个值,在这个项目里面的其他的servlet里面都可以获得这个值。
(1)servletContext域对象:在一定的范围内,存值和取值,范围是整个web项目 (2)存值:setAttribute(String name, Object object) (3)取值:getAttribute(String name) (4)首先创建servlet1,通过servlet1向servletContext里面设置一个值,其次,再创建servlet2,在servlet2获取通过servlet1设置的值9.4. 练习:统计网站的访问次数
创建一个servlet,每次访问这个servlet计算一次访问
实现的步骤(分析图)10. ServletContext获取项目资源
10.1. 传统方式获取web项目中的文件
(1)创建web项目,创建properties文件
(2)得到要操作文件的输入流,使用相对路径 * classes/db1.properties : 相对路径 * 相对虚拟机的位置 * 在web项目中,虚拟机在tomcat启动时候,tomcat在bin里面 (3)使用传统方式里面的相对路径,不能读取web项目中的文件10.2. ServletContext读取项目中的文件
(1)InputStream getResourceAsStream(java.lang.String path),得到要操作文件的输入流
(a)第一个操作:文件放到src下面 路径:第一个位置/,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径 代码:InputStream in = context.getResourceAsStream("/WEB-INF/classes/db1.properties");
(b)第二个操作:文件放到包里面
路径:第一个位置/理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径InputStream in= context.getResourceAsStream("/WEB-INF/classes/cn/itcast/read/db2.properties");
(c)第三个操作:文件放到webroot下面
路径:第一个位置/理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径 代码:InputStream in = context.getResourceAsStream("/db3.properties");
*注意:当把文件放到和webroot同级的目录下面,这个文件不会部署到tomcat里面,所以使用servletContext对里面getResourceAsStream方法不能得到文件的内容。
(2)String getRealPath(java.lang.String path),得到要操作文件的完全路径(带盘符的路径)
参数:和getResourceAsStream类似的 第一个位置/,项目名称;后面写文件在tomcat的webapps里面的具体的路径。 代码://使用getRealPath方法String path = context.getRealPath("/db3.properties");//C:\Users\asus\Desktop\javaweb\day06\apache-tomcat-7.0.53\webapps\day07-7\db3.properties//得到要操作文件的输入流InputStream in = new FileInputStream(path);
11. 类加载器读取文件
读取的文件的位置是 classes里面的文件
得到类加载器: (1)首先得到Class *第一种方式:类名.class *第二种方式:对象.getClass() *第三种方式:Class.forName(“包类路径”)(2)使用Class得到类加载器
代码://得到类的ClassClass clazz = ServletDemo1.class;//得到类加载器ClassLoader loader = clazz.getClassLoader();//得到要操作文件的输入流//文件的路径,因为读取的classes里面的文件,直接写文件的名称InputStream in = loader.getResourceAsStream("db1.properties");
12. 默认的servlet
比如在浏览器的地址栏随便输入一个地址,出现404,资源找不到,这个效果是由默认的servlet实现的。在tomcat的conf里面找到web.xml,有对默认servlet的配置:
(a)如果自己创建servlet,让这个servlet在启动时候创建,<load-on-startup>大于1的值</load-on-startup>
(b)默认servlet的配置里面url-pattern是/,当把自己创建的servlet的url-pattern写成/,这个servlet就会成为一个默认的servlet default org.apache.catalina.servlets.DefaultServlet debug 0 listings false 1 default /
在默认的servlet的初始化参数里面有 listings,当把这个参数的值设置成true之后,当直接访问web项目中文件夹时候,会把文件夹里面的所有内容显示出来。
13. Response和Request
request:代表请求,在浏览器的地址栏输入地址,点击回车,这个过程称为一次请求;
response:代表响应,服务器端根据客户端的请求,返回数据到浏览器中进行显示,这个过程称为一次响应。14. Response对象
HttpServletResponse,是一个接口,父接口是ServletResponse,代表响应对象。
http的响应包含三部分组成: (1)第一部分:响应行,响应行中包含了状态码 常用方法:方法 | 作用 |
---|---|
setStatus(int sc) | 设置状态码 如response.setStatus(302) |
(2)第二部分:响应头
响应头是key-value结构,一个key可以有一个value,一个key也可以有多个value。 常用方法:方法 | 作用 |
---|---|
setHeader(java.lang.String name, java.lang.String value) | 设置响应头 两个参数:第一个参数是响应名称;第二个参数值 |
setIntHeader(java.lang.String name, int value) | 针对int类型值的方法 |
setDateHeader(java.lang.String name, long date) | 值long类型,是毫秒数(1970 1 1至今的毫秒数) |
addHeader(java.lang.String name, java.lang.String value) | 设置响应头 两个参数:第一个参数是响应名称;第二个参数值 |
addIntHeader(java.lang.String name, int value) | 针对int类型值的方法 |
addDateHeader(java.lang.String name, long date) | 值long类型,是毫秒数 |
setHeader和addHeader的区别:
setHeader会将之前的值覆盖掉,而addHeader可以添加多个响应头。(3)第三部分:响应体,向页面显示的内容
常用方法:方法 | 作用 |
---|---|
getWriter() | 使用字符流向页面输出内容 |
getOutputStream() | 使用字节流向页面输出内容 |
14.1. 重定向的案例
当注册一个网站,注册完成之后,5秒之后跳转到登录页面。
实现方式:使用头信息Refresh实现response.setHeader("Refresh","在几秒值后跳转;url=要跳转到页面的路径");
创建servlet,在servlet实现,在五秒之后跳转到一个页面:
response.setHeader("Refresh", "5;url=/day08-1/login.html");
14.2. 设置响应体(向页面输出内容)
14.2.1. 使用字节流向页面输出内容
代码:
response.getOutputStream().write("输出的内容".getBytes());
如果向页面输出中文,根据不同的浏览器的编码设置会产生乱码问题。产生原因:浏览器的编码和字节数组的编码不一致。
解决方法:让浏览器的编码和字节数组的编码一致 1、设置浏览器的编码 2、设置字节数组的编码//设置浏览器的编码 使用头信息 Content-Typeresponse.setHeader("Content-Type", "text/html;charset=utf-8");//设置字节数组的编码response.getOutputStream().write("字节流中文".getBytes("utf-8"));
14.2.2. 使用字符流向页面输出内容
代码:
response.getWriter().write("response");
如果使用字符流向页面输出中文,一定会有乱码
原因:使用字符流向页面输出内容;首先会把内容放到response缓冲区里面,response缓冲区默认的编码是 iso8859-1,这个编码不支持中文,一定会有乱码。 解决方法:response缓冲区的编码和浏览器的编码一致。 1、设置response缓冲区的编码 2、设置浏览器的编码//设置response缓冲区的编码response.setCharacterEncoding("utf-8");//设置浏览器的编码response.setHeader("Content-Type", "text/html;charset=utf-8");response.getWriter().write("字符流中文");
14.3. response的流的注意事项
(1)使用字符流向页面输出中文乱码问题解决,简写方式
response.setContentType("text/html;charset=utf-8");
(2)字节流和字符流是互斥的
(3)使用字符流不能直接向页面输出数字//根据数字到码表中查询数字对应的字符,把字符输出response.setCharacterEncoding("utf-8");response.getWriter().write(111);
15. 文件下载的案例
(1) 设置头信息 Content-Disposition,无论是什么格式的文件都以下载方式打开
(2) 在服务器上面有一个可以下载的文件 (3) 从服务器上拿到这个文件(使用文件输入流得到文件) (4) 使用输出流把文件写到浏览器public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { // 得到要下载文件的路径 String path = getServletContext().getRealPath("/down/a.zip"); // 得到文件的名称 int lens = path.lastIndexOf("\\"); String filename = path.substring(lens + 1); // 设置头信息 response.setHeader("Content-Disposition","attachment;filename=" + filename); // 得到文件的输入流 InputStream in = new FileInputStream(path); // 使用输出流操作 OutputStream out = response.getOutputStream(); // 流对接 int len = 0; byte[] b = new byte[1024]; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } // 关闭流 in.close();}
16. Request对象
request代表请求的对象,HttpServletRequest接口,父接口是ServletRequest。
16.1. 获取请求行的信息
方法 | 作用 |
---|---|
getMethod() | 得到http请求方式 |
getRequestURI() | 得到请求地址(不包含ip+端口号) |
getProtocol() | 得到http的版本 |
16.2. 获取请求头的信息
方法 | 作用 |
---|---|
getHeader(java.lang.String name) | 根据名称得到请求头的值,如:头信息 User-Agent:获取当前请求的浏览器的类型 String agent = request.getHeader(“User-Agent”); |
16.3. 获取客户机的信息
方法 | 作用 |
---|---|
getContextPath() | 请求项目的名称 |
getRequestURL() | 客户端发送的请求的路径 |
getRemoteAddr() | 获取当前客户端的ip地址 |
16.4. 获取表单提交的数据
(1)String getParameter(java.lang.String name) :参数是表单输入项name属性的值,根据名称得到输入的值
代码:String username = request.getParameter("username");String password = request.getParameter("password");
(2)String[] getParameterValues(java.lang.String name) :参数是表单输入项name的值,针对复选框的情况
代码:String[] loves = request.getParameterValues("love");
(3)String[] getParameterValues(java.lang.String name) :
返回的是map集合,key是表单输入项name属性的值,value是输入的值 代码:Mapmap = request.getParameterMap();//得到map集合里面的key和value,遍历mapSet keys = map.keySet();//遍历set集合for (String key : keys) {//根据key得到valueString[] values = map.get(key); //key和对应的value输出(表单输入项name的属性值和输入的值) System.out.println(key+" :: "+Arrays.toString(values));}
(4)Enumeration
16.5. 获取表单提交的中文数据乱码问题
(1)post提交方式解决方法
使用post提交数据时候,会把数据放到request缓冲区里面,request缓冲区默认的编码 iso8859-1,不支持中文。 解决方法: 设置request缓冲区的编码 代码:request.setCharacterEncoding("utf-8");
(2)get提交中文乱码解决
有三种方式 第一种:修改tomcat的配置文件第二种:把数据先编码,再进行解码
第三种:使用string构造进行编码,new String(“”); 代码:username = new String(username.getBytes("iso8859-1"),"utf-8");
16.6. request是域对象
(1) 域对象:在一定的范围内,可以存值和取值。
(2) servletContext域对象:范围是整个web项目,存值setAttribute方法和取值getAttribute方法。 (3) request也是一个域对象:范围是一次请求,存值和取值。 向request域里面存值的方法:setAttribute(java.lang.String name, java.lang.Object o); 从request域里面取值的方法:getAttribute(java.lang.String name)。 (4) request域对象范围是一次请求,经常和转发一起使用 代码request.getRequestDispatcher(“转发的路径不带项目名称”).forward(..); (5) 举例演示request域对象 创建servlet1,在servlet1里面向request域里面设置一个值,最后转发到servlet2里面://向request域里面设置一个值request.setAttribute("msg", "itcast100");//转发到servlet2request.getRequestDispatcher("/servlet2").forward(request, response);
创建servlet2,在servlet2里面获取通过servlet1向request域里面设置的那个值
//获取通过servlet1向request里面设置的值response.getWriter().write(""+request.getAttribute("msg"));
16.7. 重定向和转发的区别
(1)重定向
请求次数:重定向请求两次,请求的地址带项目名称 实现方式:302+Location实现重定向的操作 实现代码:response.sendRedirect(“路径 带项目名称”);(2)转发
请求次数:转发请求一次,路径不需要带项目名称(在服务器内部进行操作) 实现代码:request.getRequestDispatcher(“转发的路径 不带项目名称”).forward(request, response);(3)重定向:从一个网站到另外的一个网站
转发:请求的过程中需要携带数据操作17. 文件上传
17.1. 什么是文件上传
把本地的文件存储到服务器上,这个过程称为文件的上传。比如,网盘、qq空间。
17.2. 文件上传的实现
(1) jspSmartUpload:应用在jsp的模型一
适于嵌入执行上传下载操作的JSP文件中 (2) fileUpload:应用在jsp的模型二(mvc) FileUpload 是 Apache commons下面的一个子项目 组件FileUpload依赖于Commons IO组件 导入jar包(有两个jar包) (3) 要想使用第三方的技术实现文件的上传,首先导入jar包17.3. 文件上传需要满足的条件
第一个要求:表单,提交方式是post
get提交方式:地址栏会携带数据,get大小有限制 第二个要求:在表单里面有文件上传项,必须有name属性 第三个要求:在form里面,设置一个属性值enctype,设置为multipart/form-data18. 文件上传的原理的分析(画图)
首先,找到分割线;
第二,根据分割线区别不同的项; 第三,普通输入项得到值; 第四,文件上传项,得到文件的内容,把内容写到服务器里面的一个文件中(使用输入流得到文件的上传内容,使用输出流把文件内的内容写到服务器上)19. 代码实现文件上传
19.1. 文件上传代码实现的步骤
第一步:创建磁盘文件项工厂
new DiskFileItemFactory();
- 1
第二步:创建核心上传类
new ServletFileUpload(FileItemFactory fileItemFactory);
第三步:使用核心上传类解析request对象
parseRequest(javax.servlet.http.HttpServletRequest request)返回的List集合,集合里面有多个FileItem,List
第四步:遍历list集合,得到每个FileItem
第五步:判断是普通输入项还是文件上传项
boolean isFormField()
第六步:如果是普通输入项得到值;如果是文件上传项编写上传的代码
普输入项:getFieldName():得到普通输入项name的属性的值getString():得到普通输入项里面输入的值
文件上传项:
得到通过表单提交过了的文件的输入流,getInputStream()创建输出流,把文件的输入流写到服务器的一个文件中。
19.2. 代码实现
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 创建磁盘文件项工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 设置缓冲区大小和临时文件路径 factory.setSizeThreshold(1 * 1024 * 1024); // 字节 String temp = getServletContext().getRealPath("/temp"); factory.setRepository(new File(temp)); // 创建核心上传类 ServletFileUpload fileUpload = new ServletFileUpload(factory); // 设置上传文件名的编码 fileUpload.setHeaderEncoding("utf-8"); // 设置上传文件的大小 // fileUpload.setFileSizeMax(1*1024*1024); //字节 // 解析request对象 Listlist = fileUpload.parseRequest(request); // 遍历list集合 for (FileItem fileItem : list) { // 判断普通输入项 if (fileItem.isFormField()) { // 得到普通输入项的name的属性值和输入的值 String name = fileItem.getFieldName(); String value = fileItem.getString("utf-8"); System.out.println(name + " :: " + value); } else { // 得到上传文件的名称 getName() // 在某些浏览器里面,得到的是全路径名称 c:\aa\1.txt String filename = fileItem.getName(); // 判断是否带 \,如果带 \进行截取 int lens = filename.lastIndexOf("\\"); if (lens != -1) { // 截取 filename = filename.substring(lens + 1); } // 在文件名称里面添加随机的唯一的值 String uuid = UUID.randomUUID().toString(); // uuid_filename filename = uuid + "_" + filename; // 得到提交的文件的输入流 InputStream in = fileItem.getInputStream(); // 得到文件夹的带盘符的路径 ,servletContext对象 String path = getServletContext().getRealPath("/upload"); // 创建输出流 OutputStream out = new FileOutputStream(path + "/" + filename); // 流对接 int len = 0; byte[] b = new byte[1024]; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } in.close(); out.close(); // 删除临时文件 fileItem.delete(); } } } catch (Exception e) { e.printStackTrace(); } }
20. 核心api的使用
DiskFileItemFactory(int sizeThreshold, java.io.File repository)
有两个参数: 第一个参数设置上传文件的缓冲区的大小; 第二个参数是如果上传文件超出了缓冲区,产生临时文件,设置临时文件路径。 DiskFileItemFactory() setSizeThreshold(int sizeThreshold):设置上传文件的缓冲区的大小 setRepository(java.io.File repository):设置临时文件路径20.2. ServletFileUpload
ServletFileUpload(FileItemFactory fileItemFactory)
方法 | 解释 |
---|---|
parseRequest(javax.servlet.http.HttpServletRequest request) | 解析request对象,返回List集合,集合里面每个部分是FileItem。 |
setHeaderEncoding(java.lang.String encoding) | 设置上传文件名称的编码 |
setFileSizeMax(long fileSizeMax) | 设置单个上传文件的大小 |
setSizeMax(long sizeMax) | 设置上传文件的总大小 |
20.3. FileItem:文件项
方法 | 解释 |
---|---|
boolean isFormField() | 判断是否是普通输入项,返回boolean,如果返回true是普通输入项 |
getFieldName() | 得到普通输入项name的属性值 |
getString() | 得到普通输入项输入的值 |
getString(java.lang.String encoding) | 输入的值有中文,设置编码 |
getName() | 得到上传文件的名称。在某些浏览器里面得到带路径的名称,截取操作 |
getInputStream() | 得到表单提交的文件的输入流 |
delete() | 删除临时文件 |
21. 文件上传问题的解决
文件重名的问题:如果上传了多个项目名称的文件,最后一次上传的文件,把之后的文件给覆盖了。
解决方法:在上传的文件名称前面,添加一个随机的唯一的字符串,保证每个文件名称都是唯一的一个值: 第一种方式:使用当前时间毫秒数实现 第二种方式:使用UUID工具类实现 代码://在文件名称里面添加随机的唯一的值String uuid = UUID.randomUUID().toString();//uuid_filenamefilename = uuid+"_"+filename;