我是靠谱客的博主 冷酷飞鸟,最近开发中收集的这篇文章主要介绍后台系统四:【新增】功能;(FileUpload组件) 0.新增功能需要完成的功能概述:1.将新增页create.html添加到项目中2.在ManagementController类中,添加访问create.jsp的入口3.编写create.jsp:为文件上传做好准备4.在ManagementController类中,添加接收create.jsp表单提交的方法; 5.启动程序:(附加一点说明:Tomcat发布目录),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

 0.新增功能需要完成的功能概述:

1.将新增页create.html添加到项目中

2.在ManagementController类中,添加访问create.jsp的入口

3.编写create.jsp:为文件上传做好准备

4.在ManagementController类中,添加接收create.jsp表单提交的方法;

(1)不借助第三方组件,“在服务器端”采用传统的策略处理【设计文件上传的请求】时:是不行的;

(1.1)演示1:如果不设置form表单的编码方式:enctype="multipart/form-data";

(1.2)演示2:设置form表单的编码方式:enctype="multipart/form-data";

结论:通过上面的演示可以知道:不借助第三方组件,“在服务器端”采用传统的策略处理【设计文件上传的请求】时:是不行的;

(2)利用FileUpload组件实现文件上传(非常重要)

(2.1)FileUpload简介,下载:

(2.2)利用FileUpload组件实现文件上传

(2.3)文件上传后,接下来的任务,就是将这个form表单提交过来的数据,新增到存储数据的xml文件中!!!

(3)向xml中添加数据

(3.1)在XmlDataSource工具类中,编写添加的方法

(3.2)在Dao中编写create()方法,向xml中添加数据;

(3.3)在Service中编写:create()方法;

(3.4)编写Controller部分:

(3.5)最后补充一点:属性中有id(自增,唯一标识对象)属性的时候,javaBean一般不添加有参构造;

 5.启动程序:(附加一点说明:Tomcat发布目录)

(1)启动应用,观察效果

(2)再一点说明


 0.新增功能需要完成的功能概述:

实现思路:


1.将新增页create.html添加到项目中

create.html外部文件引入: create.html是新增油画的表单页:打开create.html:可以看到这个效果:

将create.html添加到工程中:

<%@page contentType="text/html;charset=utf-8"%>
<!-- 新增油画页面 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>新增油画</title>
<link rel="stylesheet" type="text/css" href="csscreate.css">
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
</head>
<body>
	<div class="container">
		<fieldset>
			<legend>新增油画</legend>
			<form action="" method="post"
				autocomplete="off">
				<ul class="ulform">
					<li>
						<span>油画名称</span>
						<span id="errPname"></span>
						<input id="pname" name="pname" />
					</li>
					<li>
						<span>油画类型</span>
						<span id="errCategory"></span>
						<select id="category" name="category">
							<option value="-1">请选择油画类型</option>
							<option value="1">现实主义</option>
							<option value="2">抽象主义</option>
						</select>
					</li>
					<li>
						<span>油画价格</span>
						<span id="errPrice"></span>
						<input id="price" name="price"/>
					</li>
					<li>
						<span>作品预览</span>
						<span id="errPainting"></span>
						<input id="painting" name="painting" type="file" 
							style="padding-left: 0px;" accept="image/*" />
					</li>

					<li>
						<span>详细描述</span>
						<span id="errDescription"></span>
						<textarea
							id="description" name="description"></textarea>
					</li>
					<li style="text-align: center;">
						<button type="submit" class="btn-button">提交表单</button>
					</li>
				</ul>
			</form>
		</fieldset>
	</div>

</body>
</html>

可以看到,create.jsp里面就是一个form表单;


2.在ManagementController类中,添加访问create.jsp的入口

因为,在工程中,所有JSP对外是不可见的,所以需要在Controller这只一个跳转,作为访问create.jsp的入口

而在https://blog.csdn.net/csucsgoat/article/details/114897829这篇博客中创建的ManagementController类,ManagementController类需要完成,【增】,【删】,【改】,【查】的操作的;自然新增文件这条业务的Controller部分也是在ManagementController这个类中写的:

package com.imooc.mgallery.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.imooc.mgallery.service.PaintingService;
import com.imooc.mgallery.utils.PageModel;

/**
 * 后台管理功能Controller;
 * 后台系统,所需要的增,删,改,查的操作,都在这一个Controller类中完成;
 * Servlet implementation class ManagementController
 */
@WebServlet("/management")
public class ManagementController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	// 创建PaintingService对象;;
	// 即无论是前台系统的PaintingController,还是后台系统的ManagementController都调用PaintingService中提供的方法;
	private PaintingService paintingService = new PaintingService();
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ManagementController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求体中的字符集编码方式;;;
		// get请求没有请求体,所以,这个语句是为doPost()方法中执行doGet(request,response)后,跳转过来的post请求来设置的;
		// 即这条代码是为doPost()来进行服务的;
		request.setCharacterEncoding("UTF-8");
		// 设置响应的字符集编码方式
		response.setContentType("text/html;charset=utf-8");
		
		String method = request.getParameter("method");
		if(method.equals("list")) {  // 当前台传入的method参数值为“list”的时候,代表是分页请求,调用定义的list方法;
			this.list(request,response);  // 然后,将分页处理的代码写在list方法中就可以了;
		}else if(method.equals("delete")) {  // 当method参数值为“delete”时,表示是删除请求,调用定义的delete方法;
			this.delete(request, response);
		}else if(method.equals("show_create")) {
			// method参数为“show_create”,表示是新增;调用新增的方法,跳转到create.jsp
			this.showCreatePage(request, response);
		}
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response); // doPost调用了doGet()方法,所以,把逻辑代码都写在doGet方法中就可以了;
	}
	
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String p = request.getParameter("p");
		String r = request.getParameter("r");
		if(p==null) {
			p = "1";
		}
		if(r==null) {
			r = "6";
		}
		PageModel pageModel = paintingService.pagination(Integer.parseInt(p), Integer.parseInt(r));
		request.setAttribute("pageModel", pageModel);
		request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);
	}
	private void delete(HttpServletRequest request, HttpServletResponse response) {
		
	}
	
	/**
	 * 这个方法,是一个纯粹的入口;
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showCreatePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}

}

 ManagementController类的几点说明:

      (1)首先,如果请求中method参数值为“show_create”时,就调用showCreatePage()方法;

else if(method.equals("show_create")) {
			// method参数为“show_create”,表示是新增;调用新增的方法,跳转到create.jsp
			this.showCreatePage(request, response);
		}

      (2)showCreatePage()方法就是将请求转发到create.jsp上去;再次说明,这个方法仅仅为create.jsp提供一个访问入口!!!

private void showCreatePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}

自此:在浏览器中访问: localhost:8080/management?method=show_create时候,就会访问ManagementController类,然后ManagementController再请求重定向到create.jsp;即还是那句话,jsp需要在Controller中提供访问入口。


3.编写create.jsp:为文件上传做好准备

文件上传:前提条件

下面,根据文件上传的前提条件,对create.jsp进行编写:

<%@page contentType="text/html;charset=utf-8"%>
<!-- 新增油画页面 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>新增油画</title>
<link rel="stylesheet" type="text/css" href="csscreate.css">
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
</head>
<body>
	<div class="container">
		<fieldset>
			<legend>新增油画</legend>
			<!-- enctype="multipart/form-data"只有这样设置,我们选择的文件才能以二进制的形式上传至服务器 -->
			<form action="/management?method=create" method="post"
				autocomplete="off" enctype="multipart/form-data">
				<ul class="ulform">
					<li>
						<span>油画名称</span>
						<span id="errPname"></span>
						<input id="pname" name="pname" />
					</li>
					<li>
						<span>油画类型</span>
						<span id="errCategory"></span>
						<select id="category" name="category">
							<option value="-1">请选择油画类型</option>
							<option value="1">现实主义</option>
							<option value="2">抽象主义</option>
						</select>
					</li>
					<li>
						<span>油画价格</span>
						<span id="errPrice"></span>
						<input id="price" name="price"/>
					</li>
					<li>
						<span>作品预览</span>
						<span id="errPainting"></span>
						<!-- accept="image/*":表示在文件选择框中默认保留所有图片格式的文件,这相当于是一个文件的筛选条件,
						但是这个条件并不靠谱;在后面涉及表单校验的时候,就会明白。 -->
						<input id="painting" name="painting" type="file" 
							style="padding-left: 0px;" accept="image/*" />
					</li>

					<li>
						<span>详细描述</span>
						<span id="errDescription"></span>
						<textarea
							id="description" name="description"></textarea>
					</li>
					<li style="text-align: center;">
						<button type="submit" class="btn-button">提交表单</button>
					</li>
				</ul>
			</form>
		</fieldset>
	</div>

</body>
</html>

create.jsp的几点说明:

      (1)form表单提交方式设为post;enctype="multipart/form-data":设置表单编码类型;

<form action="/management?method=create" method="post"
				autocomplete="off" enctype="multipart/form-data">

      (2)添加type="file"的input标签;

<input id="painting" name="painting" type="file" 
							style="padding-left: 0px;" accept="image/*" />

      (3)action="/management?method=create" :form表单提交后,设置提交的地址;

<form action="/management?method=create" method="post"
				autocomplete="off" enctype="multipart/form-data">

4.在ManagementController类中,添加接收create.jsp表单提交的方法;

可以发现,create.jsp表单提交的地址是ManagementController类:

<form action="/management?method=create" method="post"
				autocomplete="off" enctype="multipart/form-data">

(1)不借助第三方组件,“在服务器端”采用传统的策略处理【设计文件上传的请求】时:是不行的;

这个表单提交涉及到了文件上传,如果不借助第三方组件,采用以前的方式,在Controller中通过诸如【request.getParameter("pname");】的方式,获取请求中的数据的时候: 

package com.imooc.mgallery.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.imooc.mgallery.service.PaintingService;
import com.imooc.mgallery.utils.PageModel;

/**
 * 后台管理功能Controller;
 * 后台系统,所需要的增,删,改,查的操作,都在这一个Controller类中完成;
 * Servlet implementation class ManagementController
 */
@WebServlet("/management")
public class ManagementController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	// 创建PaintingService对象;;
	// 即无论是前台系统的PaintingController,还是后台系统的ManagementController都调用PaintingService中提供的方法;
	private PaintingService paintingService = new PaintingService();
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ManagementController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求体中的字符集编码方式;;;
		// get请求没有请求体,所以,这个语句是为doPost()方法中执行doGet(request,response)后,跳转过来的post请求来设置的;
		// 即这条代码是为doPost()来进行服务的;
		request.setCharacterEncoding("UTF-8");
		// 设置响应的字符集编码方式
		response.setContentType("text/html;charset=utf-8");
		
		String method = request.getParameter("method");
		if(method.equals("list")) {  // 当前台传入的method参数值为“list”的时候,代表是分页请求,调用定义的list方法;
			this.list(request,response);  // 然后,将分页处理的代码写在list方法中就可以了;
		}else if(method.equals("delete")) {  // 当method参数值为“delete”时,表示是删除请求,调用定义的delete方法;
			this.delete(request, response);
		}else if(method.equals("show_create")) {
			// method参数为“show_create”,表示是新增;调用新增的方法,跳转到create.jsp
			this.showCreatePage(request, response);
		}else if(method.equals("create")) {
			this.create(request, response);
		}
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response); // doPost调用了doGet()方法,所以,把逻辑代码都写在doGet方法中就可以了;
	}
	
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String p = request.getParameter("p");
		String r = request.getParameter("r");
		if(p==null) {
			p = "1";
		}
		if(r==null) {
			r = "6";
		}
		PageModel pageModel = paintingService.pagination(Integer.parseInt(p), Integer.parseInt(r));
		request.setAttribute("pageModel", pageModel);
		request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);
	}
	private void delete(HttpServletRequest request, HttpServletResponse response) {
		
	}
	
	/**
	 * 显示【新增】页面;这个方法,是一个纯粹的入口;
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showCreatePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void create(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String pname = request.getParameter("pname");
		System.out.println(pname);
		//request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}


}

为什么采取传统方式(不使用第三方组件)去处理【涉及文件上传的请求】是不行的???演示如下 

(1.1)演示1:如果不设置form表单的编码方式:enctype="multipart/form-data";

说明,此时这个表单的编码方式还是采取传统的提交方式,这也是我们以前经常惯见的编码方式:

在ManagementController类中,添加的create()方法中,在System.out.println(pname);处打一个断点:为了方便观察效果

发现,在请求头中有表单提交的参数;

发现,如果不设置form表单的编码方式:enctype="multipart/form-data";一切正常,和以前经常遇到的情况一样!!!

(1.2)演示2:设置form表单的编码方式:enctype="multipart/form-data";

但是,这个表单是需要上传文件,而如果表单需要上传文件,这个表单的编码方式就需要设置为enctype="multipart/form-data";

发现,请求头中没有form表单提交的参数了,因为这些数据存放在请求体中了;

即:发现,此时,“在服务器端”再采取传统的 【request.getParameter("pname");】的策略,无法获得请求中的数据了;;;;这表示,出问题了。。。。。

结论:通过上面的演示可以知道:不借助第三方组件,“在服务器端”采用传统的策略处理【设计文件上传的请求】时:是不行的;

当表单提交包含文件上传时,需要设置form编码方式为【enctype="multipart/form-data"】,因此从客户端向服务器传递的是二进制数据,如果都是自己编写代码实现,而不借助第三方提供的组件,是一件非常麻烦的事情。所以上面的演示给的启发就是:当涉及文件上传的时候需要用到第三方组件:也就是Apache提供的FileUpload组件。

换句话说,客户端(也就是前端)的Fome表单为了实现【请求中包含上传文件的需求】,需要将form表单的编码方式设置为【enctype="multipart/form-data"】,至此前端准备好了;;;但是服务器端(也就是后端)如果仍旧采取传统的策略是不行的,服务器端也必须变换一种处理策略,以应对【请求中包含上传文件的需求】;;;这也就是下面要介绍的【FileUpload组件】;

……………………………………………………

(2)利用FileUpload组件实现文件上传(非常重要)

(2.1)FileUpload简介,下载:

           

       

但是,fileupload在运行时候,要基于另外一个组件【commons-io】才可以,所以需要在Apache官网上下载【commons-io】的jar包;

(2.2)利用FileUpload组件实现文件上传

前端点击提交后,会跳转到【"/management?method=create"】,在ManagementController中完成接受这个“提交请求”的逻辑代码;

即在后端,接收前端(附带上传文件的)form提交请求,并将提交的文件上传的代码如下;下面的部分,仅仅是完成了将文件上传到Tomcat服务器某个目录下,并不涉及其他!!!

package com.imooc.mgallery.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.imooc.mgallery.service.PaintingService;
import com.imooc.mgallery.utils.PageModel;

/**
 * 后台管理功能Controller;
 * 后台系统,所需要的增,删,改,查的操作,都在这一个Controller类中完成;
 * Servlet implementation class ManagementController
 */
@WebServlet("/management")
public class ManagementController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	// 创建PaintingService对象;;
	// 即无论是前台系统的PaintingController,还是后台系统的ManagementController都调用PaintingService中提供的方法;
	private PaintingService paintingService = new PaintingService();
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ManagementController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求体中的字符集编码方式;;;
		// get请求没有请求体,所以,这个语句是为doPost()方法中执行doGet(request,response)后,跳转过来的post请求来设置的;
		// 即这条代码是为doPost()来进行服务的;
		request.setCharacterEncoding("UTF-8");
		// 设置响应的字符集编码方式
		response.setContentType("text/html;charset=utf-8");
		
		String method = request.getParameter("method");
		if(method.equals("list")) {  // 当前台传入的method参数值为“list”的时候,代表是分页请求,调用定义的list方法;
			this.list(request,response);  // 然后,将分页处理的代码写在list方法中就可以了;
		}else if(method.equals("delete")) {  // 当method参数值为“delete”时,表示是删除请求,调用定义的delete方法;
			this.delete(request, response);
		}else if(method.equals("show_create")) {
			// method参数为“show_create”,表示是新增;调用新增的方法,跳转到create.jsp
			this.showCreatePage(request, response);
		}else if(method.equals("create")) {
			this.create(request, response);
		}
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response); // doPost调用了doGet()方法,所以,把逻辑代码都写在doGet方法中就可以了;
	}
	
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String p = request.getParameter("p");
		String r = request.getParameter("r");
		if(p==null) {
			p = "1";
		}
		if(r==null) {
			r = "6";
		}
		PageModel pageModel = paintingService.pagination(Integer.parseInt(p), Integer.parseInt(r));
		request.setAttribute("pageModel", pageModel);
		request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);
	}
	private void delete(HttpServletRequest request, HttpServletResponse response) {
		
	}
	
	/**
	 * 显示【新增】页面;这个方法,是一个纯粹的入口;
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showCreatePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * @throws FileUploadException 
	 */
	private void create(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		// 使用FileUpload需要按照以下步骤
		// 1.初始化FileUpload组件
		FileItemFactory factory = new DiskFileItemFactory();
		/**
		 * FileItemFactory :将前端表单的数据转化为一个一个的FileItem对象;即用于数据的转换;
		 * ServletFileUpload :为FileUpload组件提供凝Java web层面上的HTTP请求解析的功能;即提供对web的支持;
		 */
		ServletFileUpload sf = new ServletFileUpload(factory);
		// 2.遍历所有的FileItem
		try {
			// 对原有的request请求进行解析;这个方法执行后,就会将当前请求中每一个提交来的表单数据转化为一个一个的FileItem对象;
			// 并且方法的返回值是一个List
			// 这个会抛出“FileUploadException”,这儿建议对异常进行捕捉而不是抛出;
			// 这个“FileUploadException”异常抛出的时机是:当对form表单进行解析时候,发现当前表单的编码格式并不是【enctype="multipart/form-data"】时候,就会抛出“FileUploadException”异常
			List<FileItem> formData = sf.parseRequest(request);
			for(FileItem fi:formData) {
				// FileItem对象的isFormField()方法可以判断:这个FileItem对象是一个普通输入项,还是一个文件上传框;
				// 如果FileItem对象是一个普通输入项,该FileItem对象调用isFormField()方法,返回true;
				// 如果FileItem对象是一个文件上传框,该FileItem对象调用isFormField()方法,返回false;
				if(fi.isFormField()) {
					// 这个输出,只是开发阶段的测试用,后续会有其他处理方式;;;
					System.out.println("普通输入项"+fi.getFieldName()+":"+fi.getString("UTF-8"));
				}else {
					// 这个输出,只是开发阶段的测试用,后续会有其他处理方式;;;
					System.out.println("文件上传框"+fi.getFieldName());
					// 3.将前端上传的文件,保存到服务器某个目录中
					// getRealPath()方法:获取Tomcat在实际运行环境中,某个对应的目录在(部署了该Tomcat)服务器上的物理地址;
					String path = request.getServletContext().getRealPath("/upload");
					System.out.println(path);
					//String fileName = "test.jpg";
					// UUID:根据计算机(实际中就是Tomcat部署的服务器)的本地特性,根据当前时间,计算机网卡的mac地址,或
					// 者其他的,诸如此类独特的特性,生成一个全世界唯一的字符串;
					// UUID类是Java内置的,可以直接使用;调用randomUUID()就可以得到随机字符串;
					// 以这个随机字符串作为文件名,根本不用担心重名的问题;
					String fileName = UUID.randomUUID().toString();
					// 得到文件扩展名:getName():获取文件的名称;然后substring()获取文件的扩展名
					String suffix = fi.getName().substring(fi.getName().lastIndexOf("."));
					fi.write(new File(path,fileName+suffix));
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
		
	}


}

ManagementController类需要注意的:

(1)需要导入的包:看下,注意一下就行,别import错包就行;

(2)【FileItemFactory】是一个工厂类,用于创建FileItem对象;

          ●【FileItem】是什么:在前端表单进行数据提交的时候,表单的每一个输入项在提交到后端(也就是服务端)的时候,都被叫做是一个【FileItem文件对象】;即可以把每一个FileItem与前端所传递的对应数据进行对应;即可以理解为:FileItem对象就是包含了表单(某一)项的数据对象;

          ●【FileItemFactory factory = new DiskFileItemFactory();】中的,factory对象的职责就是负责将前台传入的数据,一个一个转化为对应的FileItem;后续的代码体现了出来;

(3)一点对应关系的说明:

其中注意一下;

         ● getFieldName():获得【普通输入项】和【文件上传框】的,在前端文件标签中的name属性; 

         ● getString():获得【普通输入项】的实际输入值;【文件上传框】到后端之后是二进制数据文件,无法通过getString()获取实际输入值;

(4)文件上传的逻辑分析

需要注意:

          ●  request.getServletContext().getRealPath("/upload");:获取当前Tomcat在服务器中某个目录的实际物理地址;

          ● FileItem类的write方法:将文件写入到服务器的对应的地址中去;

(5)上传的文件,如何防止重名异常

          ●  getName()方法:获得【文件上传框】的文件文件名;

如果名字写死,或者后面上传的文件名字,和在upload目录中已有文件重名的话,会报异常,提示文件已经存在,而且这个是不允许进行文件覆盖的;

即FileUpload组件在上传文件的时候:不支持后上传的文件去覆盖掉先前上传的(重名的)文件;

解决方案:需要在文件名上,让每一次上传的文件,都产生一个不一样的文件名;

可以采用随机数,或者当前的时间作为文件名;

利用UUID类获取随机文件名:注意FileItem对象的getName()方法,可以获取上传文件的文件名;

这样以后,上传的文件如下:发现在Tomcat在服务器(这儿的服务器是本地的计算机)中的某个指定目录下,有这个文件了;

 

一个疑问:?????????????????????????????、、这个问题的答案,本篇文章的第5大节:【5.启动程序:(附加一点说明:Tomcat发布目录)】有说明!!!!!

…………………………

(2.3)文件上传后,接下来的任务,就是将这个form表单提交过来的数据,新增到存储数据的xml文件中!!!


(3)向xml中添加数据

(3.1)在XmlDataSource工具类中,编写添加的方法

具体Dom4j内容,可以参考这篇博客操作xml,使用Dom4j追加这篇博客;

XmlDataSource这个工具类:

package com.imooc.mgallery.utils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import com.imooc.mgallery.entity.Painting;

/**
 * 数据源类,将xml文件解析为Java对象
 * 
 * @author dell
 *
 */
public class XmlDataSource {
	// 为了保证在同一时间,内存中只有一份xml的Document对象,即为了保证加载的xml对象全局唯一
	// 通过static静态关键字保证数据的全局唯一性;(自然也可以通过单例模式)
	private static List<Painting> data = new ArrayList<Painting>();  // 在XmlDataSource类加载的时候,就会创建data对象,这个对象隶属于XmlDataSource类,可以保证是全局唯一;
	private static String dataFile;  // xml文件的地址;
	static {
		// 程序运行编译后,src目录下得java文件会被编译为class文件,这些class文件会被放在classes目录下,而同样处于src目录下的painting.xml文件也会放在classes目录下;
		// XmlDataSource.class.getResoure()得到classes目录的根路径,然后在classes目录的根路径下找到painting.xml,然后getPath()获得painting.xml文件的完整的物理磁盘的地址;	
		dataFile = XmlDataSource.class.getResource("/painting.xml").getPath();
		//System.out.println(dataFile);
		// 如painting.xml文件的地址是:c:new stylepainting.xml;可以发现,new和style之间有一个空格,这个空格是个特殊字符;
		// datFile得到painting.xml文件地址的时候,会进行base64转换,实际dataFile的值会是:c:new%20stylepainting.xml,即空格被转化成了%20;
		// 但是如果在后续中,利用JavaIO对painting.xml文件按照“c:new%20stylepainting.xml”读取时,会提示路径找不到,因为%20不会被JavaIO解析;需要手动的将%20转换为空格;
		// URLDecoder的作用就是:将base64转回普通的字符串;
		reload();
	}
	
	/**
	 * 读取xml文件内容到内存中,把这个功能,提炼成了一个方法
	 */
	private static void reload() {
		data.clear();// 先清空
		URLDecoder decoder = new URLDecoder();
		try {
			dataFile = decoder.decode(dataFile, "UTF-8");  // 这个需要捕获“不支持的编码格式”异常
			//System.out.println(dataFile);
			SAXReader reader = new SAXReader();
			Document document = reader.read(dataFile);  // 需要捕获“DocumentException”异常
			List<Node> nodes = document.selectNodes("/root/painting");
			for(Node node:nodes) {
				Element element = (Element)node;
				// 提取数据,如何将数据转换成Java对象?通过什么载体来保存油画的数据?所以,需要开发对应的JavaBean承载油画数据;
				String id = element.attributeValue("id");
				String pname = element.elementText("pname");
				//
				Painting painting = new Painting();
				painting.setId(Integer.parseInt(id));
				painting.setPname(pname);
				// 剩余几个采用紧凑的写法
				painting.setCategory(Integer.parseInt(element.elementText("category")));
				painting.setPrice(Integer.parseInt(element.elementText("price")));
				painting.setPreview(element.elementText("preview"));
				painting.setDescription(element.elementText("description"));
				// 将对象存储到data集合中;
				data.add(painting);  // 这样以后,当XmlDataSource这个类被加载以后,data集合中就保存了完整的油画信息;
				
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 为了保证外部可以访问data集合,需要给data增加一个出口;;;
	 * 这儿添加一个方法,getRawData():即获取最原始的信息;
	 * @return
	 */
	public static List<Painting> getRawData(){
		return data;
	}
	

	/**
	 * 
	 * @param painting :从前端封装好的Painting对象,一个Painting对象就是一个油画数据
	 * @throws DocumentException 
	 */
	public static void append(Painting painting) {
		//1.读取XML文档,得到Document对象 
		SAXReader reader = new SAXReader();
		Writer writer = null;
		try {
			Document document = reader.read(dataFile); // xml文件地址,上面已经定义好了,直接拿来用就可以了
			//2.创建新的painting
			Element root = document.getRootElement();  // 获取根节点
			Element p = root.addElement("painting"); // 创建一个新的节点
			// 下面,就根据原始xml的结构,来以此设置它的属性和子节点了
			//3.创建painting节点的各个子节点
			p.addAttribute("id", String.valueOf(data.size()+1));  // 直接在原有节点数的基础上加一就可以了;
			Element pname = p.addElement("pname");
			pname.setText(painting.getPname());
			p.addElement("category").setText(painting.getCategory().toString());
			p.addElement("price").setText(painting.getPrice().toString());
			p.addElement("preview").setText(painting.getPreview());
			p.addElement("description").setText(painting.getDescription());
			// 自此,就创建了一个新的painting节点,属性节点已经设置好了;;即内存中的Document对象就形成了一个全新的油画数据;
			// 接下来,需要把内存中的油画数据,写入到xml文件中
			//4.写入XML,完成追加操作
			writer = new OutputStreamWriter(new FileOutputStream(dataFile),"UTF-8");
			document.write(writer);
			//System.out.println(dataFile);   // 测试用,测试后删除
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(writer != null) {        // 这儿将writer的关闭操作,写在了finally中;
				try {
					writer.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			reload();// 将重新加载的方法,写在了finally中,这或许也是为了保证reaload()方法一定会被执行的 一个保证措施吧
		}
	}
//	public static void main(String[] args) { // 这个main方法主要目的,是测试一下
		//new XmlDataSource();   // 创建这个对象之前,需要加载XmlDataSource这个类,一旦加载这个类,那么和这个类的static块就会初始dataFile对象;
		List<Painting> list = XmlDataSource.getRawData();
		System.out.println(list);
//		Painting p = new Painting();
//		p.setPname("测试油画");
//		p.setCategory(1);
//		p.setPrice(4500);
//		p.setPreview("/upload/10.jpg");
//		p.setDescription("这是一张测试的图片");
//		
//		XmlDataSource.append(p);
//	}
}

XmlDataSource这个工具类几点说明:

(1)主要是新增了append()方法;注意一下,【writer.close();】写在了finally中了,注意下这种写法吧。目前觉得这样做也可以,但不这样做为什么不行还不是特别明白;;;

(2)为了能在xml文件内容改变后,能实时更新xml在内存中的内容,将data的产生的内容,实例化了一个方法;注意reload()方法首行的data.clear();

XmlDataSource类中编写main方法,运行测试后:

发现,此时油画信息已经写进xml文件中了,表示这部分的编码没有问题;;;;;;在实际工作中,为了测试某些功能代码是否编写成功,似乎可以采用这种,添加个main方法,来局部测试的套路!!!!!

(3.2)在Dao中编写create()方法,向xml中添加数据;

package com.imooc.mgallery.dao;

import java.util.ArrayList;
import java.util.List;

import com.imooc.mgallery.entity.Painting;
import com.imooc.mgallery.utils.PageModel;
import com.imooc.mgallery.utils.XmlDataSource;

/**
 * Dao类;调用PageModel类和XmlDataSource这个两个工具类;
 * 数据访问对象类,作用是获取最原始的xml数据,并且对其进行分页;
 * @author dell
 *
 */
public class PaintingDao {

	/**
	 * 实现分页的方法
	 * @param page 查询第几页数据;
	 * @param rows 每一页显示几条
	 * @return
	 */
	public PageModel pagination(int page,int rows) {
		List<Painting> xmlDataSourceList = XmlDataSource.getRawData();  // 先获取xml完整的数据;
		PageModel pageModel = new PageModel(xmlDataSourceList,page,rows);
		return pageModel;	
	}
	
	/**
	 * 对pagination方法进行重载
	 * @param category 类别
	 * @param page  查询第几页数据
	 * @param rows  每一页显示几条数据
	 * @return
	 */
	public PageModel pagination(int category,int page,int rows) {
		List<Painting> xmlDataSourceList = XmlDataSource.getRawData();  // 先获取xml完整的数据;
		List<Painting> categoryList = new ArrayList<Painting>();   // 保存符合类别要求的数据
		for(Painting p:xmlDataSourceList) {
			if(p.getCategory() == category) {
				categoryList.add(p);
			}
		}
		PageModel pageModel = new PageModel(categoryList,page,rows);
		return pageModel;
	}
	
	/**
	 * 新增油画数据
	 * @param painting
	 */
	public void create(Painting painting) {
		XmlDataSource.append(painting);
	}
}

PaintingDao类的几点说明:

(1)Dao中内容很简单,只是调用了 XmlDataSource工具类中的append()方法;

(3.3)在Service中编写:create()方法;

package com.imooc.mgallery.service;

import java.util.List;

import com.imooc.mgallery.dao.PaintingDao;
import com.imooc.mgallery.entity.Painting;
import com.imooc.mgallery.utils.PageModel;

/**
 * 这个类主要职责:完成的程序业务逻辑;
 * 涉及到与底层数据交互的工作,交给Dao类去实现
 * @author dell
 *
 */
public class PaintingService {
	private PaintingDao paintingDao = new PaintingDao();
	/**
	 * 调用PaintingDao类的pagination()方法,获得分页数据;
	 * 这个类的内容看似和PageModel类的内容雷同,但是这个类还是必须的,在实际的开发中,需要遵从MVC原
	 * 则的按层逐级调用的规范;;;所以,即便没有其他的业务逻辑,我们也要写一个Service,然后让这个Service去调用Dao;
	 * @param page 当前第几页
	 * @param rows 每页有几条数据
	 * @return 分页对象
	 */
	public PageModel pagination(int page,int rows,String...category) {
		if(rows == 0) {   // 可以看到,Service类中不但需要调用Dao来进行数据访问;
			// Service类还包括:一些前置条件的检查,以及得到调用结果后的后置数据的处理,这些工作都是与底层数据无关的
			// Service类中的方法用于处理完整的业务逻辑,Service类中方法需要尽量写的完整;
			// 而Dao中的方法只与底层数据进行交互的;;;
			// 所以,在这个例子中,即使Service类中的方法和Dao中的内容基本相同,也必须要要写这个Service类;
			throw new RuntimeException("无效的rows参数");
		}
		if((category.length==0)||(category[0]==null)) {   // 如果没有传递可选参数category的时候;
			return paintingDao.pagination(page, rows);
		}else {
			return paintingDao.pagination(Integer.parseInt(category[0]),page, rows);
		}
		
	}
	
	/**
	 * 新增油画数据
	 * 因为这儿逻辑比较简单,所以没有进行前置或者后置处理
	 * @param painting
	 */
	public void create(Painting painting) {
		paintingDao.create(painting);
	}

}

PaintingService类的几点说明:

(1)因为这儿的逻辑比较简单,Service中并没有添加一些前置或者后置代码,而是直接调用了Dao中的create()方法; 

(3.4)编写Controller部分:

package com.imooc.mgallery.controller;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.imooc.mgallery.entity.Painting;
import com.imooc.mgallery.service.PaintingService;
import com.imooc.mgallery.utils.PageModel;

/**
 * 后台管理功能Controller;
 * 后台系统,所需要的增,删,改,查的操作,都在这一个Controller类中完成;
 * Servlet implementation class ManagementController
 */
@WebServlet("/management")
public class ManagementController extends HttpServlet {
	private static final long serialVersionUID = 1L;
	// 创建PaintingService对象;;
	// 即无论是前台系统的PaintingController,还是后台系统的ManagementController都调用PaintingService中提供的方法;
	private PaintingService paintingService = new PaintingService();
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ManagementController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 设置请求体中的字符集编码方式;;;
		// get请求没有请求体,所以,这个语句是为doPost()方法中执行doGet(request,response)后,跳转过来的post请求来设置的;
		// 即这条代码是为doPost()来进行服务的;
		request.setCharacterEncoding("UTF-8");
		// 设置响应的字符集编码方式
		response.setContentType("text/html;charset=utf-8");
		
		String method = request.getParameter("method");
		if(method.equals("list")) {  // 当前台传入的method参数值为“list”的时候,代表是分页请求,调用定义的list方法;
			this.list(request,response);  // 然后,将分页处理的代码写在list方法中就可以了;
		}else if(method.equals("delete")) {  // 当method参数值为“delete”时,表示是删除请求,调用定义的delete方法;
			this.delete(request, response);
		}else if(method.equals("show_create")) {
			// method参数为“show_create”,表示是新增;调用新增的方法,跳转到create.jsp
			this.showCreatePage(request, response);
		}else if(method.equals("create")) {
			this.create(request, response);
		}
		
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response); // doPost调用了doGet()方法,所以,把逻辑代码都写在doGet方法中就可以了;
	}
	
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String p = request.getParameter("p");
		String r = request.getParameter("r");
		if(p==null) {
			p = "1";
		}
		if(r==null) {
			r = "6";
		}
		PageModel pageModel = paintingService.pagination(Integer.parseInt(p), Integer.parseInt(r));
		request.setAttribute("pageModel", pageModel);
		request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);
	}
	private void delete(HttpServletRequest request, HttpServletResponse response) {
		
	}
	
	/**
	 * 显示【新增】页面;这个方法,是一个纯粹的入口;
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	private void showCreatePage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.getRequestDispatcher("/WEB-INF/jsp/create.jsp").forward(request, response);
	}
	
	/**
	 * 新增油画数据
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 * @throws FileUploadException 
	 */
	private void create(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		// 使用FileUpload需要按照以下步骤
		// 1.初始化FileUpload组件
		FileItemFactory factory = new DiskFileItemFactory();
		/**
		 * FileItemFactory :将前端表单的数据转化为一个一个的FileItem对象;即用于数据的转换;
		 * ServletFileUpload :为FileUpload组件提供凝Java web层面上的HTTP请求解析的功能;即提供对web的支持;
		 */
		ServletFileUpload sf = new ServletFileUpload(factory);
		// 2.遍历所有的FileItem
		try {
			// 对原有的request请求进行解析;这个方法执行后,就会将当前请求中每一个提交来的表单数据转化为一个一个的FileItem对象;
			// 并且方法的返回值是一个List
			// 这个会抛出“FileUploadException”,这儿建议对异常进行捕捉而不是抛出;
			// 这个“FileUploadException”异常抛出的时机是:当对form表单进行解析时候,发现当前表单的编码格式并不是【enctype="multipart/form-data"】时候,就会抛出“FileUploadException”异常
			List<FileItem> formData = sf.parseRequest(request);
			Painting painting = new Painting();
			for(FileItem fi:formData) {
				// FileItem对象的isFormField()方法可以判断:这个FileItem对象是一个普通输入项,还是一个文件上传框;
				// 如果FileItem对象是一个普通输入项,该FileItem对象调用isFormField()方法,返回true;
				// 如果FileItem对象是一个文件上传框,该FileItem对象调用isFormField()方法,返回false;
				if(fi.isFormField()) {
					// 这个输出,只是开发阶段的测试用,后续会有其他处理方式;;;
					switch (fi.getFieldName()) {
					case "pname":
						// 当请求中是一个form,而且这个form的编码方式是“multipart/form-data”时候,在doGet()方法中的【request.setCharacterEncoding("UTF-8");】会失效;;;所以这儿在获取请求中(表单的)参数值的时候,需要设置下编码方式
						painting.setPname(fi.getString("UTF-8"));
						break;
					case "category":
						painting.setCategory(Integer.parseInt(fi.getString("UTF-8")));
						break;
					case "price":
						painting.setPrice(Integer.parseInt(fi.getString("UTF-8")));
						break;
					case "description":
						painting.setDescription(fi.getString("UTF-8"));
						break;
					default:
						break;
					}
					//System.out.println("普通输入项"+fi.getFieldName()+":"+fi.getString("UTF-8"));
				}else {
					// 这个输出,只是开发阶段的测试用,后续会有其他处理方式;;;
					System.out.println("文件上传框"+fi.getFieldName());
					// 3.将前端上传的文件,保存到服务器某个目录中
					// getRealPath()方法:获取Tomcat在实际运行环境中,某个对应的目录在(部署了该Tomcat)服务器上的物理地址;
					String path = request.getServletContext().getRealPath("/upload");
					System.out.println(path);
					//String fileName = "test.jpg";
					// UUID:根据计算机(实际中就是Tomcat部署的服务器)的本地特性,根据当前时间,计算机网卡的mac地址,或
					// 者其他的,诸如此类独特的特性,生成一个全世界唯一的字符串;
					// UUID类是Java内置的,可以直接使用;调用randomUUID()就可以得到随机字符串;
					// 以这个随机字符串作为文件名,根本不用担心重名的问题;
					String fileName = UUID.randomUUID().toString();
					// 得到文件扩展名:getName():获取文件的名称;然后substring()获取文件的扩展名
					String suffix = fi.getName().substring(fi.getName().lastIndexOf("."));
					fi.write(new File(path,fileName+suffix));
					painting.setPreview("/upload/"+fileName + suffix);// 设置油画地址
				}
			}
			paintingService.create(painting);
			// 由此,后台部分,油画的新增操作已经完成了;;;;然后可以再跳转到油画列表页面,对数据进行展示
			// 使用响应重定向,调回到油画列表页面;
			// 上面【完成新增数据】和【显示列表页】,这两者并没有明显的直接关系;;;【显示列表页】仅仅是让浏览器跳转到一个全新的功能上,对于此类场景就可以使用响应重定向;
			// 如果此时,【新增完数据 】之后,不是显示列表页,而是弹出另外一个页面,进行新增数据以后的后续操作,这个操作和前面的新增数据是紧密联系的,此时就需要使用请求转发,将当前的请求转给下面的功能,继续进行操作;
			response.sendRedirect("/management?method=list");
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
		
	}


}

ManagementController类的几点说明:

(1)这个类主要作用,是获取前端传过来的form表单中的各项目数据,组成一个Painting类对象,作为调用Service中的方法的参数;

(2) 注意Switch的这种用法;;;表单+附带文件+FileUpload组件+获取对应值::就用Switch!!!!!!不过好像不一定,利用if判断,好像也能完成,不过这儿使用了Switch,注意一下吧,这大概率是更好的的一种策略;

(3)还有需要注意【paintingService.create(painting);】和【response.sendRedirect("/management?method=list");】也都写在了try块中,需要注意下哦;这样写是更合理的,可以设想一下,万一上面的代码有异常了后,需要先处理异常,如果异常没有处理完,就不要执行“【paintingService.create(painting);】和【response.sendRedirect("/management?method=list");】”;;;;如果“【paintingService.create(painting);】和【response.sendRedirect("/management?method=list");】”不写在try块中,那么会发生这种现象:try块中代码报错了,异常处理完成后,本次的信息按理说已经是异常的了,应该重新发起一次正确的调用,但是程序会继续执行“【paintingService.create(painting);】和【response.sendRedirect("/management?method=list");】”,这显然是不合理的;;;说的好乱,但是自己应该能懂;;;

(4)最后,注意一下,请求转发和重定向,应用场景的不同;;;这一点有点感觉,但似乎并没有彻底理解;;;可以看下请求转发与响应重定向这篇文章。

……………………………………………………

(3.5)最后补充一点:属性中有id(自增,唯一标识对象)属性的时候,javaBean一般不添加有参构造;


 5.启动程序:(附加一点说明:Tomcat发布目录)

(1)启动应用,观察效果

点击【提交表单】后,会根据Controller中编写的逻辑,跳转到油画列表页面;

注:当关闭Tomcat服务器,(需要clean一下,具体clean是什么意思,可以看下eclipse中使用clean命令这篇文章;;;可以这样认为,当使用clean命令后,下次启动应用的时候,Tomcat会先彻底清空发布目录的东西,然后重新发布项目所有相关的所需文件),再次发布项目并查看Tomcat项目的发布目录的时候:

OK,能懂。。。

(2)再一点说明

Eclipse的WorkSpace:

……………………………………………………

Eclipse这个IDE中的build目录:

……………………………………………………

Tomcat项目发布目录:(这儿就和eclipse中的clean命令的清空和刷新发布目录的问题了)

  

OK,自己慢慢熟悉吧~~~目测,在IDEA一定会有和【Eclipse中的clean命令】效果一样的操作;


 

最后

以上就是冷酷飞鸟为你收集整理的后台系统四:【新增】功能;(FileUpload组件) 0.新增功能需要完成的功能概述:1.将新增页create.html添加到项目中2.在ManagementController类中,添加访问create.jsp的入口3.编写create.jsp:为文件上传做好准备4.在ManagementController类中,添加接收create.jsp表单提交的方法; 5.启动程序:(附加一点说明:Tomcat发布目录)的全部内容,希望文章能够帮你解决后台系统四:【新增】功能;(FileUpload组件) 0.新增功能需要完成的功能概述:1.将新增页create.html添加到项目中2.在ManagementController类中,添加访问create.jsp的入口3.编写create.jsp:为文件上传做好准备4.在ManagementController类中,添加接收create.jsp表单提交的方法; 5.启动程序:(附加一点说明:Tomcat发布目录)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部