上传下载功能
文件的上传
理解上传思路:
- 稍微复杂一些 直接使用Servlet实现有难度 一般使用apache commons组件中commons-fileUpload组件大大降低操作的难度。
- commons-fileUpload离不开commons-io组件
- commons-fileUpload的常用类
- FileItemFactory DiskFileItemFactory:工厂类,生产FileItem
- FileItem:每个表单项都会被封装成一个FileItem对象
- ServletFileUpload:实现上传操作,将表单数据封装到FileItem中
实现
添加jar commons-fileupload.jar commons-io.jar

视图层
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'add.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
${requestScope.mess }
<form action="servlet/AddServlet" method="post" enctype="multipart/form-data" >
用户名:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
分数:<input type="text" name="score"><br>
图片:<input type="file" name="photo"><br>
<input type="submit" value="提交">
</form>
</body>
</html>
控制层 掌握FileItem的常用方法
- item.isFormField() 如果是普通表单项true,如果是file表单项,false
- item.getFieldName() 表单项的name属性
- item.getString() 普通表单项的值,file表单项就是file的内容
- item.getString(“utf-8”) 解决普通表单项的中文乱码问题
- item.getName() 普通表单项就是null,file表单项就是文件的名称
- item.getContentType() 普通表单项是null,file表单项就是文件的类型
- item.getSize():表单项内容长度
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.创建FileItemFactory对象
FileItemFactory factory=new DiskFileItemFactory();
//2.创建ServletFileUpload对象
ServletFileUpload upload=new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");////解决file表单项的文件名中文乱码问题
//3.通过 ServletFileUpload对象实现上传操作 将客户端一个个表单项封装到一个FileItem中
List<FileItem> itemList=null;
try {
itemList=upload.parseRequest(request);
} catch (FileUploadException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//4.遍历各个FileItem 相当于对各个表单项进行处理
// System.out.println(itemList.size());
for (int i = 0; i < itemList.size(); i++) {
//取出第i个表单项
FileItem item=itemList.get(i);
//输出itemList的内容 熟悉FileItem的主要方法
System.out.println(item.isFormField());//是否是file表单项 是file false 不是file true
System.out.println(item.getFieldName());//表单项的name属性的值
//System.out.println(item.getString());//对于非file表单项,value属性的值对于file表单项,是文件内容
System.out.println(item.getString("utf-8"));//解决非file表单项的中文乱码问题 比如name
System.out.println(item.getName());//对于file表单项,上传文件的名称对于非file表单项,返回null
System.out.println(item.getContentType());//对于file表单项,上传文件的名称对于非file表单项,返回null
System.out.println(item.getSize());//对于file表单项,上传文件的大小 对于非file表单项,value值的宽度
System.out.println("===========================================");
}
int n = 1;
// 页面跳转
if (n != 0) {
// 重定向:/后面要跟上下文路径 /stumgr /stumgr2
response.sendRedirect(request.getContextPath()
+ "/servlet/ShowAllServlet");
} else {
request.setAttribute("mess", "添加失败!");
request.getRequestDispatcher("/add.jsp").forward(request, response);
}
}
运行结果: 添加用户名为英文

遍历结果

解决中文乱码问题
- 解决file表单项中文乱码问题: upload.setHeaderEncoding("utf-8");
- 解决普通表单项的中文乱码问题: item.getString(“utf-8“)
运行结果



上传文件到指定目录保存到数据库
实体类
/**
* 学生实体类
* @author Administrator
*
*/
public class Student {
private int id;
private String name;
private int age;
private double score;
private String realName;
private String photoName;
private String photoType;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(int id, String name, int age, double score) {
super();
this.id = id;
this.name = name;
this.age = age;
this.score = score;
}
public Student(String name, int age, double score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public Student(int id, String name, int age, double score, String realName,
String photoName, String photoType) {
super();
this.id = id;
this.name = name;
this.age = age;
this.score = score;
this.realName = realName;
this.photoName = photoName;
this.photoType = photoType;
}
public Student(String name, int age, double score, String realName,
String photoName, String photoType) {
super();
this.id = id;
this.name = name;
this.age = age;
this.score = score;
this.realName = realName;
this.photoName = photoName;
this.photoType = photoType;
}
// private Date birthDate;//生日
// private java.util.Date inputTime;//录入时间
// private String photoName;//照片名称
// private String photoType;//照片类型
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getPhotoName() {
return photoName;
}
public void setPhotoName(String photoName) {
this.photoName = photoName;
}
public String getPhotoType() {
return photoType;
}
public void setPhotoType(String photoType) {
this.photoType = photoType;
}
}
showAll.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'showAll.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<!--输出所有的学生信息 -->
<a href="add.jsp">添加学生信息</a>
<table align="center" border="1" width="70%">
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>分数</th>
<th>照片</th>
<th>下载</th>
</tr>
<c:forEach items="${requestScope.stuList2}" var="stu" >
<tr>
<td>${stu.id}</td>
<td>${stu.name }</td>
<td>${stu.age }</td>
<td>${stu.score}</td>
<td><img src="upload/${stu.photoName }" alt="" width="100px"/></td>
<td>
<a href="upload/${stu.photoName }">下载1</a>
<a href="servlet/DownServlet?id=${stu.id}">下载2</a>
</td>
</tr>
</c:forEach>
</table>
</body>
</html>
AddServlet
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.创建FileItemFactory对象
FileItemFactory factory=new DiskFileItemFactory();
//2.创建ServletFileUpload对象
ServletFileUpload upload=new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");////解决file表单项的文件名中文乱码问题
//完善5:限制上传的单个和所有文件的大小 建议使用该方式
upload.setFileSizeMax(200*1024);//单个文件的上限
upload.setSizeMax(5*200*1024);//一次上传的所有文件的总大小的上限
//3.通过 ServletFileUpload对象实现上传操作 将客户端一个个表单项封装到一个FileItem中
List<FileItem> itemList=null;
try {
itemList=upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
request.setAttribute("mess", "文件不能超过200kb....");
request.getRequestDispatcher("/add.jsp").forward(request, response);
return;
}
//4.遍历各个FileItem 相当于对各个表单项进行处理
// System.out.println(itemList.size());
String name=null;
int age=0;
double score=0;
String realName=null;
String photoName=null;
String photoType=null;
for (int i = 0; i < itemList.size(); i++) {
//取出第i个表单项
FileItem item=itemList.get(i);
String filedName=item.getFieldName();
//对各个表单项进行处理(普通表单项和文件表单项要分开处理)
if(item.isFormField()){ //是普通表单项
if ("name".equals(filedName)) {
name=item.getString("utf-8");
}
if ("age".equals(filedName)) {
age=Integer.parseInt(item.getString());
}
if ("score".equals(filedName)) {
score=Integer.parseInt(item.getString());
}
}else{ //文件表单项
if ("photo".equals(filedName)) {
//完善5: 限制上传文件大小 200kb 在此处 采用此种方法限制文件大小 不合适
// long size=item.getSize();
// if (size>200*1024) {
// request.setAttribute("mess", "文件不能超过200kb");
// request.getRequestDispatcher("/add.jsp").forward(request, response);
// return;
// }
//完善4:只上传jpg、jpeg和gif文件
String contentType=item.getContentType();
photoType=item.getContentType();
if (!"image/jpeg".equals(contentType)&&!"image/gif".equals(contentType)) {
request.setAttribute("mess", "只能上传jpg和gif");
request.getRequestDispatcher("/add.jsp").forward(request, response);
return;
}
//指定上传的文件夹 Tomcat的webApps目录下,Tomcat的webApps目录之外
//直接使用物理路径,不灵活
//完善3:由逻辑路径得到物理路径,提高灵活性
// File dir=new File("D:apache-tomcat-7.0.56webappsupdownload1upload");
// String path="upload"; //逻辑路径
String realPath=this.getServletContext().getRealPath("/upload");
File dir=new File(realPath);
//完善1:如果文件夹不存在 就创建
if (!dir.exists()) {
dir.mkdirs();
}
//指定上传的文件名
realName=item.getName();
//完善2:为了防止文件的同名覆盖 上传到服务器端的文件重新命名
UUID uuid=UUID.randomUUID();
String extName = realName.substring(realName.lastIndexOf("."));
photoName=uuid.toString()+extName;
//指定上传的文件夹和文件名
File file=new File(dir,photoName);
//上传该照片到指定位置
try {
item.write(file);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Student stu=new Student(name, age, score, realName, photoName, photoType);
StudentService stuService=new StudentServiceImpl();
int n=stuService.save(stu);
// 页面跳转
if (n != 0) {
// 重定向:/后面要跟上下文路径 /stumgr /stumgr2
response.sendRedirect(request.getContextPath()
+ "/servlet/ShowAllServlet");
} else {
request.setAttribute("mess", "添加失败!");
request.getRequestDispatcher("/add.jsp").forward(request, response);
}
}
ShowAllServlet
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//按照查询条件进行查询
StudentService stuBiz = new StudentServiceImpl();
List<Student> stuList = stuBiz.findAll();
request.setAttribute("stuList2", stuList);
//页面跳转
request.getRequestDispatcher("/showAll.jsp").forward(request, response);
}
StudentService
/**
* 查找所有学生信息
* @return
*/
public List<Student> findAll();
/**
* 添加学生信息
* @param stu
* @return
*/
public int save(Student stu);
StudentServiceImpl
private StudentDao stuDao = new StudentDaoImpl();
public List<Student> findAll() {
return this.stuDao.findAll();
}
public int save(Student stu) {
return this.stuDao.save(stu);
}
StudentDao
/**
* 查找所有学生信息
* @return
*/
public List<Student> findAll();
/**
* 添加学生信息
* @param stu
* @return
*/
public int save(Student stu);
StudentDaoImpl
public List<Student> findAll() {
List<Student> stuList = new ArrayList<Student>();
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//获取连接
conn = DBUtil.getConnection();
//发送命令或获取结果
stmt = conn.createStatement();
//处理结果
rs =stmt.executeQuery("select * from stu");
while(rs.next()){
//获取各个字段的值
int id =rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
double score = rs.getDouble("score");
String realName=rs.getString("realName");
String photoName=rs.getString("photoName");
String photoType=rs.getString("photoType");
//由字段创建对象
Student stu = new Student(id, name, age, score,realName,photoName,photoType);
//将对象放入集合
stuList.add(stu);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
DBUtil.closeAll(rs, stmt, conn);
}
//返回结果
return stuList;
}
public int save(Student stu) {
Connection conn = null;
PreparedStatement pstmt = null;
int n=0;
try{
//获取连接
conn = DBUtil.getConnection();
//发送命令或获取结果
pstmt = conn.prepareStatement("insert into stu values(seq_stu.nextval,?,?,?,?,?,?)");
pstmt.setString(1, stu.getName());
pstmt.setInt(2, stu.getAge());
pstmt.setDouble(3, stu.getScore());
pstmt.setString(4, stu.getRealName());
pstmt.setString(5, stu.getPhotoName());
pstmt.setString(6, stu.getPhotoType());
n = pstmt.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
DBUtil.closeAll(null, pstmt, conn);
}
return n;
}
失败的运行结果 文件类型不符合要求时


文件大小不符合要求时


成功的运行结果


数据库中

文件


文件的下载
需求说明: 将服务器的图片在客户端下载
实现
DownServlet
public class DownServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1获取学生编号
int id=Integer.parseInt(request.getParameter("id"));
//2根据编号调用业务层查询到该学生的所有信息(包括realname photoname...)
StudentService stuService=new StudentServiceImpl();
Student stu = stuService.findById(id);
//3通过io流实现照片下载 (从服务器到客户端)
//3.1创建一个输入流和输出流
String realPath=this.getServletContext().getRealPath("/upload");
String fileName=realPath+"/"+stu.getPhotoName();
File file=new File(fileName);
response.setContentLength((int) file.length()); //文件长度
response.setContentType(stu.getPhotoType()); //MIME类型
// response.setHeader("Content-disposition", "inline"); //默认
String realName=stu.getRealName();// 汉字.jpg
String userAgent=request.getHeader("User-Agent").toLowerCase();
if (userAgent.indexOf("wow")>=0) { //ie浏览器
realName=URLEncoder.encode(realName,"utf-8");
} else { //其他浏览器
realName=new String(realName.getBytes("utf-8"),"iso-8859-1");
}
response.setHeader("Content-disposition", "attachment;filename="+realName);
InputStream is=new FileInputStream(file); //读服务器端的一个文件
OutputStream os=response.getOutputStream(); //写到客户端
//3.2 使用输入流和输出流完成复制 (服务器端----客户端)
IOUtils.copy(is, os);
//3.3关闭输入流和输出流
is.close();
os.close();
//表单 method=get 表单提交的中文乱码解决
//request.setCharacterEncoding("utf-8"); //post
//String name = request.getParameter("name");
// byte [] bytes = name.getBytes("iso-8859-1");
// name = new String(bytes,"utf-8");
//name = new String(name.getBytes("iso-8859-1"),"utf-8");
// name=new String(name.getBytes("utf-8"),"iso-8859-1");
}
}
StudentService
/**
* 按照id查询学生信息
* @param id
* @return
*/
public Student findById(int id);
StudentServiceImpl
public Student findById(int id) {
return this.stuDao.findById(id);
}
StudentDao
/**
* 按照id查询学生信息
* @param id
* @return
*/
public Student findById(int id);
StudentDaoImpl
public Student findById(int idd) {
Student stu = null;
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//获取连接
conn = DBUtil.getConnection();
//发送命令或获取结果
stmt = conn.createStatement();
//处理结果
rs =stmt.executeQuery("select * from stu where id = "+idd);
rs.next();
//获取各个字段的值
int id =rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
double score = rs.getDouble("score");
String realName=rs.getString("realName");
String photoName=rs.getString("photoName");
String photoType=rs.getString("photoType");
//由字段创建对象
stu = new Student(id, name, age, score,realName,photoName,photoType);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
DBUtil.closeAll(rs, stmt, conn);
}
//返回结果
return stu;
}
运行结果
点击下载 保存文件确定就下载成功

SVN使用
一、 版本控制和SVN 入门
1. 什么是版本控制
a) 只要进行团队软件开发,就会涉及源代码的合并共享以及带来的相关问题
- 代码如何合并(手工合并几乎不可能)
- 历史版本的保存(各个版本间有大量重复,多大变化算一个版本)
- 跟踪哪些代码是谁修改(每个代码都写上注释说明作者?故意写成别人呢)
- 以上问题不解决,就会影响团队开发效率
b) 如何有效解决以上问题呢?这就需要版本控制
c) 目前计算机开发领域流行的是采用专门的版本管理软件来进行管理,大大提 高了效率
2. 常用版本管理软件
- VSS:Microsoft提供,Window平台,小型开发团队所适合的工具。
- CVS:开源工具,跨平台。绝大多数CVS服务已改用SVN。CVS已停止维护
- SVN(Subversion):开源,跨平台,在 CVS 的基础上开发。使用企业众多, 稳定安全,操作简单。集中式版本控制系统。
- GIT:开源的分布式版本控制系统,用以有效高速的处理从很小到非常大的项 目版本管理。(GITHUB 是一个用 GIT 做版本控制的项目托管平台,B/S 架构。 放到GITHUB上的代码需要开源,并且是互联网开发)

3. SVN
- 传统的SVN是通过命令进行操作的,现在一般通过 GUI形式使用 SVN
- 服务器端Visual SVN(GUI)
- 客户端:TortoiseSVN 第三方客户端(GUI)
- 客户端:subclipse Eclipse的插件 第三方客户端(GUI)
- TortoiseSVN功能更强、使用范围更广,但是 eclipse下使用subclipse更方便
二、 服务器端Visual SVN
1. 安装软件
2. 创建版本库
a) 创建默认结构 use default struction

b) 默认结构的含义
- trunk:主干 开发时代码存储的位置,永远是最新的代码
- brank:分支 在不影响Trunk其它用户情况下进行一些关于新功能的探 索性或实验性的开发,待新功能完善后它也可以合并到 Trunk中
- tags:标签 历史版本 阶段性里程碑版本 比如1.0 2.0 3.0

3. 创建用户

4. 创建组

5. 为组指定用户

6. 为组指定对版本库的操作权限
a) 默认everyone具有 read/write权限,无法删除,要修改为 no access

7. 通过浏览器访问服务器端


三、 客户端subclipse
1. 简介
- subclipse=subversion+eclipse
- 一个为 Eclipse添加 Subversion 支持的项目。支持几乎所有版本的Eclipse
2. 安装
- 解压后将其中的 features和plugin文件夹放入MyEclipse的dropins目录下
- 重新启动MyEclipse,即可自动发现并安装
- 安装后在window------preferrences---—team中可以看到SVN

3. 提交项目到服务器端
- 选中项目右键--------team----share project----选择SVN
- 提交版本位置、用户名、密码都会由相关服务器管理人员提供。
- 可以选择记住密码,避免多次的重复输入。
- 提交后会跳到 team synchronizing view,还需要真正同步代码到服务器,同 步之前可以选择哪些代码不需要使用 svn进行管理
- 提交成功后可以观察版本库容量的变化
- 提交成功后客户端项目会显示专门的标记,并且增加了相应的.svn项目,来 存储操作记录
4. 断开和服务器连接
- team—断开连接--------从项目中删除SVN 元信息
5. 客户端从SVN检出项目
- new--- Project…--------SVN----从SVN检出项目
6. 更新和提交操作
- 更新将服务器最新代码更新到本地;提交是将本地最新代码提交到服务器
- 提交之前要先更新,因为可能其他程序员期间以及提交了最新代码到服务器
- 提交一定要给出注释,对提交内容进行说明,作为以后辨别版本的主要依据。
7. 解决冲突
- 模拟两个用户对一个类进行修改,分别修改相同的方法和增加一个新方法
- 更新后出现冲突,和冲突方沟通后,对冲突文件给出最终解决方案
- 还需要team----标记为解决,相应冲突文件为自动删除,当前文件由冲突状态 转换为已修改状态,待提交
8. 还原没有提交的代码
- team----还原
9. 还原已经提交的代码
- 如果最新的代码出现问题,可以直接修改,也可以回滚到之前的某个历史版 本,直接使用或者进行修改
- 查看资源历史记录
- 根据注释确定要还原的版本,无法确定可以查看或者比较代码
- 确定版本后,右键选择”从修订班x回复更改”
- 可能出现冲突,解决后提交代码到服务器