一、企业级架构
1.1框架图
经典的业务请求过程:前端html页面发起ajax请求(http://localhost:8080/factoryController/findAll),访问SpringMVC框架的Controller控制层,SpringMVC框架解析请求,找到要调用的某个Controller,找到其中的findAll方法,同时把请求提交的参数封装到java对象中。之后Controller层把请求传递给Spring框架的Service业务层,Service层在把请求传递给Mybatis框架的Mapper持久层,Mapper访问MySQL数据库进行数据库表的查询,查询结果返回给Mapper层,Mapper再返回给Service层,Service再返回给Controller层。Controller把java数据转换为json字符串,返回给ajax调用,ajax进行回调并把json字符串转换为js对象,再在页面中就可以通过js/vue解析js对象,最终把数据展现到html页面中。
1、开发工具: 前端采用HBuilderX,而后端采用eclipse/idea
2、项目管理: 前端采用npm、webpack,而后端采用Maven、SpringBoot
3、web中间件: 前端采用NodeJS,而后端采用Tomcat
二、Maven
2.1概述
是项目构建的工具.
以前是需要手动管理jar包(下载/安装/编译)
全新的设计体系:创先河的发明pom模型,引入了“仓库”、“依赖”、“坐标”和“命令”。
2.2四大特征
2.2.1仓库 repository
中央仓库(project object model):就是一个国外的网址,存了大量的jar包
镜像仓库(mirror):国内的网址,人家从中央仓库下载了所有jar包(阿里/网易/华为...)
本地仓库(local):从镜像仓库down的jar包,存到本地的磁盘中(可以自己指定)
2.2.2依赖 dependency
每个核心jar包形成一个依赖,maven底层进行它相关的jar的自动导入
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
2.2.3坐标 coordinate
坐标:jar包的真实路径(层层的文件夹),groupId-artifactId-version
2.2.4命令 mvn cmd
常用命令:
1、 clean 清理
2、 compile 编译
3、 test 测试
4、 site 站点文档
5、 package 打包jar、war
6、 deploy 部署到私服
7、 install 安装jar到本地仓库中
8、 run 运行
每个周期中运行一个命令时,在这个周期里的其他在该命令之前的phase步骤都会执行。如:执行install会自动执行compile(编译java变成了class),test(运行所有单元测试类),package(把整个项目零碎的class文件打包为jar包),最终把成品jar发布到本地仓库中。但执行install并不会自动执行clean。
2.3小结
优点:
1、Jar管理起来更加轻松,已经被业界广泛采用,springboot就是maven的延伸
2、仓库的独特设计,实现仓库自行维护
3、依赖管理方便很多,把开发人员从手工导包解脱出来
4、坐标体系使不同厂商的文件也井然有序,不会冲突覆盖
5、生命周期对应命令,使一键做完以前手动的n步事情
缺点:
1、下载异常让初学者手足无措,不得不删掉仓库重新下就好了,为什么好了,不知道
2、部分包因为版本问题,需要手工导入
3、引发新的问题,版本冲突:大型项目中jar中依赖其它jar包,会发生你调3.1,我调3.2,臭名昭著的版本冲突问题,如何解决呢?上面方式手工排除,而maven采用就近原则
4、本地仓库日积月累巨大,本人的达到2g,很多低版本的jar已经无用,或者过气的技术的jar
5、大型项目中jar冲突非常厉害,仍需手动排除,而且实现方式很多,没有统一规则。如当年加入dubbo的jar时,那冲突叫做满天飞,项目做完也没很良好的解决。但这点springboot却解决了,maven的失败却早就了今天springboot能大行其道的根本原因。
2.4安装
2.4.1官网
http://maven.apache.org/download.html
2.5配置settings.xml
2.5.1配置文件
apache-maven-3.6.3\conf\settings.xml 全局配置文件
2.5.2设置镜像仓库
默认从maven官网下载,全球都去下载,又是国外网站,因此速度缓慢。
配置为阿里镜像,速度快,但有时有错,如果有错,删除配置,默认从maven官网下载。配置阿里私服镜像仓库,可以写在<mirrors></mirrors>中间:
<!--阿里私服地址-->
<mirror>
<id>ali</id>
<name>ali Maven</name>
<mirrorOf>*</mirrorOf>
<url>https://maven.aliyun.com/repository/public/</url>
</mirror>
2.5.3改变仓库位置
默认仓库位置:C:\Users\lpx\.m2,建议改变默认仓库位置的配置,否则重装操作系统时,可能会把仓库误删除。
三、 eclipse 集成 maven
在教学文档11-18里面有详解
四、IDEA集成maven
4.1IDEA 里配置 maven
--File-Settings-maven-配置三处(解压位置/settings.xml/本地仓库)-ok
4.2IDEA创建 maven工程
--File-New-Project-选Maven-next-输入工程名/groupId-Finish
--配置maven管理工程
--File-Settings-maven-配置三处(解压位置/settings.xml/本地仓库)-ok
--双击打开pom.xml文件,不报错就行了.
如果报错,打开右侧的Maven视图-点击刷新就行了maven会再去下载jar包。
在教学文档11-18里面有详解
五、开发JDBC程序(练习)
5.1打开pom.xml文件,添加依赖的jar包坐标
5.2写jdbc代码
--maven的目录结构
src/main/java --写正式的代码
src/main/resources --存资源文件js/css/jpg....
src/test/java -- 写测试代码
5.3练习
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestJDBC {
public static void main(String[] args) throws Exception {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/demo"
+"?characterEncoding=utf8" //防止中文乱码
+"&useSSL=false" //高版本的jar需要忽略权限
+"&serverTimezone=Asia/Shanghai";//高版本的jar需要
String name="root";
String pwd="root";
//获取和数据库的连接
Connection conn = DriverManager.getConnection(url,name,pwd);
//获取传输器,查询user表的所有数据
String sql = "select * from user";
PreparedStatement ps = conn.prepareStatement(sql);
//执行SQL
ResultSet rs = ps.executeQuery();
//解析结果集
while(rs.next()){
for (int i = 1; i <= 3 ; i++) {
System.out.println( rs.getString(i) );
}
}
//释放资源
rs.close();
ps.close();
conn.close();
}
}
六、SpringBoot(微服务)
6.1概述
简化了Spring框架的开发和配置过程.
本质上是一个maven项目
6.2特点
1、创建独立的Spring应用程序
2、嵌入的Tomcat,无需部署WAR文件
3、简化Maven配置
4、自动配置Spring
5、提供生产就绪型功能,如指标,健康检查和外部配置
6.3IDEA创建springboot项目
--File-New-Project-选择springboot项目-next-输入名字(groupId/项目id/改成 java8)-选中要用的功能(spring web)-Finish
--配置maven
Settings-maven-配置(解压的位置/settings的位置/本地仓库的位置)-ok
--刷新maven
--使用自动生成的文件,并运行,表示服务器已启动(小红点亮起)
eclipse创建springboot项目在教学文档11-18里面有详解(包括IDEA)
七、Tomcat
--是一个轻量级的服务器技术.可以当做是一个容器
--容器里存了很多项目,通常存在Tomcat里的项目,才能被客户端访问
--接受客户端发来的请求,开始找要访问哪个项目,再找要访问哪个类里的哪个方法
--要返回结果,通过Tomcat里的技术再把数据返回给浏览器展示
Springboot整合了。
八、SpringMVC框架
8.1概述
SpringMVC是Spring家族的产品,和spring框架可以无缝衔接
还遵循了MVC的设计模式.就是想让三层松耦合,互不影响.
POJO就是Model层,我们的JSP就是视图层,我们的Controller就是控制层。
M: Model,是数据模型:封装数据
V: View,是视图:就是展示页面的数据
C: Controller,是控制器: 可以接受view发来的请求,给view做响应数据的展示
持久层DAO:持久层用来和数据库读写ORM
业务层Servie:业务层用来处理复杂的业务逻辑
控制层Controller:控制层用来处理MVC的控制。
提高代码的可读性,实现程序间的松耦合、提高代码复用性。
8.2原理
过程简单描述:
客户端发送请求-> 前端控制器 DispatcherServlet 接受客户端请求 -> 找到处理器映射 HandlerMapping 解析请求对应的 Handler-> HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑 -> 处理器返回一个模型视图 ModelAndView -> 视图解析器进行解析 -> 返回一个视图对象->前端控制器 DispatcherServlet 渲染数据(Moder)->将得到视图对象返回给用户.
更具体一些的描述:
1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、andlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
五大组件:请求->前端控制器/处理器映射器/处理器适配器/视图解析器/视图渲染->响应
前端控制器DispatcherServlet::接受请求,分发请求
处理器映射器HandlerMapping::根据地址栏的请求,找到具体的Controller
--url:http://localhost:8080/student/save
--返回:StudentController/save()
处理器适配器HandlerAdaptor::开始调用方法,执行任务,返回结果
--MVC: Controller - Service - DAO
视图解析器ViewReslover::解析返回的数据,把数据解析成按照规则整理好的数据
视图渲染View::找到正确的网页,做数据展示
8.3SpringMVC里涉及到的注解
@RestController:标记着这个类是Controller层的代码+会把返回的数据自动变成json
@RequestMapping("/car"):就是要把地址栏里的url信息和哪个Controller做匹配
SpringMVC是MVC设计模式的,主要负责的就是Controller代码和Model代码
8.4练习
package cn.tedu.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/op")
public class Car1Contorller {
@RequestMapping("/io")
public String io(){
return "访问成功";
}
@RequestMapping("/ko")
public void ty(){
System.out.println("123");
}
}
8.5处理请求参数
8.5.1RestFul方式(推荐)
为了简化GET请求的写法,可以使用RESTFul方式,用法:
1、需要使用注解@PathVariable来获取请求路径中的参数值,
@PathVariable用来绑定值
@RequestMapping("insert4/{id}") //{id}用来获取地址栏里的参数10
public void insert4( //@PathVariable解析{id}里id的数据 @PathVariable int id){ System.out.println(id); }
2、通过{???}获取路径中传递来的值
3、以前GET的访问方式即将被简化成:
http://localhost:8080/car/insert/1/张三/18
8.5.2GET方式发送给服务器
--说明:把要给服务器发送的数据在地址栏拼接,不安全,长度有限制
package cn.tedu.controller;
import cn.tedu.pojo.Car;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//测试springmvc自动解析请求参数
@RestController
@RequestMapping("/car3")
public class Car3Controller {
//7,,,利用springmvc框架提供的restful风格,优化get的提交方式
//普通的get提交:http://localhost:8080/car3/insert5?id=10&name=张三
//restful提交:http://localhost:8080/car3/insert5/10/张三
@RequestMapping("insert5/{x}/{y}") //{x}用来获取地址栏里的参数10
public void insert5(
//@PathVariable解析{x}里x的数据
@PathVariable int x,
@PathVariable String y){
System.out.println(x+y);
}
//6,,,利用springmvc框架提供的restful风格,优化get的提交方式
//普通的get提交:http://localhost:8080/car3/insert3?id=10
//restful提交:http://localhost:8080/car3/insert4/10
@RequestMapping("insert4/{id}") //{id}用来获取地址栏里的参数10
public void insert4(
//@PathVariable解析{id}里id的数据
@PathVariable int id){
System.out.println(id);
}
//5,,,利用springmvc框架把参数,自动封装成对象
//测试:http://localhost:8080/car3/insert3?id=1&name=2&type=3&color=4&price=5
@RequestMapping("insert3")
public void insert3(Car c){
System.out.println(c);
}
//4,,,利用springmvc框架解析多个参数
//测试:http://localhost:8080/car3/insert2?id=1&name=张三&age=18&addr=北京
@RequestMapping("insert2")
public void insert2(int id,String name,int age,String addr){
System.out.println(id+name+age+addr);
}
//3,,,利用springmvc框架解析多个参数(还可以自动类型转换)
//测试:http://localhost:8080/car3/insert?id=1&name=张三&age=18
@RequestMapping("insert")
public void insert(String id,String name,int age){
System.out.println(id+name+age);
}
//2,,,利用springmvc框架解析1个参数
//测试:http://localhost:8080/car3/add?id=1
@RequestMapping("/add")
public void add(int id){
//成功接受到了id的值1
System.out.println(id);
}
//1,,,我们手动解析url地址栏里的数据
public void mine(){
String url = "http://localhost:8080/car/insert?id=1&name=张三&age=18";
//url.split("\\?")得到[http://localhost:8080/car/insert, id=1&name=张三&age=18]
//[1]得到 id=1&name=张三&age=18
//split("&")得到 [id=1, name=张三, age=18]
String[] s = url.split("\\?")[1].split("&");
for (String ss : s) {
//data得到 [id,1] [name,张三] [age,18]
//[1]得到 1 张三 18
String data = ss.split("=")[1];
//打印解析到的数据1 张三 18
System.out.println(data);
}
}
}
前后端整合练习
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试前后端连接</title>
</head>
<body>
<a href="http://localhost:8080/car3/get">点我点我玩</a>
<a href="http://localhost:8080/car3/get2?id=1&age=10">get提交数据</a>
<a href="http://localhost:8080/car4/get3/1/10">restful提交数据</a>
</body>
</html>
package cn.tedu.controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController //这个类是controller层的代码+可以接受浏览器发来的请求
@RequestMapping("/car4") //和地址栏里的url匹配
public class Car4Controller {
//地址栏:http://localhost:8080/car4/get3/1/10
//{id}是restful的特殊语法: 从地址栏里获取参数的值
@RequestMapping("/get3/{id}/{age}")
public String get3(
//获取{id}里id的值
@PathVariable int id,
@PathVariable int age) {
//给浏览器做出响应,结果展示在页面上
return id+""+age;
}
@RequestMapping("/get2") //和地址栏里的url匹配
public String get2(int id,int age) {
//给浏览器做出响应,结果展示在页面上
return id+""+age;
}
@RequestMapping("/get")
public String get(){
return "abc";
}
}
8.5.3POST方式发送给服务器
--说明:把要给服务器发送的数据后台拼接,安全,数据没有大小的限制
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>测试 前后端 连接</title>
<!-- 在HTML中嵌入css代码 -->
<style>
input[type='text']{
width: 300px;
height: 30px;
}
</style>
<!-- 引入jQuery -->
<script src="jquery-1.8.3.min.js"></script>
<!-- ajax异步访问局部刷新,经常用!! -->
<script>
function sub(){
$.ajax({
type: "POST" ,
// 'http://localhost:8080/stu/add' from origin 'http://127.0.0.1:8848'
//has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
url: "http://localhost:8080/stu/add" ,
data: $("#form1").serialize() , //把表单里的所有数据变成串提交给服务器
dataType: "json" ,
success: function(data){
console.log(data);
}
});
}
</script>
</head>
<body style="margin: 100px;">
<form method="post" action="#" id="form1">
<table>
<h2>学生信息管理系统MIS</h2>
<tr>
<td>姓名:</td>
</tr>
<tr>
<td>
<input type="text" name="user" placeholder="请输入姓名..."/>
</td>
</tr>
<tr>
<td>年龄:</td>
</tr>
<tr>
<td>
<input type="text" name="age" placeholder="请输入年龄..."/>
</td>
</tr>
<tr>
<td>
性别:(单选框)
<input type="radio" name="sex" value="1" checked="checked"/>男
<input type="radio" name="sex" value="0" />女
</td>
</tr>
<tr>
<td>
爱好:(多选)
<input type="checkbox" name="hobby" value="ppq" checked="checked"/>乒乓球
<input type="checkbox" name="hobby" value="ps" />爬山
<input type="checkbox" name="hobby" value="cg" />唱歌
</td>
</tr>
<tr>
<td>
学历:(下拉框)
<select name="edu">
<option value="0">本科</option>
<option value="1">专科</option>
<option value="2">研究生</option>
<option value="3">博士</option>
</select>
</td>
</tr>
<tr>
<td>
入学日期: <br />
<input type="date" name="intime"/>
</td>
</tr>
<tr>
<td>
<input type="button" onclick="sub();" value="保存"
style="background-color: blue;color: white;border: blue;
width: 50px;height: 30px;"/>
<input type="reset" value="取消" style="background-color:
palevioletred;color: white;border: blue;width: 50px;
height: 30px;"/>
</td>
</tr>
</table>
</form>
</body>
</html>
package cn.tedu.pojo;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Arrays;
import java.util.Date;
//封装网页中发来的数据
public class Student {
private String user;//封装网页中输入的用户
private int age;//封装网页中输入的年龄
private int sex;//封装网页中选择的性别
private String[] hobby;//封装网页中选择的多个爱好
private int edu;//封装网页中选择的学历
//格式化日期的:浏览器上选择的日期是string类型,要转成Date类型就要用注解,否则页面400
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date intime;//封装网页中填的日期
//提供 set/get 和 toString
}
package cn.tedu.controller;
import cn.tedu.pojo.Student;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/stu")
@CrossOrigin(origins = "*")//解决跨域问题,放行所有请求
public class StudentController {
@RequestMapping("/add")
public Student add(Student s){
System.out.println(s);
return s;
}
}
九、拓展
9.1.执行过程
url的解析执行过程:
浏览器输入的url,就会被解析后传入web中间件(/hi),web中间件再会进一步的解析,找到对应的Controller的某个注解里对应的url @RequestMapping({"/","/hi"}) ,从而就找到HelloController的hi()方法。最终利用反射执行这个类的方法(将来这个方法中就用来编写实现业务逻辑代码)。因为使用了@RestController,返回的String字符串对象底层会使用jackson工具类转换java对象为json字符串,返回给浏览器,浏览器将字符串回显(展示)在页面上。
8080端口冲突问题看教学文档11-18里面有详解
9.2.请求响应过程
2.1Http协议
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web)服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据(HTML文件、图片文件、查询结果等)。
2.2执行过程
怎么浏览器输入url就可以找到我们写的controller进行执行并且返回呢?
其实这底层是有一套标准的,这个标准称为HTTP协议。我们浏览器成输入的http://这就代表执行http协议。
9.3.springmvc和struts2比较
9.4SpringMVC常用的注解
@Controller 标识是一个Controller,Spring包扫描创建实例
@RequestMapping 请求后的映射路径
@PathVariable 标识接收单个参数
@ResponseBody 返回对象利用jackson工具类转换为json字符串
@RequestParam 参数名和请求参数名称不同时使用,可以设置默认值