1、表单中有文件上传项时,不能用常用的request.getParameter()获取表单中的值
此时需要使用第三方jar包fileupload包和io包里面相关的类来完成对于表单值的获取,jar包的下载地址:
https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi
https://commons.apache.org/proper/commons-io/download_io.cgi
例如此时有这样一个表单,存在于regist.jsp中,其中registServletPath是RegistServlet的对外访问路径
<!--
表单中有文件上传项的条件
1. 表单必须是post提交方式
2. 表单中必须有文件上传项,文件上传项必须有name属性和值
3. 表单的enctype属性必须设置为multipart/form-data
-->
<form action="<%= registServletPath %>" method="post" enctype="multipart/form-data">
<table>
<tr>
<td class="td1">用户名</td>
<td><input type="text" class="input1" name="username"></td>
</tr>
<tr>
<td class="td1">密码</td>
<td><input type="password" class="input1" name="password"></td>
</tr>
<tr>
<td class="td1">昵称</td>
<td><input type="text" class="input1" name="nickname"></td>
</tr>
<tr>
<td class="td1">性别</td>
<td>
<input type="radio" name="sex" value="male">男
<input type="radio" name="sex" value="female">女
</td>
</tr>
<tr>
<td class="td1">上传头像</td>
<td><input type="file" id="photo" name="upload"></td>
</tr>
<tr>
<td class="td1">兴趣爱好</td>
<td>
<label>
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="足球">足球
<input type="checkbox" name="hobby" value="排球">排球
<input type="checkbox" name="hobby" value="羽毛球">羽毛球
</label>
</td>
</tr>
<tr>
<td colspan="2">
<div class="btn-red">
<input type="submit" value="注册" id="reg-btn">
</div>
</td>
</tr>
</table>
</form>
此时我们点击注册后,将表单信息提交给RegistServlet处理:
/**
* 用户注册Servlet
*/
@WebServlet(name = "RegistServlet", urlPatterns = "/RegistServlet")
public class RegistServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//数据的接收,由于表单内有文件上传项,因此不能使用传统的request.getParameter(String name)来接收表单数据,
// 需要使用第三方jar包fileupload来进行相应表单数据的获取
//文件上传基本操作:
try {
//1、创建一个磁盘文件项工厂对象
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//2、创建一个核心解析类对象
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
//3、解析request请求,返回的是List集合,集合中存放的是FileItem对象,一个FileItem对应的是表单中的一个表单项
List<FileItem> list = servletFileUpload.parseRequest(req);
//定义一个List集合,用于保存兴趣爱好数据
List<String> hobbyList = new ArrayList<>();
//4、遍历集合,获得每个FileItem,判断是表单项还是文件上传项
for (FileItem fileItem : list) {
//判断是普通表单项还是文件上传项
if (fileItem.isFormField()) {
//普通表单项
//接收表单项参数的值
String name = fileItem.getFieldName();//获得表单项的name属性的值
String value = fileItem.getString("UTF-8");//获得表单项的值
System.out.println(name + " " + value);
//接收复选框的数据
if ("hobby".equals(name)) {
String hobbyValue = fileItem.getString("UTF-8");
//接收到一个值,将这个值存入到hobbyList集合中
hobbyList.add(hobbyValue);
hobbyValue = hobbyList.toString().substring(1, hobbyList.toString().length() - 1); //[xxx,yyy]
System.out.println(name + " " + hobbyValue);
}
}else {
//文件上传项
//完成文件上传功能
//文件上传项
/**
* 文件上传功能:
*
*/
//获得用户上传的文件的名称
String fileName = fileItem.getName();
//若上传的文件不为空,并且文件名也不为空字符串
if (fileName != null && !fileName.equals("")) {
//获得唯一文件名
String uuidFileName = UploadUtils.getUniqueFileName(fileName);
//获得上传的文件的输入流
InputStream is = fileItem.getInputStream();
//获得上传文件要保存到的位置路径,此处保存在upload文件夹下
String path = this.getServletContext().getRealPath("/upload");
System.out.println("path:" + path);
//将输入流对接到输出流,完成文件上传
url = path + "\\" + uuidFileName;
System.out.println("url:" + url);
OutputStream os = new FileOutputStream(url);
int length = 0;
byte[] b = new byte[1024];
while ((length = is.read(b))!= -1) {
os.write(b, 0, length);
}
is.close();
os.close();
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
注意,在文件上传功能中,我们将上传的保存在了upload文件夹下,如果我们使用的是IDEA,那么我们应该在out\artifacts\项目名_war_exploded下创建一个upload文件夹,而不是在web文件夹下创建upload
在文件上传功能中我们使用到了UUID的一个工具类来将每个上传的文件都设置为一个唯一的名称,这个工具类如下:
/**
* 文件上传工具类
*/
public class UploadUtils {
/**
* 生成唯一的文件名
*/
public static String getUniqueFileName (String fileName) {
//将文件名的前面部分进行截取:xx.jpg ---> .jpg,从而获取到文件扩展名
int idx = fileName.lastIndexOf(".");
String extension = fileName.substring(idx);
//得到随机字符串作为文件名,同时去除生成的随机字符串中的"-"
String uuidFileName = UUID.randomUUID().toString().replace("-", "") + extension;
return uuidFileName;
}
}
2、使用IDEA时启动Tomcat失败
今天在学习Servlet的时候发现IDEA中启动Tomcat总是失败,控制台分别报了下面三个错误:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/reglogin]]
......
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/reglogin]]
......
javax.management.RuntimeOperationsException: Exception invoking method manageApp
......
经过研究发现原来是新导入的包commons-io和commons-fileupload的问题,解决方法如下:
- 进入Project Structure
- 进入Artifacts
- 点击最下方的fix
3、使用JSTL报错:The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be resolved in either web.xml or the jar files deployed with this application
出现这个问题的原因是虽然JSTL的jar包加进了ide项目中,但在tomcat发布的应用WEB-INF/lib下没有,这是工具发布项目的问题,因此我们需要将JSTL的jar包再添加进去,如果你使用的是IDEA,那么可以按照我的做法:
- 进入project structure
- 进入Artifacts
- 在右边Available Elements栏中找到JSTL的jar包
- 右键点击jar包,再点击put into /WEB-INF/lib
- Apply