TODO:这仅仅是一篇草稿 个人使用,内容有待完善不建议查看
TODO: 此文档还需完善请留言或联系作者
以上内容是为了防止此文被发布
Java Web 开发复习
Web 服务器
SpringBoot 内嵌支持的三款 Servlet 容器 ( Tomcat 、Jetty 和 Undertow ) , 当下比较推荐的是 Undertow
-
Tomcat
-
Jetty
-
Undertow: Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括 阻塞和基于 NIO 的非堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。
WildFly,原名 JBoss AS(JBoss Application Server) 或者 JBoss,是一套应用程序服 务器,属于开源的企业级 Java 中间件软件。
Undertow
Undertow 完全嵌入,不需要容器,只需通过 构建器 API 即可快速搭建 web 服务器;并且 Undertow 的生命周期完全由嵌入应用程序控制。
使用 undertow builder API 启动 Undertow:
|
|
上面示例启动一个服务器处理所有 HTTP 请求并返回"Hello World"字符串,这种方式的优 点是简单,是最通用的一种方式。
在 Srping Boot 中使用 Undertow:
Srping Boot 已经完全继承了 Undertow 技术,我们只需要引入 Undertow 的依赖即可(先 排除 tomcat,再添加 undertow)
|
|
配置好以后,我们启动应用程序,发现容器已经替换为 Undertow
tomcat
Web 应用和虚拟目录的映射:
- Web 应用程序:指提供浏览器访问的程序,通常也称为 Web 应用。
- 一个 Web 应用由多个静态 web 资源和动态 web 资源组成,如:
- HTML、CSS、js 文件
- jsp 文件、java 程序、支持 jar 包
- 配置文件等
- 组成 web 应用的这些文件通常我们会使用一个目录组织,这个目录称之为:web 应用所在目录
- Web 应用开发好后,若想提供外界访问,需要把 web 应用所在目录交给 web 服务器管理 ,这个过程称之为虚拟目录的映射(需在配置文件中配置)。
web 应用的基本组成结构:
mail
|
|------ html、jsp、css、js等文件
|
|------ WEB-INF/
|
|--- classes/ (Java类)
|
|--- lib/ (jar包)
|
|---- web.xml (web应用的配置文件)
tomcat 作为运行 Servlet 的容器,其基本功能是负责接收和解析来自客户的请求,同时把 客户的请求传送给相应的 Servlet,并把 Servlet 的响应结果返回给客户。
图:Servlet 容器响应客户请求访问特定 Servlet 的时序图(重要)
时序图中: 对象 A 到对象 B 的箭头,表示发送消息,因此也可理解为 A 调用 B 的方法。
Tomcat 与 Servlet:
- Servlet 规范规定,JavaWeb 应用必须采用固定的目录结构。
- Servlet 规范把能够发布和运行 JavaWeb 应用的 Web 服务器称为Servlet 容器。
- tomcat 支持全部 JSP 以及 Servlet 规范。
- tomcat 是使用 Java 写成,需要 java 运行环境。
Tomcat配置:
- Tomcat 的启动和关闭脚本都会执行同目录下的 catalina.sh 脚本;
catalina.sh
脚本允许输入命令行参数。比如 start、run、debug、embedded、stop 参数。为了方便可以自定义 tomcatStart 和 tomcatShut 这两个别名或脚本来控制 - 配置虚拟主机:通过配置 server.xml 中配置 Host 标签来配置主机地址和网站路径。
- 更改 tomcat 的 server.xml 配置文件后需要重启 tomcat 服务器。
- web 应用可以被打包成一个 war 包,使用命令:
jar -cvf news.war news
;服务器会自动解压该 war - 包。
- tomcat 中的 context 就代表了一个 web 应用。配置 context 元素中的 reloadable 元素,可以让 tomcat 自动加载更新后的 web 应用。
- 在运行时,Servlet 容器的类加载器先加载 classes 目录下的类,再加载 lib 目录下的 jar 文件中的类。因此如果两个目录下存在同名的类,classes 目录下的类具有优先权。
- tomcat 服务器本身还提供了一个前端控制台界面,其用户与密码在 tomcat 的 conf/tomcat-users.xml 文件来配置。该密码非常重要,不要透露。
HTTP 协议
可以通过 telnet 发送 http 请求,来获得服务器的 http 响应。并通过其测试 http 1.0 和 http 1.1 的区别。
对于请求下面的这样一个 html 页面,浏览器需要向服务器发送 5 次请求。第一次请求得 到整个 html 页面,后面三次请求获得三个图片和一个 js 文件。
|
|
上面的页面设计的不好,请求多次会加大服务器的压力;对此还有相应的优化方法
Chrome 开发者工具的简单使用:
直接在 Chrome 浏览器中打开开发者工具,切换到"Network"选项卡,然后按 F5 刷新页 面,在该选项卡中就会列出此次刷新请求的具体资源的详细信息,并会统计进行了多少次 请求(在 Name 栏的底部)。“Name"栏中列出了所有请求资源的名称,点击具体资源会出现 几个标签页,点击"Headers"可查看其对应的请求头,点击"Preview"可预览资源…
http 请求
请求行、请求头、空行、请求数据(如表单提交数据)
Post /hello.jsp HTTP/1.1
Accept: image/gif,image/jpeg, */*
Referer: http://localhost/login.html
...
Cache-Control: no-cache
username=Tom&password=1234&sublmit=submit # Post方式的请求正文
用户如果没有设置,默认情况下浏览器向服务器发送的都是 get 请求,例如在浏览器直接 输入地址访问,点击超链接等。
如果想发送 post 请求,方法是在表单 form 标签中指定使用 post 。很显然当我们想要做 请求测试时会有些麻烦,
- 对于 get 请求测试我们可以很方便的只需要在浏览器直接输入地址即可;
- 但是对于 post 请求,难道我们还需要新建一个带有 form 表单前端页面来进行测试?为
了解决这一问题,我们可以使用现有的 Rest Client 工具来方便的进行测试,常见工具
有:
- Advanced Rest Client (ARC)
- Postman
- Postwoman
(可以这样理解吗? 首先在浏览器输入网址使用 get 请求一个页面包含表单的网页, 然后我填写好表单后点击提交按钮,并且该表单的源代码中指定了使用 post,那么就会使 用 post 提交表单请求)
这样理解最好:
在浏览器中输入一个网址,回车后,此时浏览器向发送了一个 Get 请求(用于获取页面的源
代码??),而浏览器为了加载页面中的脚本和图片等(解析源代码??)又会自行发起请求
。比如打开一个 Github 上的仓库,共发起了 100 次请求。
发现老师讲的很好。有些东西如果自己摸索会话费很多时间,而且不一定能达到那种程度 的理解。要自己快速的动手去实施…来提高速度。可能前提是自己对这方面已经有了些 理解。今天发现多与人交流是可以锻炼自己的思维的。
get 提交的数据有长度限制(数据在请求头的第一行)
post 无限制(在请求头空行下方)
如果要在用户点击超链接时提交数据给服务器,则可直接在超链接的地址后添
加?usernaem=fan
的这种 get 方式。
请求行: GET ...
请求头:
Accept: */* -- 可接收的文件类型
Referer: http://localhost:8080/myhome/index.html -- 从哪个网址进入此页面;可用于设置防盗链
User-Aget: ... -- 客户机软件环境(比如系统,浏览器版本)
Range: 头指示服务器只传输部分Web资源。这个头可以用来实现断点续传功能。
Range:字段可以通过3种格式设置要传输的字节范围
Range: bytes=1000-2000 #
Range: bytes=1000- #1000以后的所有内容
Range: bytes=1000 #传输最后1000个字节
get 请求示例:
一般不包含请求正文,因为没有意义。见此处的讨 论 HTTP GET with request body
GET /hello.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
post 请求示例:
包含请求正文
POST /cgi-bin/process.cgi HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
licenseID=string&content=string&/paramsXML=string
思考:观察一下 Idea 下的 Java Web 项目结构,其 webapp 目录下的 html 静态页面的 获取与 servlet 的关系。提示:这些
.html
文件是通过 get 请求获取的。
http 响应
HTTP /1.1 200 OK -- 状态行
Server: Microsoft-IIS/5.0 -- 多个响应头(服务器通过这些数据的描述信息,可以通知客户端如何处理它返回的数据)
Date: Thu, 13 Jul 2000 05:46:53 GMT
Content-Type: text/html
Content-Length: 2291
Cache-control: private
-- 一个空行
<HTML> -- 响应正文(实体内容)
<head>
<title>helloapp</title>
</head>
<BODY>
....
</body>
</html>
状态行:
格式:HTTP 版本号,状态码
状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为 5 类:
状态码 | 含义 |
---|---|
100~199 | 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 |
200~299 | 表示成功接收请求并已经完成整个处理过程,常用 200 |
300~399 | 为完成请求,客户端需进一步细化请求。例如,请求的资源已经移动一个新地址,常用 302(页面不位于此处,请访问别处,重定向),307 和 304(要求浏览器使用缓存) |
400~499 | 客户端的请求有错误,常用 404(无此资源) 403(无权限) |
500~599 | 服务器端出现错误,常用 500 |
响应头:
- Location: 配合 302 状态码使用,用于告诉客户端去找谁(实现重定向,通过地址的改 变判断是否进行了重定向)。
- Content-Encoding: 服务器通过这个头,指示数据的压缩格式
- Content-Length:
- Content-Type:
- Last-Modified: 当前资源的缓存时间。
- Refresh: 告诉浏览器隔多长时间刷新一次。(重要,聊天时获取最新数据,刷新实时图 表)
- Content-Disposition: 告诉浏览器以下载方式打开数据
- Expires: 缓存的保存时间,-1 和 0 表示不缓存。
- Cache-Control: no-cache – 控制浏览器不要缓存
- Pragma: no-cache – 控制浏览器不要缓存。 3 个都设置缓存(适用不同浏览器)
Servlet
Servlet 生命周期
创建 Servlet 实例有两个时机:
- 客户端第一次请求某个 Servlet 时,Web 容器创建该 Servlet 的实例
- Web 应用启动时立即创建 Servlet 实例,即
load-on-startup
Servlet
每个 Servlet 的运行都遵循如下生命周期:
- 创建 Servlet 实例
- Web 容器调用 Servlet 的
init
方法,对 Servlet 进行初始化。 - Servlet 初始化后,将一直存在于容器中,用于响应客户端请求。如果客户端发送 Get 请求,容器将调用 Servlet 的 doGet 方法,(Post 类似);或者统一使用 service() 方法处理来响应用户请求。
- Web 容器决定销毁 Servlet 时,先调用 Servlet 的 destroy 方法,通常在关闭 Web 应用之时销毁 Servlet。
servlet 在初始化一次之后,就不再创建,servlet 是一个单例对象。
servlet 是单例
web.xml 文件
web.xml 被称为配置描述符,
Web.xml 配置(该文件在 web/WEB-INF 文件夹下)。
Servlet 3.0 相较于 Servlet 2.5:
新增了一些注解,简化的 javaweb 代码开发,可以省略 web.xml 配置文件 支 持异步处理(多线程技术) 支持可插性特性(书写的代码编译后生成的 class 文件可以 直接部署到其他项目的,自动加载执行)
一般的 web 工程中都会用到 web.xml,web.xml 主要用来配置,可以方便的开发 web 工程 。web.xml 主要用来配置 Filter、Listener、Servlet 等。但是要说明的是 web.xml 并不 是必须的,一个 web 工程可以没有 web.xml 文件。
response 和 request
后端会将前端发送的 request 转换为 JavaBean 对象
前后端数据交互
- 前端需要使用到的技术为: Ajax
Ajax(Asynchronous JavaScript and XML)异步的 JS 和 XML。主要用来:
在前端进行局部刷新:即在不刷新整体页面的情况下,异步的向服务端发送请求,异步的接收服务端 的响应数据,异步的对当前页面的某一部分进行更新。
前端与服务器之间异步交互时使用的数据格式:
-
都是以字符串的形式发送,并且这些字符串的格式为 JSON 字符串格式。
-
前端: Ajax 原生是使用 XML 进行客户端和服务端之间的数据交互的。目前 XML 已经被
json
取 代了。 -
服务端: 发送数据之前先将 JavaBean 转换成 JSON 格式的字符串。 服务端向客户端传递数据的时候,可能会有一些比较复杂的数据,比如:JavaBean 对象,或者是 JavaBean 对象的集合。这些数据使用文本形式传递太麻烦,可以把 JavaBean 对象转换成 JSON 格式的字符串,把这个字符串响应给客户端。客户端的 JS 在接收到这个字符串之后,会把它转换成一个 json 对象,传递给回调函数内部。
会话技术
略,见 content\posts\back-end\java-web\token认证.md
JSP
JSP 技术:它可以简化 html 书写,同时动态生成页面。
其实 JSP 底层就是一个 servlet
JSP 技术所开发的 Web 应用程序是基于 Java 的,它可以用一种简捷而快速的方法从 Java 程序生成 Web 页面
JSP基本已经不使用
过滤器
应用场景:
- 登录权限检查
- 浏览器发出的任何请求,通过过滤器统一处理中文乱码。
Maven
Maven 作用:
- 依赖管理
- 项目生命周期管理:编译、测试、打包、部署、运行。这些都是基于插件完成的,例如: 开发中使用的 tomcat 插件
- maven 对工程分模块构建。 maven 工程有自己标准的 工程目录结构
补充项目结构图:
Maven 的常用命令:
- clean 命令:清除编译产生的 target 文件夹内容,可以配合相应命令一起使用,如
mvn clean package
,mvn clean test
- complie 命令:该命令可以对 src/main/java 目录的下的代码进行编译
- test 命令:测试命令,执行
src/test/java/
下 junit 的测试用例 - package 命令:mvn package,打包项目;打包后的项目会在 target 目录下找到
- **install 命令:**打包后将其安装在本地仓库
Maven 插件:
Maven 是一个核心引擎,提供了基本的项目处理能力和建设过程的管理,以及一系列的插件 是用来执行实际建设任务。
maven 插件可以完成一些特定的功能。例如,
- 集成 jdk 插件可以方便的修改项目的编译环境;
- 集成 tomcat 插件后,无需安装 tomcat 服务器就可以运行 tomcat 进行项目的发布与测 试。
在 pom.xml 中通过 plugin 标签引入 maven 的功能插件。
依赖范围:(影响 编译、测试、运行)
- compile:默认的依赖范围。在编译、测试、运行时都有效;最终会出现在 jar 包/war 包里
- test:单元测试有效,其它无效。最后生成的 jar 包/war 包里没有这一类 jar 包
- provided: jar 包在其它地方已经提供了,比如:jdk 已经提供了,或者 Tomcat/WebLogicWebSphere 里边提供了。 编译以及测试有效,最终不会出现在 war 包 或 jar 包 里
- runtime:编译无效,测试有效,运行有效。比如:数据库驱动包。
JDBC与DataSource
JDBC(Java Data Base Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
DataSource是一个接口,它由驱动程序供应商实现。共有三种类型的实现:
- 基本实现 - 生成标准的Connection对象
- 连接池实现 - 生成自动参与连接池的Connection对象。此实现与中间层连接池管理器一起使用。
- 分布式事务实现
Spring Boot默认使用 tomcat-jdbc 数据源;你也可以使用其它数据源,比如 Druid 。
Mybatis
它是一个持久层框架,解决项目对数据库的 CRUD 操作。
目前使用 Spring Data JPA 来实现数据持久化也是一种趋势。
Mybatis 采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化 操作。
ORM (Object Relational Mapping) 对象关系映射: 通过建立数据库表和 Java 实 体类的对应关系,从而实现操作实体类就相当于操作数据库表。
相关设计模式:工厂模式(Factory 工厂模式)、构造者模式(Builder 模式)、代理模 式
配置:
- 配置文件:sqlMapConfig.xml:配置 mybatis 的环境,比如数据库的连接信息
- 映射文件:UserDao.xml(一般对应 UserDao.java)或 UserMapper.xml
- 注解
因为是 maven 项目,所有 xml 的配置文件应该放在 resources 下,而配置文件的读取 我们借助 Resources 类完成
几个插件:
- 通用Mapper可以简化对单表的CRUD操作,
- PageHelper分页插件可以帮我们自动拼接分页SQL,
- 并且可以使用 MyBatis Geneator 来自动生成实体类(javabean),Mapper接口和Mapper xml代码,非常的方便。插件地址及作者链接https://gitee.com/free。
Mybatis 中的多表操作:
Mybatis 中的注解开发:
Spring
依赖注入
依赖注入:Dependency Injection。它是 spring) 框架核心 ioc 的具体实现。
那这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。简单的 说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。 这就是依赖注入。
能注入的数据:有三类
- 基本类型和 String
- 其他 bean 类型(自定义的 Bean,需要先在配置文件中或者注解中进行配置)
- 复杂类型/集合类型
能注入的方式:
- 第一种:使用构造函数提供
- 第二种:使用 set 方法提供(使用 p 名称空间注入)
更多理论知识请参考《Spring》
-
spring 中基于 XML 的 IOC 配置:
applicationContext.xml,管理对象的创建。示例(spring01_di ),applicationContext.xml 中的部分内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
<!-- ApplicationContext:只要一读取配置文件,默认情况下就会创建所有对象。(立即加载) BeanFactory:什么时候使,用什么时候创建对象。(延迟加载) --> <!--把对象的创建交给spring来管理--> <!-- 数据是写死的,那么该如何传入可变数据?? --> <!-- 构造器注入 --> <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl1"> <constructor-arg name="name" value="Fan"/> <constructor-arg name="age" value="25"/> <!-- 对于Date这种引用类型(自定义的引用类型也一样),需要spring先为你创建一个对象,再通过ref引用 --> <constructor-arg name="birthday" ref="now"/> </bean> <bean id="now" class="java.util.Date"/> <!-- Set 注入:需要存在set方法 --> <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2"> <property name="name" value="小明"/> <property name="age" value="20"/> <!-- 对于Date这中引用类型,需要spring先为你创建一个对象,再引用 --> <property name="birthday" ref="now2"/> </bean> <bean id="now2" class="java.util.Date"/> <!-- 使用p名称空间注入数据(本质还是调用set方法,所以需要存在set方法)--> <bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl2" p:name="胡歌" p:age="30" p:birthday-ref="now"/> <!-- 通过工厂方法注入 --> <!-- 使用场景:当一个类没有公开的构造方法时,比如单例类,但是它提供了静态方法getInstance()来获取实例 --> <bean id="stage" class="com.spring.entity.Stage" factory-method="getInstance"/> <!-- 指定Bean的作用域:scope,默认为 singleton --> <bean id="ticket" class="com.spring.entity.Ticket" scope="prototype"/> <!-- 指定初始化和销毁Bean时执行的方法 --> <bean id="light" class="com.spring.entity.Light" init-method="turnOnTheLight" destroy-method="turnOffTheLight"/> <!-- 如何注入集合属性 --> <bean id="accountService4" class="com.itheima.service.impl.AccountServiceImpl3"> <!--数组--> <property name="myArrays"> <set> <value>aaa</value> <value>bbb</value> <value>ccc</value> </set> </property> <!--list集合(更多集合省略)--> <property name="myList"> <set> <value>AAAAA</value> <value>BBBBB</value> <value>张艺谋</value> </set> </property> </bean> <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"> <property name="runner" ref="queryRunner"/> </bean> <!-- 我们还可在此配置数据源(url,用户密码等): 这里我们将配置信息写入jdbc.properties文件 --> <!--加载jdbc.properties 使用 ${jdbc.url}--> <context:property-placeholder location="jdbc.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"/> <property name="jdbcUrl" value="${jdbc.url}"/> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--创建QueryRunner的对象 QueryRunner queryRunner = new QueryRunner(ds); --> <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"> <constructor-arg name="ds" ref="dataSource"/> </bean>
在测试类中的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@Test public void test01() { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); //我们并非直接new一个AccountService AccountService as = (AccountService) ac.getBean("accountService"); as.saveAccount(); } @Test public void test02() { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); // 这里 accountService2 是 配置文件中 bean 标签下的 id AccountService as = (AccountService) ac.getBean("accountService2"); as.saveAccount(); }
另外可参考:
-
spring 中基于注解的 IOC
参考 《Spring 第三天笔记》
(1) 用于创建对象的注解,
@Component
,它们的作用相当于<bean>
标签@Component
:标注一个普通的 spring Bean 类。它的value
属性用于指定 bean 的 id。当我们不写时,它的默认值是当前类名,且首字母改小写。以及
@Component
的衍生注解:@Controller
:用来修饰 WEB 层 类 ( 控制层 )(springMVC 延用了该注解 )@Service
:用来修饰 service 层类 ( 业务层)@Repository
:用来修饰 DAO 层类 ( 持久层)
(2)用于注入数据的
先来看一下之前的示例:
1 2
<!-- 存在一个 id(名称) 和 类型 --> <bean id="ticket" class="com.spring.entity.Ticket"/>
所以这里会出现按 id(名称) 和按类型方式注入的注解:
@Autowired
:自动按照类型注入。@Qualifier
:在按照类型注入的基础之上再按照名称(id)注入。不能独立使用 。@Resource
:直接按照 bean 的 id 注入。如果 id 属性不存在,可以再按照类型注入 。它可以独立使用;JSR-250 标准(基于 jdk)。它的name
属性:用于指定 bean 的 id,如果指定 name,只能按照 bean 的 id 注入,不能按照类型注入。
注意: 1)以上三个注入都只能注入其他 bean 类型的数据,而基本类型和 String 类 型无法 使用上述注解实现。 2)集合类型的注入只能通过 XML 来实现。
@Value
: 用于注入基本类型和 String 类型的数据。 它的 value
属性,用于指定数
据的值。它可以使用 spring 的 SpEL。
示例(spring02_anno_ioc):
|
|
|
|
测试类:
|
|
除此之外:我们还需要指定 spring 在创建容器时要扫描的包;我们可以在
applicationContext.xml 中配置:
|
|
也可以通过,创建 SpringConfiguration.java 配置类加注解的方式来实现;这样一来我们 就可以完全替换 xml 文件。一般我们将其放在 config 包下,示例:
|
|
|
|
测试(上的变化):
|
|
另外可参考: (推荐 ⭐)
Spring 创建这个类的时候,默认采用的单例的模式进行创建的
Spring Bean 生命周期:
自动化装配 bean
Spring 从两个角度来实现自动化装配:
- 组件扫描(component scanning):Spring 会自动应用上下文中所创建的 bean
- 自动装配(autowiring):Spring 自动满足 bean 之间的依赖。
组件扫描和自动装配组合在一起就能发挥出强大的威力,它们能够将你的显 式配置降低 到最少。
创建可被发现的 bean:
@Component
:作为组件类,并为其创建 bean@ComponentScan
:扫描某个包的组件,即扫描包下的@Component
。 将@ComponentScan
放在 javaConfig 类(配置类)上使用。实现自动装配
使用
@Autowired
,用于方法之上;或使用@Inject
。自动装配就是让 Spring自 动满足 bean 依赖的一种方法,在满足依赖 的过程中,会在 Spring 应用上下文中 寻找匹配某个 bean 需求的其他 bean
Spring 整合 Junit
观察上面的测试代码,我们仍然需要使用 ApplicationContext
示例的 getBean()
方
法;但当我们将 Spring 和 Junit 进行了整合后变成:
|
|
SpEL 表达式
在 Spring 配置过程中有时会用到 SpEL,所以有必要了解一下。
Spring 表达式语言(Spring Expression Language,SpEL)
SpEL 的写法: #{ SpEL expression }
JSP 中的 EL 表达式的基本形式为:
${表达式}
, SpEL 也兼容这种写法
请参考:
Spring 事务控制与 AOP
见《Spring 5 第三天,第四天笔记》
Spring MVC
我们的开发架构一般都是基于两种形式,
- 一种是 C/S 架构,也就是 客户端 / 服务器
- 另一种是 B/S 架构,也就是 浏览器 / 服务器
在 JavaEE 开发中,几乎全都是 基于 B/S 架构的开发。那么在 B/S 架构中,系统标 准的三层架构包括:表现层、业务层、持久层。
-
表现层:也就是我们常说的 web 层。它负责接收客户端请求,向客户端响应结果, 通常客户端使用 http 协议请求 web 层,web 需要接收 http 请求,完成 http 响应。 表现层包括展示层和控制层:
- 控制层负责接收请求,
- 展示层负责结果的展示。
表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响 应给客户端。表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其 他层没有关系)
-
业务层:也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的 需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。
业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也 就是我们说的,事务应该放到业务层来控制)
-
持久层:也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数 据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口 ,业务层需要通过数据访问层将数据持久化到数据库中。通俗的讲,持久层就是和数据库 交互,对数据库表进行增删改查的。
服务器端分层三层框架:
graph LR;
A(浏览器) --"请求参数"--> B("表现层: Spring MVC") -->
C("业务层:Srping框架") --> D("持久层:MyBatis")
B --"响应结果"--> A
C --> B
D --> C
MVC 设计模式:
- M(Model)模型:通常指的就是我们的数据模型。JavaBean
- V (View)视图:通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。通常 视图是依据模型数据创建的。
- C(Controller)控制器:是应用程序中处理用户交互的部分。作用一般就是处理程序逻 辑的。 Servlet
Spring MVC 已经成为目前最主流的 MVC 框架之一;它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求 。
Request 流程,生命周期:
Spring MVC 搭建过程:
-
在 IDEA 中创建 Maven Web 工程
-
添加 Maven 依赖
-
配置 web.xml 文件
配置前端控制器:DispatcherServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置Servlet的初始化参数,读取spring mvc 的配置文件,创建spring 容器 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 配置Tomcat启动时加载的对象 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
配置 springmvc.xml 文件
1 2 3 4 5 6 7 8 9 10 11 12 13
<!-- 开启组件的扫描--> <context:component-scan base-package="com.itheima"/> <!-- 配置视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 在此示例中,存在/WEB-INF/pages/目录,且该目录下有一个叫做 --> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 注意:Spring MVC中需要用到各种处理器适配器等,我们可以使用bean标签一个个导入,也可以直接使用下面的标签直接一次性导入 --> <!-- 简写为:启用Spring mvc --> <mvc:annotation-driven/>
-
编写前端页面 (这里是 jsp 页面)
编写 index.jsp ;创建
/WEB-INF/pages/
目录,并在该目录下创建 success.jsp -
编写 Controller 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
@Controller @RequestMapping(path = "/user") //路径可拼接 public class HelloController { /** * 请求参数 * 访问路径是: /user/hello */ @RequestMapping(path = "/hello") public String sayHello() { System.out.println("Hello SpringMVC"); return "success"; } /** * 访问地址:/user/testRequestMapping?username=test */ @RequestMapping(path = "/testRequestMapping", method = {RequestMethod.GET}, params = {"username=test"}, headers = "accept") public String testRequestMapping() { System.out.println("测试 testRequestMapping"); return "success"; } }
另外可参考:
- 搭建 SpringMVC | MrBird ,还介绍了 JavaConfig 配置
- Spring 传递参数 | MrBird
- Spring 表单校验 | MrBird
⭐ 推荐 :@RequestMapping 与@GetMapping 和@PostMapping 等新注释
RESTful Web 服务
RESTful Web 服务控制器只返回对象,对象数据作为 JSON / XML 直接写入 HTTP 响应。
我们可以使用 @RestController
注解 来方便的完成此功能。
@RestController
注解相当于 @ResponseBody
+ @Controller
Spring Boot
- SpringBoot-Learning: Spring Boot 基础教程,Spring Boot 2.x 版本连载中!!!
- spring-boot-demo: spring boot demo 是一个用来深度学习并实战 spring boot 的项目,目前总共包含 65 个集成 demo,已经完成 53 个
- SpringAll: 循序渐进,学习 Spring Boot、Spring Boot & Shiro、Spring Cloud、Spring Security & Spring Security OAuth2,博客 Spring 系列源码
再添两个重量级仓库:
入门示例 :spring-boot-demo-helloworld
⭐Spring Boot 干货系列:(一)优雅的入门篇 | 嘟嘟独立博客
@SpringBootApplication = @EnableAutoConfiguration + @Configuration + @ComponentScan
推荐使用 Spring Initializr 初始化 Spring Boot 项目
Spring Boot 的入门需要理解的概念:
- Spring Boot 父级依赖的概念
- 起步依赖 spring-boot-starter-xx 的概念
- 应用入口类的作用
Spring Boot 2.x 基础教程:工程结构推荐 - 简书
热部署:有多种方式,这里只介绍一种
Spring Cloud
Spring Cloud Alibaba 与 Spring Boot、Spring Cloud 之间不得不说的版本关系 | 程序猿 DD
Spring Cloud 基于 Spring Boot 构建
如何做到前后端分离
我的职业是前端工程师【七】:你真的懂前后端分离吗? - 简书
RESTful Web 服务与传统的 MVC 开发一个关键区别是返回给客户端的内容的创建方式 :传统的 MVC 模式开发会直接返回给客户端一个视图,但是 RESTful Web 服务一般会将 返回的数据以 JSON 的形式返回,这也就是现在所推崇的前后端分离开发。
发送前端请求
- Rest Client (简单)
- 通过 Swagger 的后台 API 接口
- 还有一个关键的技术:ajax
Mock 模拟后端响应
6. quarkus-quickstarts 感觉不错
Quarkus 开源的 Java 多种框架 demo 项目集合。这些示例项目可以快速启动、结构清 晰,初学者可用作 Java 的实战项目,老手可以当作项目脚手架。启动示例:
mvn quarkus:dev
mvn clean package -Pnative
./target/amqp-quickstart-1.0-SNAPSHOT-runner