java项目解析
注解
@PathVariable
使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id){
System.out.println(id);
return "OK";
//多参
@RequestMapping("/path/{id}/{name}")
public String pathParam2(@PathVariable Integer id, @PathVariable
String name){
System.out.println(id+ " : " +name);
return "OK";
@RestController和@ResponseBody
但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解,并没有使用@ResponseBody注解,怎么给浏览器响应呢?
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
}
原因:在类上添加的@RestController注解,是一个组合注解。
@RestController = @Controller + @ResponseBody
结论:在类上添加@RestController就相当于添加了@ResponseBody注解。
-
类上有@RestController注解或@ResponseBody注解时:表示当前类下所有的方法返回值做为响应数据
-
方法的返回值,如果是一个POJO对象或集合时,会先转换为JSON格式,在响应给浏览器
@Component
使用Spring提供的注解:@Component ,就可以实现类交给IOC容器管理
而Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了
@Component的衍生注解:
@Controller (标注在控制层类上)
@Service (标注在业务层类上)
@Repository (标注在数据访问层类上)
在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。如果没有指定,默认为类名首字母小写。
使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。
.
使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描
@ComponentScan注解虽然没有显式配置,但是实际上已经包含在了引导类声明注解
@SpringBootApplication 中, 默认扫描的范围是SpringBoot启动类所在包及其子包
解决方案:手动添加@ComponentScan注解,指定要扫描的包 ( 仅做了解,不推荐 )
.
@Autowired
使用Spring提供的注解:@Autowired ,就可以实现程序运行时IOC容器自动注入需要的依赖对象
Autowired翻译过来叫:自动装配。
.
那如果在IOC容器中,存在多个相同类型的bean对象,程序运行会报错
解决上述问题呢?Spring提供了以下几种解决方案:
-
@Primary(默认实现)
-
@Qualifier(指定名称)
-
@Resource(指定名称)
使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
@Qualifier注解:指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。
@Qualifier注解不能单独使用,必须配合@Autowired使用
@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
面试题 : @Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入
细节
前端的代码是如何转换成用户眼中的网页的 ?
通过浏览器转化(解析和渲染)成用户看到的网页
浏览器中对代码进行解析和渲染的部分,称为 浏览器内核
Web标准
也称为网页标准,由一系列的标准组成,大部分由W3C( World Wide Web
Consortium,万维网联盟)负责制定。由三个组成部分:
HTML:负责网页的结构(页面元素和内容)。
CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)。
JavaScript:负责网页的行为(交互效果)。
前端应该如何从后台获取数据-Ajax
Ajax: 全称Asynchronous JavaScript And XML,异步的JavaScript和XML
与服务器进行数据交换:通过Ajax可以给服务器发送请求,并获取服务器响应的数据。
异步交互:可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用的校验等等
ajax使用方法
创建XMLHttpRequest对象,用于和服务器交换数据,也是原生Ajax请求的核心对象,
提供了各种方法。代码如下:
//1. 创建XMLHttpRequest
var xmlHttpRequest = new XMLHttpRequest();
调用对象的open()方法设置请求的参数信息,例如请求地址,请求方式。然后调用send()方法向服务器发送请求,代码如下:
//2. 发送异步请求
xmlHttpRequest.open('GET,'http://yapi.smartxwork.cn/mock/169327/emp/list');
xmlHttpRequest.send();//发送请求
通过绑定事件的方式,来获取服务器响应的数据。
//3. 获取服务响应数据
xmlHttpRequest.onreadystatechange = function(){
//此处判断 4表示浏览器已经完全接受到Ajax请求得到的响应, 200表示这是
一个正确的Http请求,没有错误
if(xmlHttpRequest.readyState == 4 && xmlHttpRequest.status ==
200){
document.getElementById('div1').innerHTML =
xmlHttpRequest.responseText;
}
}
Axios的基本使用
更加简单的发送Ajax请求的技术Axios 。Axios是对原生的AJAX进行封装,Axios中文文档 | Axios中文网
Axios的使用比较简单,主要分为2步:
引入Axios文件
<script src="js/axios-0.18.0.js"></script>
使用Axios发送请求,并获取响应结果,官方提供的api很多,此处给出2种,如下
发送 get 请求
axios({
method:"get",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1?
username=zhangsan"
}).then(function (resp){
alert(resp.data);
})
发送 post 请求
axios({
method:"post",
url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
data:"username=zhangsan"
}).then(function (resp){
alert(resp.data);
});
axios()是用来发送异步请求的,小括号中使用 js的JSON对象传递请求相关的参数:
method属性:用来设置请求方式的。取值为 get 或者 post。
url属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2。
data属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为data 属性的值。
then() 需要传递一个匿名函数。我们将 then()中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。
Axios快速入门
后端实现
查询所有员工信息服务器地址:http://yapi.smart-xwork.cn/mock/169327/emp/list
根据员工id删除员工信息服务器地址:http://yapi.smart-xwork.cn/mock/169327/emp/deleteById
前端实现
首先在VS Code中创建js文件夹,与html同级,然后将资料/axios-0.18.0.js 文件拷贝到js目录下,然后创建名为02. Ajax-Axios.html的文件,工程结果如图所示:
然后在html中引入axios所依赖的js文件,并且提供2个按钮,绑定单击事件,分别用于点击时发送ajax请求,完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initialscale=1.0">
<title>Ajax-Axios</title>
<script src="js/axios-0.18.0.js"></script>
</head>
<body>
<input type="button" value="获取数据GET" onclick="get()">
<input type="button" value="删除数据POST" onclick="post()">
</body>
<script>
function get(){
//通过axios发送异步请求-get
}
function post(){
//通过axios发送异步请求-post
}
</script>
</html>
然后分别使用Axios的方法,完整get请求和post请求的发送
get请求代码如下:
//通过axios发送异步请求-get
axios({
method: "get",
url: "http://yapi.smart-xwork.cn/mock/169327/emp/list"
}).then(result => {
console.log(result.data);
})
post请求代码如下:
//通过axios发送异步请求-post
axios({
method: "post",
url: "http://yapi.smart-xwork.cn/mock/169327/emp/deleteById",
data: "id=1"
}).then(result => {
console.log(result.data);
})
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initialscale=1.0">
<title>Ajax-Axios</title>
<script src="js/axios-0.18.0.js"></script>
</head>
<body>
<input type="button" value="获取数据GET" onclick="get()">
<input type="button" value="删除数据POST" onclick="post()">
</body>
<script>
function get(){
//通过axios发送异步请求-get
axios({
method: "get",
url: "http://yapi.smartxwork.cn/mock/169327/emp/list"
}).then(result => {
console.log(result.data);
})
}
function post(){
// 通过axios发送异步请求-post
axios({
method: "post",
url: "http://yapi.smartxwork.cn/mock/169327/emp/deleteById",
data: "id=1"
}).then(result => {
console.log(result.data);
})
}
</script>
</html>
Element
是饿了么公司前端开发团队提供的一套基于 Vue 的网站组件库,用于快速构建网页。
需要在main.js这个入口js文件中引入ElementUI的组件库,其代码如下:
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
HTTP协议特点
· 基于TCP协议: 面向连接,安全
TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全
· 基于请求-响应模型: 一次请求对应一次响应(先请求后响应)
· HTTP协议是无状态协议: 对于数据没有记忆能力。每次请求-响应都是独立的
无状态指的是客户端发送HTTP请求给服务端之后,服务端根据请求响应数据,响应完后,不会记录任何信息。
缺点: 多次请求间不能共享数据
优点: 速度快
请求之间无法共享数据会引发的问题:
如:京东购物。加入购物车和去购物车结算是两次请求
由于HTTP协议的无状态特性,加入购物车请求响应结束后,并未记录加入购物车是何商品发起去购物车结算的请求后,因为无法获取哪些商品加入了购物车,会导致此次请求无法正确展示数据
具体使用的时候,我们发现京东是可以正常展示数据的,原因是Java早已考虑到这个问题,并提出了使用会话技术(Cookie、Session)来解决这个问题。
组成
HTTP协议又分为:请求协议和响应协议
请求协议:浏览器将数据以请求格式发送到服务器
包括:请求行、请求头 、请求体
响应协议:服务器将数据以响应格式返回给浏览器
包括:响应行 、响应头 、响应体
GET
获取资源。
POST
传输实体主体。
向指定资源提交数据进行处理请求(例:上传文件),数据被包含在请求体中。
PUT
传输文件。
tomcat中识别 Servlet程序-BS架构
在Tomcat这类Web服务器中,是不识别我们自己定义的Controller的。但是我们前面讲到过Tomcat是一个Servlet容器,是支持Serlvet规范的,所以呢,在tomcat中是可以识别 Servlet程序的。 那我们所编写的XxxController 是如何处理请求的,又与Servlet之间有什么联系呢?
其实呢,在SpringBoot进行web程序开发时,它内置了一个核心的Servlet程序DispatcherServlet,称之为 核心控制器。DispatcherServlet 负责接收页面发送的请求,然后根据执行的规则,将请求再转发给后面的请求处理器Controller,请求处理器处理完请求之后,最终再由DispatcherServlet给浏览器响应数据。
那将来浏览器发送请求,会携带请求数据,包括:请求行、请求头;请求到达tomcat之后,tomcat会负责解析这些请求数据,然后呢将解析后的请求数据会传递给Servlet程序的HttpServletRequest对象,那也就意味着 HttpServletRequest 对象就可以获取到请求数据。 而Tomcat,还给Servlet程序传递了一个参数 HttpServletResponse,通过这个对象,我们就可以给浏览器设置响应数据 。
那上述所描述的这种浏览器/服务器的架构模式呢,我们称之为:BS架构
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。
day5-postman
接收参数
在Springboot的环境中,对原始的API进行了封装,接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。
@RestController
public class RequestController {
// http://localhost:8080/simpleParam?name=Tom&age=10
// 第1个请求参数: name=Tom 参数名:name,参数值:Tom
// 第2个请求参数: age=10 参数名:age , 参数值:10
//springboot方式
@RequestMapping("/simpleParam")
public String simpleParam(String name , Integer age ){//形参名和
请求参数名保持一致
System.out.println(name+" : "+age);
return "OK";
}
}
参数名与形参变量名不同
运行没有报错。 controller方法中的username值为:null,age值为20
结论:对于简单参数来讲,请求参数名和controller方法中的形参名不一致时,无法接收到请求
解决方案:可以使用Spring提供的@RequestParam注解完成映射
在方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名,从而完成映射
@RestController
public class RequestController {
// http://localhost:8080/simpleParam?name=Tom&age=20
// 请求参数名:name
//springboot方式
@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam("name") String username
, Integer age ){
System.out.println(username+" : "+age);
return "OK";
}
}
@RequestParam中的required属性默认为true(默认值也是true),代表该请求参数必须传递,如果不传递将报错
请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam 绑定参数关系
默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系
public String listParam(@RequestParam List hobby){
System.out.println(hobby);
@DateTimeFormat注解的pattern属性中指定了哪种日期格式,前端的日期参数就必须按照指定
的格式传递。
后端controller方法中,需要使用Date类型或LocalDateTime类型,来封装传递的参数。
@RestController
public class RequestController {
//日期时间参数
@RequestMapping("/dateParam")
public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd
HH:mm:ss") LocalDateTime updateTime){
System.out.println(updateTime);
return "OK";
}
}
服务端Controller方法接收JSON格式数据:
传递json格式的参数,在Controller中会使用实体类进行封装。
封装规则:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数。需要使用@RequestBody标识。
@RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性名保持一致)
路径参数
前端:通过请求URL直接传递参数
后端:使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数
@RequestMapping("/path/{id}")
public String pathParam(@PathVariable Integer id){
System.out.println(id);
return "OK";
//多参
@RequestMapping("/path/{id}/{name}")
public String pathParam2(@PathVariable Integer id, @PathVariable
String name){
System.out.println(id+ " : " +name);
return "OK";
响应
controller方法中的return的结果,怎么就可以响应给浏览器呢?
答案:使用@ResponseBody注解
@ResponseBody注解:
类型:方法注解、类注解
位置:书写在Controller方法上或类上
作用:将方法返回值直接响应给浏览器
如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器
@RestController注解
但是在我们所书写的Controller中,只在类上添加了@RestController注解、方法添加了@RequestMapping注解,并没有使用@ResponseBody注解,怎么给浏览器响应呢?
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
System.out.println("Hello World ~");
return "Hello World ~";
}
}
原因:在类上添加的@RestController注解,是一个组合注解。
@RestController = @Controller + @ResponseBody
结论:在类上添加@RestController就相当于添加了@ResponseBody注解。
-
类上有@RestController注解或@ResponseBody注解时:表示当前类下所有的方法返回值做为响应数据
-
方法的返回值,如果是一个POJO对象或集合时,会先转换为JSON格式,在响应给浏览器
统一返回结果![](https://i-blog.csdnimg.cn/blog_migrate/d477c8d5deb0730b1c4c636b6b92fd31.png)
按照统一格式的返回结果进行解析(仅一种解析方案),就可以拿到数据。
统一的返回结果使用类来描述,在这个结果中包含:
响应状态码:当前请求是成功,还是失败
状态码信息:给页面的提示信息
返回的数据:给前端响应的数据(字符串、对象、集合)
定义在一个实体类Result来包含以上信息。代码如下:
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应码 描述字符串
private Object data; //返回的数据
public Result() { }
public Result(Integer code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
//增删改 成功响应(不需要给前端返回数据)
public static Result success(){
return new Result(1,"success",null);
}
//查询 成功响应(把查询结果做为返回数据响应给前端)
public static Result success(Object data){
return new Result(1,"success",data);
}
//失败响应
public static Result error(String msg){
return new Result(0,msg,null);
}
}
Controller:
@RestController
public class ResponseController {
//响应统一格式的结果
@RequestMapping("/hello")
public Result hello(){
System.out.println("Hello World ~");
//return new Result(1,"success","Hello World ~");
return Result.success("Hello World ~");
}
//响应统一格式的结果
@RequestMapping("/getAddr")
public Result getAddr(){
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
return Result.success(addr);
}
//响应统一格式的结果
@RequestMapping("/listAddr")
public Result listAddr(){
List<Address> list = new ArrayList<>();
Address addr = new Address();
addr.setProvince("广东");
addr.setCity("深圳");
Address addr2 = new Address();
addr2.setProvince("陕西");
addr2.setCity("西安");
list.add(addr);
list.add(addr2);
return Result.success(list);
}
}
分层解耦
尽可能让每一个接口、类、方法的职责更单一些(单一职责原
则)。
单一职责原则:一个类或一个方法,就只做一件事情,只管一块功能。
这样就可以让类、接口、方法的复杂度更低,可读性更强,扩展性更好,也更利用后期的维护。
可以分为三个部分:
-
数据访问:负责业务数据的维护操作,包括增、删、改、查等操作。
-
逻辑处理:负责业务逻辑处理的代码。
-
请求处理、响应数据:负责,接收页面的请求,给页面响应数据。
将代码分为三层
-
Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
-
Service:业务逻辑层。处理具体的业务逻辑。
-
Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的增、删、改、查。
流程
-
前端发起的请求,由Controller层接收(Controller响应数据给前端)
-
Controller层调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)
-
Serivce层调用Dao层(逻辑处理过程中需要用到的一些数据要从Dao层获取)
-
Dao层操作文件中的数据(Dao拿到的数据会返回给Service层)
实例
控制层:接收前端发送的请求,对请求进行处理,并响应数据
@RestController
public class EmpController {
//业务层对象
private EmpService empService = new EmpServiceA();
@RequestMapping("/listEmp")
public Result list(){
//1. 调用service层, 获取数据
List<Emp> empList = empService.listEmp();
//3. 响应数据
return Result.success(empList);
}
}
业务逻辑层:处理具体的业务逻辑
业务接口
//业务逻辑接口(制定业务标准)
public interface EmpService {
//获取员工列表
public List<Emp> listEmp();
}
业务实现类
//业务逻辑实现类(按照业务标准实现)
public class EmpServiceA implements EmpService {
//dao层对象
private EmpDao empDao = new EmpDaoA();
@Override
public List<Emp> listEmp() {
//1. 调用dao, 获取数据
List<Emp> empList = empDao.listEmp();
//2. 对数据进行转换处理 - gender, job
empList.stream().forEach(emp -> {
//处理 gender 1: 男, 2: 女
String gender = emp.getGender();
if("1".equals(gender)){
emp.setGender("男");
}else if("2".equals(gender)){
emp.setGender("女");
}
//处理job - 1: 讲师, 2: 班主任 , 3: 就业指导
String job = emp.getJob();
if("1".equals(job)){
emp.setJob("讲师");
}else if("2".equals(job)){
emp.setJob("班主任");
}else if("3".equals(job)){
emp.setJob("就业指导");
}
});
return empList;
}
}
数据访问层:负责数据的访问操作,包含数据的增、删、改、查
数据访问接口
//数据访问层接口(制定标准)
public interface EmpDao {
//获取员工列表数据
public List<Emp> listEmp();
}
数据访问实现类
//数据访问实现类
public class EmpDaoA implements EmpDao {
@Override
public List<Emp> listEmp() {
//1. 加载并解析emp.xml
String file =
this.getClass().getClassLoader().getResource("emp.xml").getFile();
System.out.println(file);
List<Emp> empList = XmlParserUtils.parse(file, Emp.class);
return empList;
}
}ob = emp.getJob();
.
软件设计原则:高内聚低耦合。
高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间
的联系程度越高,则内聚性越高,即 "高内聚"。
低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好
程序中高内聚的体现:
EmpServiceA类中只编写了和员工相关的逻辑处理代码
程序中耦合代码的体现:
把业务类变为EmpServiceB时,需要修改controller层中的代码
.
高内聚、低耦合的目的是使程序模块的可重用性、移植性大大增强
控制反转和依赖注入
不能new,就意味着没有业务层对象(程序运行就报错),怎么办呢?
我们的解决思路是:
-
提供一个容器,容器中存储一些对象(例:EmpService对象)
-
controller程序从容器中获取EmpService类型的对象
.
- 控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转
对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器
- 依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
程序运行时需要某个资源,此时容器就为其提供这个资源。
例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象
IOC容器中创建、管理的对象,称之为:bean对象
案例
具体将new修改为bean对象操作看day5-52页
@Component
Service层及Dao层的实现类,交给IOC容器管理
使用Spring提供的注解:@Component ,就可以实现类交给IOC容器管理
Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了
@Component的衍生注解:
@Controller (标注在控制层类上)
@Service (标注在业务层类上)
@Repository (标注在数据访问层类上)
在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。如果没有指定,默认为类名首字母小写。
使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。
.
使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描
@ComponentScan注解虽然没有显式配置,但是实际上已经包含在了引导类声明注解
@SpringBootApplication 中, 默认扫描的范围是SpringBoot启动类所在包及其子包
解决方案:手动添加@ComponentScan注解,指定要扫描的包 ( 仅做了解,不推荐 )
.
@Autowired
使用Spring提供的注解:@Autowired ,就可以实现程序运行时IOC容器自动注入需要的依赖对象
Autowired翻译过来叫:自动装配。
.
那如果在IOC容器中,存在多个相同类型的bean对象,程序运行会报错
解决上述问题呢?Spring提供了以下几种解决方案:
-
@Primary(默认实现)
-
@Qualifier(指定名称)
-
@Resource(指定名称)
使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
@Qualifier注解:指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。
@Qualifier注解不能单独使用,必须配合@Autowired使用
@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
面试题 : @Autowird 与 @Resource的区别
@Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired 默认是按照类型注入,而@Resource是按照名称注入
SQL语句根据其功能被分为四大类:DDL、DML、DQL、DCL
DDL:数据定义语言,用来定义数据库对象(数据库,表,字
段)
DML:数据操作语言,用来对数据库表中的数据进行增删改
DQL:数据查询语言,用来查询数据库中表的记录
DCL:数据控制语言,用来创建数据库用户、控制数据库的
访问权限
sql
数据库操作
创建数据库
create database [ if not exists ] 数据库名;
删除数据库
drop database [ if exists ] 数据库名 ;
创建表
create table 表名(
字段1 字段1类型 [约束] [comment 字段1注释 ],
字段2 字段2类型 [约束] [comment 字段2注释 ],
......
字段n 字段n类型 [约束] [comment 字段n注释 ]
) [ comment 表注释 ] ;
约束 | 描述 | 关键字 |
---|---|---|
非空约束 | 限制该字段值不能为null | not null |
唯一约束 | 保证字段的所有数据都是唯一、不重复的 | unique |
主键约束 | 主键是一行数据的唯一标识,要求非空且唯一 | primary key |
默认约束 | 保存数据时,如果未指定该字段值,则采用默认值 | default |
外键约束 | 让两张表的数据建立连接,保证数据的一致性和完整性 | foreign key |
在上述的表结构中:
id 是一行数据的唯一标识
username 用户名字段是非空且唯一的
name 姓名字段是不允许存储空值的
gender 性别字段是有默认值,默认为男
create table tb_user (
id int primary key comment 'ID,唯一标识',
username varchar(20) not null unique comment '用户名',
name varchar(10) not null comment '姓名',
age int comment '年龄',
gender char(1) default '男' comment '性别'
) comment '用户表';
主键自增:auto_increment
每次插入新的行记录时,数据库自动生成id字段(主键)下的值
具有auto_increment的数据列是一个正数序列开始增长(从1开始自增)
.
数据类型
很多大整数值
SMALLINT
BIGINT
TINYINT
类型 | 大小 | 有符(SIGNED)范围 | 无符号(UNSIGNED)范围 | 描述 |
---|---|---|---|---|
数值类型 | ||||
INT/INTEGER | 4bytes | (-2147483648,2147483647) | (0,4294967295) | 大整数值 |
FLOAT | 4bytes | (-3.402823466 E+383.402823466351 E+38) | 0 和 (1.175494351 E- 38,3.402823466 E+38) | 单精度浮 |
点数 | ||||
值 | ||||
DOUBLE | 8bytes | 双精度浮 | ||
点数 | ||||
值 | ||||
字符串类型 | ||||
VARCHAR | 0-65535 bytes | 变长字符串(需要指定长度) | ||
CHAR | 0-255 bytes | 定长字符串(需要指定长度) | ||
TEXT | 0-65 535 bytes | 长文本数据 | ||
日期时间类型 | ||||
DATE | YYYY-MM-DD | 日期值 |
char 与 varchar 都可以描述字符串,char是定长字符串,指定长度多长,就占用多少个字符,和字段值的长度无关 。而varchar是变长字符串,指定的长度为最大占用长度 。相对来说,char的性能会更高些。
示例:
年龄字段 ---不会出现负数, 而且人的年龄不会太大
age tinyint unsigned
分数 ---总分100分, 最多出现一位小数
score double(4,1)
生日字段 birthday ---生日只需要年月日
birthday date
创建时间 createtime --- 需要精确到时分秒
createtime datetime
添加字段
添加字段
alter table 表名 add 字段名 类型(长度) [comment 注释] [约束];
修改数据类型
alter table 表名 modify 字段名 新数据类型(长度);
alter table 表名 change 旧字段名 新字段名 类型(长度) [comment 注释][约束];
删除字段
alter table 表名 drop 字段名;
删除表语法:
drop table [ if exists ] 表名;
sql操作
insert语法:
向指定字段添加数据
insert into 表名 (字段名1, 字段名2) values (值1, 值2);
批量添加数据(指定字段)
insert into 表名 (字段名1, 字段名2) values (值1, 值2), (值1, 值2);
全部字段添加数据
insert into 表名 values (值1, 值2, ...);
批量添加数据(全部字段)
insert into 表名 values (值1, 值2, ...), (值1, 值2, ...);
update语法:
update 表名 set 字段名1 = 值1 , 字段名2 = 值2 , .... [where 条件] ;
update tb_emp set name='张三',update_time=now() where id=1;
delete语法:
delete from 表名 [where 条件] ;
delete from tb_emp where id = 1;
注意事项:
• DELETE 语句的条件可以有,也可以没有,如果没有条件,则会删除整张表的所有数据。
• DELETE 语句不能删除某一个字段的值(可以使用UPDATE,将该字段值置为NULL即可)。
• 当进行删除全部数据操作时,会提示询问是否确认删除所有数据,直接点击Execute即可。