总结一下我的java大作业
首先是题目要求
用JavaSocket编程开发云笔记本。
基本功能:该软件支持客户端从服务器下载用户之前保存的笔记。笔记以文本文档的形式保存在服务器中,笔记在客户端的界面上显示。该软件支持用户在客户端修改笔记,并通过保存按钮更新服务器的笔记文件,同一个用户可以在服务器中保存多个笔记。
要实现:“新建笔记”、“保存笔记”、“打开笔记”、“删除笔记”、“查询笔记、“笔记下载到本地”等功能。
总体思路:
1.服务器端:我写了三个服务器类,分别功能是登录和注册,加载初始数据,处理各个事件。
2.客户端:正常的笔记本客户端,只不过要加一些和服务器的交互。
这个是我项目的目录 主体是Client和Server
Client: MyNote2 是笔记本的界面。Register和Login分别是注册和登录界面和对应的点击事件。
Server:LoginServer 处理登录和注册。
MyNoteServer1 处理初始的数据加载。
MyNoteServer2 处理客户端和服务器端的交互。
其中前两个服务器类在完成任务后就会关闭。第三个服务器一直使用,利用了while死循环和 read函数的阻塞,关闭需要手动关闭。
客户端部分
登陆界面和注册界面张这个样子,很简单的布局。
笔记本的主界面张这个样子。左侧是JList,右侧是JTabbedPane。
我觉得学习到的两个点就是这两个组件的使用。
关于Jlist
1.样式
下面展示一下样式部分的代码。
ListCellRenderer<Object> renderer = new MyListCellRenderer();
jList.setCellRenderer(renderer);
//左侧列表数据的样式
class MyListCellRenderer implements ListCellRenderer<Object>{
JLabel jlabel =new JLabel();
@Override // value 是列表的数据
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
jlabel.setText(value.toString());
jlabel.setBorder(BorderFactory.createEmptyBorder(10,4,10,4));
jlabel.setFont(new Font("微软雅黑",Font.BOLD,20));
jlabel.setOpaque(true);
if(isSelected) {
jlabel.setBackground(list.getSelectionBackground());
jlabel.setForeground(list.getSelectionForeground());
}else {
jlabel.setBackground(list.getBackground());
jlabel.setForeground(list.getForeground());
}
return jlabel;
}
}
JList中的元素为cell,我在调整样式时,也是对cell进行操作,把所有的cell都看成JLabel,对JLabel进行调整,然后返回。
2.点击
jList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if(jList.getSelectedIndex()!=-1) {
if(e.getClickCount()==1) {
oneClick(jList.getSelectedIndex());
}
if(e.getClickCount()==2) {
twoClick(jList.getSelectedIndex());
}
}
}
分别为单击和双击的函数我自己写的,传入的参数是当前点击的JList的index。
3.其他
要把JList放入滑动条JScrollPane中才可以正常使用
关于JTabbedPane
在我的项目中关于JTabbedPane的操作比较简单。
主要是添加,移除,获取JTabbedPane中的组件,当然每一个选项卡中的组件都是Textarea。
分别是
add(); add方法有很多重载。传入的参数也是不同的。
remove(index);
getSelectedComponent(index);
都是void类型的函数
关于输入框
在开始用时,点击取消或者关闭,都会返回一个空值。而且不输入任何东西时,关闭会有异常,这里分享一下我的解决方法。
s = JOptionPane.showInputDialog("查询内容:");
if(s==null) {
return ;
}else if(s.equals("")) {
JOptionPane.showMessageDialog(null, "输入不能为空");
s = JOptionPane.showInputDialog("查询内容:");
}else {
System.out.println("123");
}
最后的else块中是像完成的操作。
服务器端部分
登录&注册
我的思路,客户端传需要的账号密码到服务器端(和一个flag),服务器端根据flag的进行不同操作,并返回一个flag1给客户端,客户端根据不同的flag1进行不同的操作。登录or注册后就关掉这个服务器了,防止占用端口。
下面展示代码。
server = new ServerSocket(8888);
socket=server.accept();
while(true) {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int flag = br.read();
if(flag==49) {
String name1 = br.readLine();
String pwd1 = br.readLine();
flag1=login(name1,pwd1);
//判断账号密码
//传回客户端一个登录状态
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(flag1);
if(flag1==1) {
break;
}
}else if(flag==50) {
String name1 = br.readLine();
String pwd1 = br.readLine();
int flag2 = Register(name1, pwd1);
//判断账号密码
//传回客户端一个登录状态
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
pw.println(flag2);
if(flag2==1) {
File file=new File("F:\\wzhwzh"+"\\"+name1);
file.mkdir();
break;
}
}
login和Register是我写的两个函数,用于判断登录和注册状态,用的是MySQL数据库,也是基础的查询和插入,主要熟悉了一下jdbc的使用。
初始化数据
客户端传进来用户的账号,根据账号找到所在的文件(我给每一个用户一个文件夹,里面有txt文件来保存笔记),然后将这些文件传入客户端的JList列表就可以了,这个时候只传了文件名,文件的内容会在打开JList的cell时加载进来。加载完成后,就可以关掉这个服务器了,不要占用端口。
下面展示代码。
server = new ServerSocket(8888);
socket=server.accept();
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String username=br.readLine();
System.out.println("服务器1打开了");
// 接收客户端传来的用户名
// 传回文件名字
File file = new File("F:\\wzhwzh"+"\\"+username);
File[] array = file.listFiles();
int l=array.length;
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
System.out.println(l);
pw.print(l);
for(int i=0;i<l;i++) {
System.out.println(array[i].getName());
pw.println(array[i].getName());
}
事件处理
下面展示一些 内联代码片
。
private Socket s = null;
private ServerSocket ss;
private FileInputStream fis=null;
private FileOutputStream fos = null;
private OutputStream os=null;
private BufferedReader br=null;
private InputStream is = null;
private String username;
public void run() {
try {
ss = new ServerSocket(8888);
s = ss.accept();
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
username=br.readLine();
while(true) {
int flag = br.read();
System.out.println(flag);
if(flag==49) {
String path = br.readLine();
//找到文件
File file = new File(path);
path = "F:\\wzhwzh"+"\\"+username+"\\"+file;
file = new File(path);
fis = new FileInputStream(path);
//把文件内容传给客户端
os = s.getOutputStream();
if(file.exists()&&file.length()==0) {
os.write(1);
}else {
os.write(2);
int len=0;
byte[] bytes = new byte[1024];
while((len=fis.read(bytes))!=-1) {
os.write(bytes,0,len);
}
}
}else if(flag == 50) {
String filename = br.readLine();
filename+=".txt";
System.out.println(filename);
File file = new File("F:\\wzhwzh"+"\\"+username+"\\"+filename);
file.createNewFile();
System.out.println("创建成功了");
}else if(flag == 51) {
String filename = br.readLine();
System.out.println(filename);
byte[] bytes = new byte[1024];
is=s.getInputStream();
is.read(bytes);
fos = new FileOutputStream("F:\\wzhwzh"+"\\"+username+"\\"+filename);
fos.write(bytes);
}else if(flag == 52) {
String name1 = br.readLine();
String name2 = br.readLine()+".txt";
System.out.println(name1);
System.out.println(name2);
File file=new File("F:\\wzhwzh"+"\\"+username+"\\"+name1);
if(file.renameTo(new File("F:\\wzhwzh"+"\\"+username+"\\"+name2))) {
System.out.println("成功");
}
}else if (flag == 53) {
String name = br.readLine();
System.out.println(name);
File file = new File("F:\\wzhwzh"+"\\"+username+"\\"+name);
if(file.exists()) {
System.out.println("文件存在");
fis.close();
if(file.delete()) {
System.out.println("删除成功");
}
}
}else if(flag == 54) {
String s1 = br.readLine();
File file = new File("F:\\wzhwzh"+"\\"+username);
File[] files = file.listFiles();
ArrayList<String> list = new ArrayList<String>();
for(int i=0;i<files.length;i++) {
if(files[i].getName().contains(s1)) {
list.add(files[i].getName());
}else {
fis = new FileInputStream("F:\\wzhwzh"+"\\"+username+"\\"+files[i].getName());
byte[] bytes = new byte[1024];
fis.read(bytes);
System.out.println(new String(bytes,"UTF-8"));
if(new String(bytes,"UTF-8").contains(s1)) {
list.add(files[i].getName());
}
}
}
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
pw.print(list.size());
for(int i=0;i<list.size();i++) {
pw.println(files[i].getName());
}
}
}
//首先获取客户端传来的文件名
} catch (Exception e) {
e.printStackTrace();
}finally {}
}
事件处理我用的是最笨的方法,因为 read函数阻塞的机制,如果没有数据传入它就会死等。所以我设计了while死循环,并且把客户端的事件都增加了一个部分,就是传入一个flag标志,这样服务器端就可以根据flag来判断应该执行哪个功能。
1-加载文件 2-新建笔记 3-保存笔记
4-改名 5-删除笔记 6-查询
查询功能我觉得我写的不够好,也是思路最简单的方法,因为我们要求是对名字和内容进行查询,所以用了if-else来判断,而且由于是在服务器中查询,客户端中新写的笔记但没保存进服务器时就会
结束
有一个很大的教训,就是我完成项目的时间太长了,我每天的作业量很小,然后写了很长时间,这样导致我在后期写的时候忘了我前期写的代码,而且很难找到。
功能的实现也是用的最简单的思路,效率很低。
这次的收获是学习了javaSocket,java图形界面,简单使用了jdbc,java对文件的操作。
也收获了一些简单的测试,在后期也可以自己解决一些出现的bug。
最重要的是有一个学习的过程,也是发现问题到解决问题的过程。
总体来说,收获还是很大的,这次大作业也为以后进一步学习java知识和开发技术打下了基础。