后端笔记

maven打好的jar包,真和普通的class文件目录一样,可以直接运行。 Alt text

编写自己的web应用

我们使用JavaEE提供的Servlet API编写自己的Servlet来处理HTTP请求,将代码打包成war包,再由web服务器运行。

注意:普通的Java程序是通过启动JVM,然后执行main()方法开始运行。war包不能直接运行,必须由web服务器运行。 我们编写的servlet不能直接运行,需要web服务器创建实例运行,所以类似Tomcat这样的Web服务器也称为Servlet容器。Servlet容器只会给每个Servlet类创建唯一实例。Servlet容器会使用多线程执行实例的doGet()或doPost()方法,要注意线程安全。

Servlet容器为每个Web应用程序自动创建一个唯一的ServletContext实例,这个实例就代表了Web应用程序本身,dataSource连接池等全局变量就是绑定在ServletContext上的对象。

java EE web工程代码目录结构: Alt text

tomcat架构

Alt text

数据库

数据库的发明是为了通过条件快速定位数据。 对于硬盘文件,只能将数据加载到内存,然后遍历查找数据。

SQL数据库对SQL语句相同,但只有参数不同的若干语句可以作为batch执行,即批量执行,这种操作有特别优化,速度远远快于循环执行每个SQL。

Alt text

创建线程是一个昂贵的操作,频繁地创建和销毁线程,会消耗大量的系统资源,往往创建和消耗线程所耗费的时间比执行任务的时间还长,所以为了提高效率,可以用线程池。

HikariCP是最广泛使用的JDBC连接池。

最基础jdbc只涉及Connection、PreparedStatement、resultSet。其他的数据库操作,如spring提供的jdbctemplate,只是对基础jdbc的封装。

  1. BeanPropertyRowMapper<>(User.class)在jdbctemplate是经常用到的,可以将数据库一行转换为一个对象。
try (Connection conn = ds.getConnection()) { // 在此获取连接
			try (PreparedStatement ps = conn
					.prepareStatement("SELECT * FROM students WHERE grade = ? AND score >= ?")) {
				ps.setInt(1, 3); // 第一个参数grade=?
				ps.setInt(2, 90); // 第二个参数score=?
				try (ResultSet rs = ps.executeQuery()) {
					while (rs.next()) {
						students.add(extractRow(rs));
					}
				}
			}
		} // 在此“释放”连接

spring

  1. 标注@ComponentScan的作用:容器自动搜索标注@ComponentScan类所在的包以及子包,把所有标注为@Component的Bean自动创建出来,并根据@Autowired进行装配
  2. Spring容器可以通过@PropertySource自动读取配置,并以@Value("<span data-formula="{key:defaultValue}")的形式注入

一个用户创建一个httpsession,根据JSESSIONID来判断不同的httpsession。拿到别人的JSESSIONID就可以登录别人帐号了?

在Web应用中,除了需要使用MVC给用户显示页面外,还有API接口,我们称之为REST,通常输入输出都是JSON,便于第三方调用或者使用页面JavaScript与之交互。

  1. maven工程添加jackson依赖后,加了@ResponseBody注解类的方法,返回的类都会被序列化为json格式。

  2. 要控制序列化和反序列化(比如password显示和不显示),可以使用Jackson提供的@JsonIgnore和@JsonProperty注解。

在Servlet模型中,一个请求对应一个线程

在Servlet模型中,每个请求都是由某个线程处理,开始处理请求,到写入响应完成,都是在同一个线程中处理的。但是,如果一个请求处理的时间较长,例如几秒钟甚至更长,那么,这种基于线程池的同步模型(tomcat)很快就会把所有线程耗尽,导致服务器无法响应新的请求。如果把长时间处理的请求改为异步处理,那么线程池的利用率就会大大提高。

Spring MVC中有两种方式实现Async:

  1. 方法返回Callable。 Spring MVC自动把返回的Callable.call()放入线程池执行,等待结果返回后再写入响应。
  2. 方法返回DeferredResult对象,然后在另一个新线程中,设置此对象的值并写入响应,超时未设置值超时会自动返回超时错误响应。(这种方法用的多)

()->{}就是Lambda

在Java程序中,我们经常遇到一大堆单方法接口:Comparator、Runnable、Callable。单方法接口被称@FunctionalInterface。在接收FunctionalInterface作为参数的时候,可以把实例化的匿名类改写为Lambda表达式,能大大简化代码。

websocket

http协议是请求-响应模型,如果客户端不发送请求,服务器不能向客户端发送消息。如果需要向客户端推送消息,只能通过javascript定时轮询,效率很低且实时性不高。 WebSocket在HTTP协议的基础上做了一个简单的升级,即建立TCP连接后,浏览器发送请求时,附带几个头: " aria-hidden="true">{key:defaultValue}")的形式注入

一个用户创建一个httpsession,根据JSESSIONID来判断不同的httpsession。拿到别人的JSESSIONID就可以登录别人帐号了?

在Web应用中,除了需要使用MVC给用户显示页面外,还有API接口,我们称之为REST,通常输入输出都是JSON,便于第三方调用或者使用页面JavaScript与之交互。

  1. maven工程添加jackson依赖后,加了@ResponseBody注解类的方法,返回的类都会被序列化为json格式。

  2. 要控制序列化和反序列化(比如password显示和不显示),可以使用Jackson提供的@JsonIgnore和@JsonProperty注解。

在Servlet模型中,一个请求对应一个线程

在Servlet模型中,每个请求都是由某个线程处理,开始处理请求,到写入响应完成,都是在同一个线程中处理的。但是,如果一个请求处理的时间较长,例如几秒钟甚至更长,那么,这种基于线程池的同步模型(tomcat)很快就会把所有线程耗尽,导致服务器无法响应新的请求。如果把长时间处理的请求改为异步处理,那么线程池的利用率就会大大提高。

Spring MVC中有两种方式实现Async:

  1. 方法返回Callable。 Spring MVC自动把返回的Callable.call()放入线程池执行,等待结果返回后再写入响应。
  2. 方法返回DeferredResult对象,然后在另一个新线程中,设置此对象的值并写入响应,超时未设置值超时会自动返回超时错误响应。(这种方法用的多)

()->{}就是Lambda

在Java程序中,我们经常遇到一大堆单方法接口:Comparator、Runnable、Callable。单方法接口被称@FunctionalInterface。在接收FunctionalInterface作为参数的时候,可以把实例化的匿名类改写为Lambda表达式,能大大简化代码。

websocket

http协议是请求-响应模型,如果客户端不发送请求,服务器不能向客户端发送消息。如果需要向客户端推送消息,只能通过javascript定时轮询,效率很低且实时性不高。 WebSocket在HTTP协议的基础上做了一个简单的升级,即建立TCP连接后,浏览器发送请求时,附带几个头:

Upgrade: websocket
Connection: Upgrade

收到成功响应后表示WebSocket“握手”成功,这时,TCP连接不会关闭,CS可以双向推送数据。可以是text和二进制数据。

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
  1. Spring提供了TextWebSocketHandler和BinaryWebSocketHandler分别处理文本消息和二进制消息

本文章使用limfx的vscode插件快速发布