发表于: 2020-11-12 23:25:12

1 1376


今天完成的事情:
熟悉一些HTML语言的基础


编写HTTP Server

HTTP Server本质上是一个TCP服务器,我们先用TCP编程的多线程实现的服务器端框架:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
/**
*
* @author liaoxuefeng
*/
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(8080); // 监听指定端口
System.out.println("server is running...");
for (;;) {
Socket sock = ss.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
Thread t = new Handler(sock);
t.start();
}
}
}
class Handler extends Thread {
Socket sock;
public Handler(Socket sock) {
this.sock = sock;
}
@Override
public void run() {
try (InputStream input = this.sock.getInputStream()) {
try (OutputStream output = this.sock.getOutputStream()) {
handle(input, output);
}
} catch (Exception e) {
try {
this.sock.close();
} catch (IOException ioe) {
}
System.out.println("client disconnected.");
}
}
private void handle(InputStream input, OutputStream output) throws IOException {
System.out.println("Process new http request...");
var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
// 读取HTTP请求:
boolean requestOk = false;
String first = reader.readLine();
if (first.startsWith("GET / HTTP/1.")) {
requestOk = true;
}
for (;;) {
String header = reader.readLine();
if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
break;
}
System.out.println(header);
}
System.out.println(requestOk ? "Response OK" : "Response Error");
if (!requestOk) {
// 发送错误响应:
writer.write("404 Not Found\r\n");
writer.write("Content-Length: 0\r\n");
writer.write("\r\n");
writer.flush();
} else {
// 发送成功响应:
String data = "<html><body><h1>Hello, world!</h1></body></html>";
int length = data.getBytes(StandardCharsets.UTF_8).length;
writer.write("HTTP/1.0 200 OK\r\n");
writer.write("Connection: close\r\n");
writer.write("Content-Type: text/html\r\n");
writer.write("Content-Length: " + length + "\r\n");
writer.write("\r\n"); // 空行标识HeaderBody的分隔
writer.write(data);
writer.flush();
}
}
}
碰到一大堆错误


怀疑是没有导入什么包进去,但是对这个代码也不太了解,于是去了解一些TCP编程

网络编程基础

计算机网络的基本概念主要有:
  • 计算机网络:由两台或更多计算机组成的网络;
  • 互联网:连接网络的网络;
  • IP地址:计算机的网络接口(通常是网卡)在网络中的唯一标识;
  • 网关:负责连接多个网络,并在多个网络之间转发数据的计算机,通常是路由器或交换机;
  • 网络协议:互联网使用TCP/IP协议,它泛指互联网协议簇;
  • IP协议:一种分组交换传输协议;
  • TCP协议:一种面向连接,可靠传输的协议;
  • UDP协议:一种无连接,不可靠传输的协议。

因为多个电脑相互连接时,协议不同就无法连接和传输数据,所以需要共同定义一个协议,这个协议就是TCP协议。


TCP编程

在开发网络应用程序的时候,我们又会遇到Socket这个概念。Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络:

为什么需要Socket进行网络通信?因为仅仅通过IP地址进行通信是不够的,同一台计算机同一时间会运行多个网络应用程序,例如浏览器、QQ、邮件客户端等。当操作系统接收到一个数据包的时候,如果只有IP地址,它没法判断应该发给哪个应用程序,所以,操作系统抽象出Socket接口,每个应用程序需要各自对应到不同的Socket,数据包才能根据Socket正确地发到对应的应用程序。
使用Socket进行网络编程时,本质上就是两个进程之间的网络通信。其中一个进程必须充当服务器端,它会主动监听某个指定的端口,另一个进程必须充当客户端,它必须主动连接服务器的IP地址和指定端口,如果连接成功,服务器端和客户端就成功地建立了一个TCP连接,双方后续就可以随时发送和接收数据。
因此,当Socket连接成功地在服务器端和客户端之间建立后:
  • 对服务器端来说,它的Socket是指定的IP地址和指定的端口号;
  • 对客户端来说,它的Socket是它所在计算机的IP地址和一个由操作系统分配的随机端口号。

Socket就是由IP地址和端口号(范围是0~65535)组成,可以在cmd中使用netstat -ano可以查看Socket端口占用情况

服务器端

要使用Socket编程,我们首先要编写服务器端程序。Java标准库提供了ServerSocket来实现对指定IP和指定端口的监听。ServerSocket的典型实现代码如下:
import java.io.*;
import java.nio.charset.StandardCharsets;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(6666); // 监听指定端口
System.out.println("server is running...");
for (;;) {
Socket sock = ss.accept();
System.out.println("connected from " + sock.getRemoteSocketAddress());
Thread t = new Handler(sock);
t.start();
}
}
}
class Handler extends Thread {
Socket sock;
public Handler(Socket sock) {
this.sock = sock;
}
@Override
public void run() {
try (InputStream input = this.sock.getInputStream()) {
try (OutputStream output = this.sock.getOutputStream()) {
handle(input, output);
}
} catch (Exception e) {
try {
this.sock.close();
} catch (IOException ioe) {
}
System.out.println("client disconnected.");
}
}
private void handle(InputStream input, OutputStream output) throws IOException {
var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
writer.write("hello\n");
writer.flush();
for (;;) {
String s = reader.readLine();
if (s.equals("bye")) {
writer.write("bye\n");
writer.flush();
break;
}
writer.write("ok: " + s + "\n");
writer.flush();
}
}
}
代码会报错
解决办法是将这个调到11



但是由于本地jdk版本是8.0,不是11,所以依旧会报错


这个只能升级版本解决了
师兄审核代码发现,没有service层,也没有用到动态SQL,也没有用到@Autowired,于是来重新编写一个spring+mybatis的整合
了解service层是什么?

Service层主要负责业务模块的逻辑应用设计。

1.先设计接口

2.再设计实现类,

3.接着再Spring的配置文件中配置其实现的关联。

这样我们就可以在应用中调用Service接口来进行业务处理。Service层的业务实现,具体要调用到已定义的Dao层的接口,封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。


为什么要在service层重新编写一个接口,为什么不直接引用dao层的接口?
面向对象设计原则中有三条与此相关:开闭原则、依赖倒转原则、理氏替换原则。还记得依赖倒转原则吧?高层不依赖于低层,二者都依赖于抽象,也就是面向接口编程。
为什么要用Service接口?是让表示层(原来spring mvc就是表示层)不依赖于业务层(service层)的具体实现。为什么要用DAO接口?是让业务层(service层)不依赖于持久层(JDBC,DAO等等)的具体实现。有了这两个接口,Spring IOC容器才能发挥作用。
举个例子,用DAO接口,那么持久层用mybatis,还是用Hibernate,还是 JDBC,随时可以替换,不用修改业务层Service类的代码。
使用接口的意义就在此。
加service层之后的代码
在spring-config.xml添加以下代码


加上Java项目



service接口
package com.jnshu.Mapper;
import com.jnshu.Pojo.Student;
public interface StudentQueryMapper {
//根据Id查询用户信息
public Student findStudentById(int id) throws Exception;
//根据姓名查询
public Student findStudentByname(String name) throws Exception;
//根据学号查询用户信息
public Student findStudentByStudentId(int StudentId) throws Exception;
//添加用户
public int insertStudent(Student student) throws Exception;
//删除用户
public boolean deleteStudent(int id) throws Exception;
//修改用户
public boolean updateStudent(Student student) throws Exception;
}
service实现类
package com.jnshu.service.impl;
import com.jnshu.Pojo.Student;
import com.jnshu.service.StudentService;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class StudentServiceImpl implements StudentService {
// 使用 @Autowired 也可以,@Resource 功能更单一,只能取出bean
@Resource
private SqlSessionTemplate sqlSession;
@Override
public Student findStudentById(int id) throws Exception {
Student student = sqlSession.selectOne("com.jnshu.Mapper.StudentQueryMapper.findStudentById", id);
return student;
}
@Override
public Student findStudentByname(String name) throws Exception {
Student student = sqlSession.selectOne("com.jnshu.Mapper.StudentQueryMapper.findStudentByname", name);
return student;
}
@Override
public Student findStudentByStudentId(int StudentId) throws Exception {
Student student = sqlSession.selectOne("com.jnshu.Mapper.StudentQueryMapper.findStudentByStudentId", StudentId);
return student;
}
@Override
public int insertStudent(Student student) throws Exception {
sqlSession.insert("com.jnshu.Mapper.StudentQueryMapper.insertStudent", student);
return student.getId();
}
@Override
public boolean deleteStudent(int id) {
int i = sqlSession.delete("com.jnshu.Mapper.StudentQueryMapper.deleteStudent", id);
if (i > 0) {
return true;
} else {
return false;
}
}
@Override
public boolean updateStudent(Student student) throws Exception {
int i = sqlSession.update("com.jnshu.Mapper.StudentQueryMapper.updateStudent", student);
if (i > 0) {
return true;
} else {
return false;
}
}
}
测试类
package com.jnshu.service.impl;
import com.jnshu.Pojo.Student;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
// 让测试运行于spring测试环境
@RunWith(SpringJUnit4ClassRunner.class)
// 指定 Spring 配置文件所在的位置
@ContextConfiguration(locations = "classpath:Spring-config.xml")
public class StudentServiceTest {
// 也可用 @Autowired
@Resource
private StudentServiceImpl studentService;
/**
* 根据id查找用户
*/
@Test
public void testFindStudentById() throws Exception {
System.out.println(studentService.findStudentById(1));
}
/**
* 根据名字查找用户
*/
@Test
public void testFindStudentByname() throws Exception {
System.out.println(studentService.findStudentByname("静夜思"));
}
/**
* 根据学号查询用户
*/
@Test
public void testFindStudentByStudentId() throws Exception {
System.out.println(studentService.findStudentByStudentId(21));
}
/**
* 添加用户
*/
@Test
public void testInsertStudent() throws Exception {
Student student = new Student();
student.setName("任逍遥");
student.setGender(7);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
student.setBirthday(sdf.parse("1995-08-15"));
studentService.insertStudent(student);
// 得到插入数据的主键并将其打印出来
System.out.println("index: "+student.getId());
}
/**
*
*/
@Test
public void testUpdateStudent() throws Exception {
Student student = new Student();
student.setId(1);
student.setName("佘帅帅");
student.setGender(1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
student.setBirthday(sdf.parse("2008-01-10"));
boolean a =studentService.updateStudent(student);
//输出用户信息
System.out.println("是否成功修改:"+a);
System.out.println(student);
}
/**
*
*/
@Test
public void testDeleteStudent() throws Exception {
Student student = new Student();
boolean a =studentService.deleteStudent(11);
//输出用户信息
System.out.println("是否成功删除:"+a);
System.out.println("删除" + student.getId() + "的数据");
}
}
遇到的问题:
1.


2.


明天的计划:
了解各种注解的作用,弄动代码一一对应的关系。然后优化代码,避免采用硬解码的方式。 Server入门

收获:

使用HTML语言,了解计算机网络基本概念,TCP编程基本概念,了解service层时业务层,在service层需要编写接口和实现类,为了dao层的修改不会影响到service层,同时也可以使用多个dao层。使用service层编写代码





返回列表 返回列表
评论

    分享到