根据慕课网的Socket通信实例课程,完成的文件上传器实例。某些小问题导致我卡了很久
1.未对实体类进行序列化
2.数据库blob类型反向工程在java中实体类对应字段生成String类型,由于理解有问题,本想将图片信息的字节信息转成字符串信息,但是无法保存图片信息,怎么保存都是11个字节。现在还是不知道BufferedInputStream的read(buff)方法,buff里面存的11个字节的信息代表了什么,感觉像是hashcode地址。
后来直接将对象字段改成byte[]类型,BufferedInputStream的read(buff)方法读取存入buff数组,然后包装成file类型,终于能成功保存到数据库了。
主要是按照老师的思路来,然后自己加了一个Hibernate框架,感觉Hibernate框架不熟练对我来说也是一个坑。
实体类:
文件实体类TbFfile:
package com.imooc.entity;
import com.mysql.jdbc.Blob;
/**
* TbFile entity. @author MyEclipse Persistence Tools
*/
public class TbFile implements java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer fid;
private String fname;
private byte[] fcontent;
// Constructors
/** default constructor */
public TbFile() {
}
/** minimal constructor */
public TbFile(Integer fid, String fname) {
this.fid = fid;
this.fname = fname;
}
public TbFile(String fname, byte[] fcontent) {
super();
this.fname = fname;
this.fcontent = fcontent;
}
/** full constructor */
public TbFile(Integer fid, String fname, byte[] fcontent) {
this.fid = fid;
this.fname = fname;
this.fcontent = fcontent;
}
// Property accessors
public Integer getFid() {
return this.fid;
}
public void setFid(Integer fid) {
this.fid = fid;
}
public String getFname() {
return this.fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public byte[] getFcontent() {
return this.fcontent;
}
public void setFcontent(byte[] fcontent) {
this.fcontent = fcontent;
}
}
用户实体类 TbUser:
package com.imooc.entity;
/**
* TbUser entity. @author MyEclipse Persistence Tools
*/
public class TbUser implements java.io.Serializable {
// Fields
/**
*
*/
private static final long serialVersionUID = 1L;
private Integer id;
private String username;
private String password;
// Constructors
/** default constructor */
public TbUser() {
}
public TbUser(String username, String password) {
this.username = username;
this.password = password;
}
/** full constructor */
public TbUser(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
业务类(主要实现用户类和文件类和数据库的交互):
文件业务操作FileService:
package com.imooc.service;
import java.io.File;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.imooc.entity.TbFile;
import com.imooc.util.HibernateSessionFactory;
/*
* 文件业务处理
*/
public class FileService {
public void save(TbFile file){
SessionFactory sessionFactory=HibernateSessionFactory.getSessionFactory();
Session session=sessionFactory.getCurrentSession();
Transaction transaction=session.beginTransaction();
session.save(file);
transaction.commit();
// session.close();
}
}
用户业务操作UserService:
package com.imooc.service;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.imooc.entity.TbUser;
import com.imooc.util.HibernateSessionFactory;
/*
* 用户业务处理
*/
public class UserService {
SessionFactory sessionFactory=HibernateSessionFactory.getSessionFactory();
Session session=sessionFactory.getCurrentSession();
Transaction transaction=session.beginTransaction();
//注册
public boolean signUp(TbUser user){
String hql="from TbUser as u where u.username=?";
Query query=session.createQuery(hql);
query.setString(0, user.getUsername());
List<TbUser> users=query.list();
transaction.commit();
if(users.size()!=0){
return false;//根据用户查询到数据说明用户名已存在,注册失败
}else{
session=sessionFactory.getCurrentSession();
transaction=session.beginTransaction();
session.save(user);
transaction.commit();
return true;//查不到说明改用户名有效,注册到数据库并返回true
}
}
//登陆
public boolean signIn(TbUser user){
// user.getUsername();
String hql="from TbUser as u where u.username=? and u.password=?";
Query query=session.createQuery(hql);
query.setString(0, user.getUsername());
query.setString(1, user.getPassword());
List<TbUser> users=query.list();
transaction.commit();
// session.close();
if(users.size()!=0){
return true;
}else{
return false;
}
}
}
Socket通讯类,主要是实现服务器和客户端Socket通信的实现
服务器线程类ServerThread:
package com.imooc.socket;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import com.imooc.entity.TbFile;
import com.imooc.entity.TbUser;
import com.imooc.service.FileService;
import com.imooc.service.UserService;
import com.imooc.util.CommandTransfer;
public class ServerThread extends Thread {
private OutputStream os=null;//输出流
private ObjectOutputStream oos=null;//对象输出流
private InputStream is=null;//输入流
private ObjectInputStream ois=null;//对象输入流
private FileInputStream fis=null;//文件输入流
public Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
public void run(){
CommandTransfer transfer=new CommandTransfer();
UserService us=new UserService();//用户业务操作对象
FileService fs=new FileService();//文件业务操作对象
try {
TbFile file=new TbFile();
TbUser user=new TbUser();
transfer=getData();
//服务器关于客户端 注册 的 响应
if(transfer.getCmd().equals("signUp")){
user=(TbUser) transfer.getData();
boolean flag=us.signUp(user);//注册
if(flag){
transfer.setResult("注册成功,请登录!");
transfer.setFlag(true);
}else{
transfer.setResult("注册失败,该用户名已存在!");
transfer.setFlag(false);
}
sendData(transfer);//发送给客户端
}
//服务器关于客户端 登陆 的响应
if(transfer.getCmd().equals("signIn")){
user=(TbUser) transfer.getData();
boolean flag=us.signIn(user);
if(flag){
transfer.setFlag(true);
transfer.setResult("登陆成功,请上传文件!");
}else{
transfer.setFlag(false);
transfer.setResult("账号或密码错误,请重新输入!");
}
sendData(transfer);//发送给客户端
}
//服务器关于客户端 上传文件 的响应
if(transfer.getCmd().equals("upFile")){
file= (TbFile) transfer.getData();//读取来自客户端的文件信息
fs.save(file);
transfer.setFlag(true);
transfer.setResult("文件上传成功!");
sendData(transfer);//发送给客户端
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
closeAll();//关闭所有资源
}
}
//向客户端发送数据
public void sendData(CommandTransfer transfer) throws IOException{
os=null;
oos=null;
os=socket.getOutputStream();
oos=new ObjectOutputStream(os);
oos.writeObject(transfer);
oos.flush();
}
//从客户端接受数据
public CommandTransfer getData() throws IOException, ClassNotFoundException{
is=null;
ois=null;
CommandTransfer transfer=null;
is=socket.getInputStream();
ois=new ObjectInputStream(is);
transfer = (CommandTransfer) ois.readObject();
return transfer;
}
//关闭所有资源
public void closeAll(){
try {
if(ois!=null){
ois.close();
}
if(is!=null){
is.close();
}
if(oos!=null){
oos.close();
}
if(os!=null){
os.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端Socket类,实现客户端的操作逻辑以及和服务器的通信实现:
package com.imooc.socket;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import com.imooc.entity.TbFile;
import com.imooc.entity.TbUser;
import com.imooc.util.CommandTransfer;
public class SocketClient {
Scanner input=new Scanner(System.in);
private Socket socket=null;//客户端Socket
private OutputStream os=null;
private ObjectOutputStream oos=null;
private InputStream is=null;
private ObjectInputStream ois=null;
private FileInputStream fis=null;
//显示主菜单
public void showMenu(){
System.out.println("*****欢迎使用文件上传器*****");
System.out.println("1.登陆\n2.注册\n3.退出");
System.out.println("**********************");
System.out.println("请选择:");
int choice=input.nextInt();
switch(choice){
case 1:
showSignIn();
break;
case 2:
showSignUp();
break;
case 3:
System.out.println("再见,感谢您对本系统的支持");
System.exit(0);
default:
System.out.println("输入有误!");
System.exit(0);
}
}
//登陆
public void showSignIn(){
TbUser user= new TbUser();
CommandTransfer transfer=new CommandTransfer();
int count=0;//登陆次数
while(true){
count++;
if(count>3){
System.out.println("您已连续三次登陆失败,程序退出!");
System.exit(0);
}
System.out.println("请输入用户名:");
user.setUsername(input.next());
System.out.println("请输入密码:");
user.setPassword(input.next());
transfer.setCmd("signIn");
transfer.setData(user);
try {
socket=new Socket("127.0.0.1",8888);
sendData(transfer);//将数据发送到服务器
transfer=getData();//从服务器接受数据
System.out.println("**********************");
System.out.println(transfer.getResult());//输出显示结果
if(transfer.isFlag()){
break;//如果登陆成功则不再重复登陆
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
closeAll();//关闭所有资源
}
}
showUpFile();//登陆完之后上传文件
}
//注册
public void showSignUp(){
TbUser user= new TbUser();
CommandTransfer transfer=new CommandTransfer();
while(true){
System.out.println("请输入用户名:");
user.setUsername(input.next());
System.out.println("请输入密码:");
user.setPassword(input.next());//注册时第一次输入的密码
System.out.println("请再次输入密码:");
//确认密码
if(!user.getPassword().equals(input.next())){
System.out.println("两次输入的密码不一致,请重新输入");
System.out.println("**********************");
continue;
}
transfer.setCmd("signUp");
transfer.setData(user);
try {
socket=new Socket("127.0.0.1",8888);
sendData(transfer);
transfer=getData();
System.out.println(transfer.getResult());//输出显示结果
if(transfer.isFlag()){
break;//若注册成功则不再重复注册
}
System.out.println("**********************");
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
closeAll();//关闭所有资源
}
}
System.out.println("**********************");
showSignIn();//注册完之后登陆
}
//上传文件
public void showUpFile(){
System.out.println("**********************");
System.out.println("请输入文件的绝对路径");
CommandTransfer transfer=new CommandTransfer();//创建命令传输对象,准备传送命令
TbFile tbFile=new TbFile();//创建实体类TbFile对象,准备接受文件信息
File file=new File(input.next());//读入文件地址,创建File对象
try {
fis=new FileInputStream(file);
BufferedInputStream bis=new BufferedInputStream(fis);
byte[] fcontent=new byte[fis.available()];//定义缓冲区,准备把文件信息写入缓冲区
bis.read(fcontent);
tbFile.setFname(file.getName());//文件名字
tbFile.setFcontent(fcontent);//文件内容
//发送文件数据到服务器
socket=new Socket("127.0.0.1",8888);
transfer.setCmd("upFile");
transfer.setData(tbFile);
sendData(transfer);
//从服务器接受信息
transfer=getData();
System.out.println(transfer.getResult());//输出显示结果
// System.exit(0);//上传文件后退出
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
closeAll();//关闭所有资源
}
}
//向服务器发送数据
public void sendData(CommandTransfer transfer) throws IOException{
os=null;
oos=null;
os=socket.getOutputStream();
oos=new ObjectOutputStream(os);
oos.writeObject(transfer);
oos.flush();
}
//从服务器接受数据
public CommandTransfer getData() throws IOException, ClassNotFoundException{
is=null;
ois=null;
CommandTransfer transfer = null;
is=socket.getInputStream();
ois=new ObjectInputStream(is);
transfer = (CommandTransfer) ois.readObject();
return transfer;
}
//关闭所有资源
public void closeAll(){
try {
if(ois!=null){
ois.close();
}
if(is!=null){
is.close();
}
if(oos!=null){
oos.close();
}
if(os!=null){
os.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
启动客户端StartClient:
package com.imooc.socket;
/*
* 启动客户端
*/
public class StartClient {
public static void main(String[] args) {
SocketClient socketClient=new SocketClient();
socketClient.showMenu();
}
}
启动服务器StartServer:
package com.imooc.socket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class StartServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket=new ServerSocket(8888);
System.out.println("***服务器已就绪,等待客户端访问***");
while(true){
//启动服务器,开始监听
Socket socket=serverSocket.accept();
ServerThread serverThread=new ServerThread(socket);
serverThread.start();
}
}
}
com.imooc.util主要就是工具类:
CommandTransfer主要是传递命令和数据,返回操作结果(因为服务器Socket接受一次输入流,无法分清楚客户端想让服务器对这个输入流进行什么操作,因此把操作命令和数据重新包装成一个对象,在服务器端接受了输入流之后就有更多的操作空间)
package com.imooc.util;
import java.io.Serializable;
public class CommandTransfer implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String cmd;
private Object data;
private boolean flag;
private String result;
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
HibernateSessionFactory类是Hibernate框架自动生成的。
另外Hibernate.xml文件配置如下:
数据库的设置和慕课网中课程一样。
运行结果:
另外我看到博客上一片是UI版的,感觉很酷炫,大家自行学习查看
http://blog.youkuaiyun.com/su20145104009/article/details/52843735