文章目录
SpringMVC
Axios入门案例
Ajax
局部刷新,异步访问。
同步:浏览器发起请求到服务器时,如果服务器没有响应,用户则无法获取页面数据,处于等待状态.不可以做其它的操作.
异步:异步请求时,浏览器可以进行其它的操作.当ajax数据获取之后,信息在页面的局部刷新. (可以理解为多线程操作方式)
Ajax为什么可以异步: 中间有Ajax引擎.
回调函数: 服务器返回数据,通过回调函数通知用户.
常见Ajax API : jQuery/axios 让Ajax调用更简洁
SpringMVC
总结:
1.SpringMVC是Spring框架后续开发的web模块.主要负责与前端用户进行交互.
2.SpringMVC基于Servlet进行开发的框架,目的简化前后端的调用.
传统servlet的弊端(看看行了)
1.传统servlet 一个业务方法,需要编辑一个servlet。如果业务复杂就会导致servlet数量增多
2.servlet请求方式只能支持get和post请求
3.通过servlet获取参数的类型都是String类型,需要手动类型转换
4.如果编辑servlet需要编辑大量的web.xml文件
上述都是历史产物!后期SpringMVC将servlet进行了封装
框架之间的关系
常用的注解!!
@Controller // 将该类先交给SpringMVC进行管理,之后将SpringMVC整体框架交给Spring管理
@RequestMapping("/hello") //该路径必须与用户访问路径一致.如果路径不一致,则会报404异常
@ResponseBody //表示该方法的返回值都是JASON字符串,如果返回值为String类型,则原数据返回
小demo
SpringMVC-简单参数传递
需求说明
常识:通过浏览器地址栏只能发起get请求
Url1:http://localhost:8080/findUserByid?id=123
难点:动态接收请求和参数id
底层源码
SpirngMVC为了简化取值过程,可以直接添加参数。简化后:
结果:
知识点:
1.SpirngMVC为了简化取值过程,可以直接添加参数
2.SpirngMVC请求路径地址不能重复
3.如果遇到多个参数,则可以使用对象方式接收,对象属性必须添加get/set方法
SpringMVC如果发现参数名称与对象属性名称一致时则自动调用set方法完成赋值
User对象接收信息,set方法赋值
Json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。它是基于 JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于程序语言的文本格式,但是也使用了类C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。
根源: 网络传输协议http/https,本质传输的数据都是字符串/字节信息. 协议与系统无关. 所以采用JSON的方式将数据按照特定的顺序进行排列. JSON中的特殊的数据结构,可以很好的解析字符串.
小demo
注意:这边打印出来的值,是利用get方法打印出来的。getxx(),去掉get首字母小写当作key,方法返回值当作value
Json
{“id”: “100”,“name”:“tomcat”,“age”:18,“sex”:“男”}
[1,2,3,4,“张三”,“李四”]
[1,2,true,false,{“id”:100,“name”:“tomcat”},[{arrays: [[],[],[]]},5,6]]、
MVC参数接收
RestFul结构(难点)
传统get请求业务说明
需求:向后端服务器传递多个参数,
需求说明: 向后端服务器传递多个参数, name=tomcat, age=18,sex=男
URL地址: http://localhost:8080/getUser?name=tomcat&age=18&sex=男
该方法能否优化? 能否降低字节数量?
RestFul参数拼接
语法: 省略key,将value使用/的方式进行分隔.并且位置固定.
URL地址: http://localhost:8080/getUser/tomcat/18/男
先修改URL地址
RestFul参数接收
优化:
如果restFul的属性名称与对象的属性名称一致,则可以利用对象接收
RestFul请求路径的通用写法
例子:
- http://localhost:8080/getUserById?id=100
- http://localhost:8080/deleteUserById?id=100
- http://localhost:8080/updateUserById?id=100&name=tomcat
- http://localhost:8080/insertUser POST 提交
问题: 上述的操作 意图特别的明显. 对后期操作会带来不安全的风险.
优化: restFul风格的请求名称的要求,不能出现动词
http://localhost:8080/userById?id=100 类型: GET 查询业务逻辑
http://localhost:8080/userById?id=100 类型: Delete 删除业务逻辑
http://localhost:8080/userById?id=100&name=tomcat 类型: PUT 更新业务逻辑
http://localhost:8080/user 类型: POST 新增业务逻辑
请求类型的种类
常用4种:get/post/put/delete
注解总结
27. @PathVariable restful结构,接收参数的注解
28. @GetMapping(“”) 只能接收get请求类型
29. @DeleteMapping(“”)
30. @PostMapping(“”)
31. @PutMapping(“”)
32. @RestController 标识controller类 返回值为Jason
33. @Controller@ResponseBody结合体
34. @CrossOrigin //允许跨域访问
35. @Data //动态生成get/set/toString/equals/hashCode等方法
36. @Accessors(chain = true) //开启链式加载 重写set方法
37. @NoArgsConstructor //无参构造
38. @AllArgsConstructor //全参构造
39. @Mapper //将接口交给Spring容器管理 Map<userMapper,JDK代理对象>
40. @SpringBootTest 该注解的作用在进行代码测试时启动spring容器,之后动态的获取对象 注意包路径 主启动类的同包及子包中.
41. @Param mybatis中将参数封装为map集合
42. @Alias(“user”)mybatis定义别名
43. @MapperScan Mybatis中扫描指定包路径的接口 为其创建代理对象.
44. @Insert Mybatis 新增操作注解
45. @Update Mybatis 修改操作注解
46. @Delete Mybatis 删除操作注解
47. @Select Mybatis 查询操作注解
48. @Transactional//事务的注解
49.
前后端调用
demo
</head>
<body>
<!-- 1导入js文件 -->
<script src="js/axios.js"></script>
<!-- 2编辑js代码 -->
<script>
// url地址:http://localhost:8080/findUser
let url1="http://localhost:8080/axios/findUser";
//(url地址,参数)
axios.get(url1) //发起ajax请求
.then(function(promise){ //成功之后执行回调函数,promise是返回值对象
console.log(promise.data) //输出
})
// axios.get(url1);
// .then(res=>{
// })
</script>
<h1>学习Axios的ajax调用</h1>
</body>
package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
//@Controller
//@ResponseBody
@RestController //两个结合体
@CrossOrigin //允许跨域访问
@RequestMapping("/axios") //抽取公共部分
public class AxiosController {
@RequestMapping("/findUser")
public String findUser(){
return "查询用户成功";
}
}
前端网页:
axios用法
浏览器F12用法
Network,(console)
Axios-Get传参
参数拼接写法
多参数:axios.get(url2,{params:user1})
前端:
后端:
html结果:
network可以查看执行内容
restful传参
Axios-post请求
关于常见请求类型语法说明
- GET/DELETE 语法相同
- POST/PUT 语法相同
Axios-put
关于跨域说明
同源策略
要素1: 浏览器的访问地址
要素2: Ajax的请求的网址
策略说明: 如果上述的要素同时满足 协议://域名:端口号都相同的情况,则称之为满足同源策略.可以进行正确的调用. 也称之为 “同域访问”.
什么是跨域
违反了同源策略就叫跨域访问
考题
案例1:
浏览器地址: http://www.jd.com/xx/xx
ajax地址: https://www.jd.com/yy/yy 跨域: 协议不同
案例2:
浏览器地址: http://www.jd.com/xx/xx
ajax地址: http://www.jd.com/yy/yy 同域请求
案例3:
浏览器地址: http://www.jd.com:80/xx/xx
ajax地址: http://www.jd.com/yy/yy 同域请求!!!
案例4:
前提: 域名与IP对应
浏览器地址: http://www.jd.com/xx/xx
ajax地址: http://8.8.8.8/yy/yy 跨域请求! 域名不一致
案例5:
浏览器地址: https://www.jd.com/xx/xx
ajax地址: https://www.jd.com:443/yy/yy 同域请求 https的默认端口号 443
案例6:
浏览器地址: http://www.jd.com/xx/yy/xx
ajax地址: http://miaoshi.jd.com/yy/yy 跨域请求 域名不同
*@CrossOrigin注解说明
前端JS-回调地狱
说明: 如果Ajax嵌套的层级较多,则把这种结构称之为"回调地狱"
嵌套规则:
- 用户发起第一个Ajax请求.回调函数中的结果,要当做第二个ajax请求的参数.
- 用户第二个ajax回调函数的结果,要当做第三个Ajax请求的参数 以此类推!!!
回调地狱问题说明:
由于回调方法和请求的方法在2行,导致嵌套的结构没有办法优化.如果需要优化,则应该将Ajax的请求一行搞定. 例如
let result1 = axios.get(url1);
let result2 = axios.get(url2,result1)
let result3 = axios.get(url3,result2)
解决方法
<!-- 2.编辑JS代码 -->
<script>
/* let url1 = "http://localhost:8080/axios/findUser"
axios.get(url1)
.then(function(promise){
console.log(promise.data)
axios.get("url2",promise.data)
.then(promise2 => {
console.log(promise2.data);
axios.get("url3",promise2.data)
.then(promise3 => {
console.log(promise3.data)
//...嵌套十八层,比喻为回调地狱
})
})
}) */
/**
* 语法:
* 1.async 关键字修饰函数
* 2.await 关键字修改ajax请求
* 3.先定义函数.之后调用函数
* 语法说明: 解构赋值操作
*/
async function getUser(){
let url1 = "http://localhost:8080/axios/findUser"
let {data: result} = await axios.get(url1)
console.log(result)
//let promise= let promise = await axios.get(url1)
//console.log(promise.data)
//return promise
}
//调用函数
getUser()
/* async function getUser2(data){
let url2 = "http://localhost:8080/axios/findUser"
let promise = await axios.get(url2,data)
return promise
}
let result1 = getUser();
let result2 = getUser2(result1); */
</script>
<h1>学习Axios的ajax调用</h1>
</body>
1、Mybatis
Mybatis介绍
官网地址: https://mybatis.org/mybatis-3/zh/index.html
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
总结:
- MyBatis 是一款优秀的持久层框架 在内部封装了JDBC,简化了操作数据库的过程.
- 映射: 数据库中的表 与POJO中的类一一映射.
表中的字段与类中的属性一一映射
导入项目
1.编辑pom.xml文件
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--添加lombok的包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
2.将原src文件删除 后 copy一份新的
lombok插件安装
1.lombok介绍
说明: pojo对象中必须添加get/set/toString等常规方法,但是该方法写起来繁琐,但是又必须添加. 所以可以引入lombok插件动态生成上述的方法.
2.导入jar包
org.projectlombok
lombok
3 安装lombok插件
3.搜索安装: lombok的插件
编辑pojo
编辑Mapper接口
规则: 基于面向接口开发的规则,准备一个新的接口
Spring整合Mybatis的配置
说明: Mybatis原生代码的结构混乱,比较复杂.所以采用Spring整合mybatis的操作.,简化开发的步骤.
其中表示spring整合mybatis的步骤 其中的配置信息暂时 了解即可.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
调用流程:
1.编辑Mapper接口 编辑接口方法
2.映射文件与Mapper接口绑定 namespace
-->
<mapper namespace="com.jt.mapper.UserMapper">
<!--标识使用二级缓存!!!-->
<cache/>
<!--
1.id与接口的方法名称绑定
2. 回顾:JDBC->resultSet->遍历结果集->手动封装对象
3. resultType: mybatis自动的将结果集的数据封装为对象
如果返回值List集合,则自动封装为List,User充当其中的泛型对象
如果返回值User对象.则直接返回User对象
-->
<select id="findAll" resultType="com.jt.pojo.User">
select * from demo_user
</select>
<!--根据id查询用户数据
语法: 动态获取数据 #{属性名称}
#号效果: 有预编译的效果 防止Sql注入攻击问题
所以以后取值使用#号
-->
<select id="findUserById" resultType="com.jt.pojo.User">
select * from demo_user where id= #{id}
</select>
<!--
规则:
1.如果接口方法中,有int类型的返回值,则入库之后,mybatis自动回传数据
2.如果接口中传递的是POJO对象.则通过#{属性}取值
大小问题:
1.windows系统中程序运行不区分大小写.
2.Linux系统 严格区分大小写.
3.程序猿口头禅: 我在我本机上没问题呀!!!!
-->
<insert id="saveUser">
insert into demo_user(id,name,age,sex) values (null,#{name},#{age},#{sex})
</insert>
<update id="updateUser">
update demo_user set age=#{age}, sex=#{sex}
where name=#{name}
</update>
<delete id="deleteUser">
delete from demo_user where name=#{name}
</delete>
<!--
知识点1: 通过 #{参数名称/对象中的属性/Map中的key}
知识点2: xml文件中有些字符需要转义
> > < <
& &
-->
<select id="findUserByAge" resultType="com.jt.pojo.User">
select * from demo_user where age>#{minAge} and age < #{maxAge}
</select>
<select id="findUserByAge2" resultType="com.jt.pojo.User">
select * from demo_user where age>#{minAge} and age < #{maxAge}
</select>
<!--Sql标签作用: 抽取公共的部分,可以被其它的Sql引用-->
<sql id="findColumn">
select id,name,age,sex from demo_user
</sql>
<select id="findByLike" resultType="User">
<include refid="findColumn"/> where name like "%"#{key}"%"
</select>
<!--
需求: Integer[] ids 中的数据一个一个取出来.拼接Sql
知识点: mybatis中如何遍历数组
foreach标签用法:
1. collection:需要遍历的集合的类型
1.1 数组类型 关键字:array
1.2 list类型 关键字:list
1.3 map类型 关键字:Map中的key
2. open/close 循环开始和结束标签,一般自己写
3. item 遍历数据的变量名称
4. separator 参数之间的分隔符
-->
<select id="findInArray" resultType="User">
select * from demo_user where id in (
<foreach collection="list" item="id" separator=",">
#{id}
</foreach>
)
</select>
<!--参数传递是Map集合,所以关键字使用key-ids1 -->
<select id="findInMap" resultType="User">
select * from demo_user where id in (
<foreach collection="ids1" item="id" separator=",">
#{id}
</foreach>
,
<foreach collection="ids2" item="id" separator=",">
#{id}
</foreach>
)
</select>
</mapper>
Spring的测试类
package com.jt;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest //该注解的作用启动spring容器中,之后动态的获取对象
public class TestMybatis {
@Autowired //IDEA编译异常 不影响代码的执行
private UserMapper userMapper;
@Test
public void test01(){
System.out.println(userMapper.getClass());
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
}
MybatisTest2-查找
1.测试函数
2.接口中创建方法
3.xml文件中与接口中方法绑定 然后 写sql语句
Test3-入库
<!--
规则:
1.如果接口方法中,有int类型的返回值,则入库之后,mybatis自动回传数据
2.如果接口中传递的是POJO对象.则通过#{属性}取值
大小问题:
1.windows系统中程序运行不区分大小写.
2.Linux系统 严格区分大小写.
3.程序猿口头禅: 我在我本机上没问题呀!!!!
-->
<insert id="saveUser1">
insert into demo_user(id,age,name,sex) values(null,#{age},#{name},#{sex})
</insert>
@param多个参数
说明: 根据下列的代码,不能非常直观去了解业务. 能否优化该操作.
List<User> findUserByAge(Map<String, Object> map);
//如果参数是多值,则需要封装为单值Map
//@Param将参数封装为Map集合
下面就等于是一个map集合 put了两次
查询一样
Mbatis模糊查询写法
Mybatis属性优化
别名包用法
其中resultType中的属性com.jt.pojo.User 定义别名.简化其操作.
<select id="findByLike" resultType="com.jt.pojo.User">
select * from demo_user where name like "%"#{key}"%"
</select>
1。标识注解
2.使用
3.定义别名包 定义别名包之后,以后的数据只需要写类名即可,使用时会自动的拼接前缀
#3.配置Mybatis
mybatis:
#定义别名包
type-aliases-package: com.jt.pojo
sql标签
Mybatis中集合参数用法 array/list
Array类型的参数说明
说明: 一般业务逻辑可能会用到array进行数据的封装. 问题: xml映射文件中如何解析数组
格式如下: Integer[] ids = {1,3,4,5,6};
测试代码:
编辑mapper接口:
编辑mapper映射文件:
Mybatis中集合参数用法Map封装
测试代码
@Test public void findInMap(){ //准备2个集合,测试map集合封装 Integer[] ids1 = {1,3,4,5,6}; Integer[] ids2 = {1,3,4,5,6}; List<User> list = userMapper.findInMap(ids1,ids2); System.out.println(list); }
编辑Mapper接口
List findInMap(@Param(“ids1”) Integer[] ids1,
@Param(“ids2”) Integer[] ids2);
编辑Mapper映射文件
<select id="findInMap" resultType="User">
select * from demo_user where id in (
<foreach collection="ids1" item="id" separator=",">
#{id}
</foreach>
)
</select>
例题小结
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper SYSTEM "http://mybatis.org/dtd/mybatis-3-mapper.dtd" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN">
<!--调用流程:1.编辑Mapper接口 编辑接口方法 2.映射文件与Mapper接口绑定 namespace -->
-<mapper namespace="com.jt.mapper.UserMapper">
<!--标识使用二级缓存!!!-->
<cache/>
<!--1.id与接口的方法名称绑定 2. 回顾:JDBC->resultSet->遍历结果集->手动封装对象 3. resultType: mybatis自动的将结果集的数据封装为对象如果返回值List集合,则自动封装为List,User充当其中的泛型对象如果返回值User对象.则直接返回User对象 -->
<select resultType="com.jt.pojo.User" id="findAll">select * from demo_user </select>
<!--根据id查询用户数据语法: 动态获取数据 #{属性名称}#号效果: 有预编译的效果 防止Sql注入攻击问题所以以后取值使用#号 -->
<select resultType="com.jt.pojo.User" id="findUserById">select * from demo_user where id= #{id} </select>
<!--规则:1.如果接口方法中,有int类型的返回值,则入库之后,mybatis自动回传数据 2.如果接口中传递的是POJO对象.则通过#{属性}取值大小问题:1.windows系统中程序运行不区分大小写.2.Linux系统 严格区分大小写.3.程序猿口头禅: 我在我本机上没问题呀!!!! -->
<insert id="saveUser">insert into demo_user(id,name,age,sex) values (null,#{name},#{age},#{sex}) </insert>
<update id="updateUser">update demo_user set age=#{age}, sex=#{sex}where name=#{name} </update>
<delete id="deleteUser">delete from demo_user where name=#{name} </delete>
<!--知识点1: 通过 #{参数名称/对象中的属性/Map中的key} 知识点2: xml文件中有些字符需要转义 > > < <& & -->
<select resultType="com.jt.pojo.User" id="findUserByAge">select * from demo_user where age>#{minAge} and age < #{maxAge} </select>
<select resultType="com.jt.pojo.User" id="findUserByAge2">select * from demo_user where age>#{minAge} and age < #{maxAge} </select>
<!--Sql标签作用: 抽取公共的部分,可以被其它的Sql引用-->
<sql id="findColumn">select id,name,age,sex from demo_user </sql>
-<select resultType="User" id="findByLike">
<include refid="findColumn"/>
where name like "%"#{key}"%"
</select>
<!--需求: Integer[] ids 中的数据一个一个取出来.拼接Sql 知识点: mybatis中如何遍历数组 foreach标签用法:1. collection:需要遍历的集合的类型 1.1 数组类型 关键字:array1.2 list类型 关键字:list1.3 map类型 关键字:Map中的key2. open/close 循环开始和结束标签,一般自己写 3. item 遍历数据的变量名称 4. separator 参数之间的分隔符 -->
-<select resultType="User" id="findInArray">
select * from demo_user where id in (
<foreach separator="," item="id" collection="list">#{id} </foreach>
)
</select>
<!--参数传递是Map集合,所以关键字使用key-ids1 -->
-<select resultType="User" id="findInMap">
select * from demo_user where id in (
<foreach separator="," item="id" collection="ids1">#{id} </foreach>
,
<foreach separator="," item="id" collection="ids2">#{id} </foreach>
)
</select>
</mapper>
测试程序:
package com.jt;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootTest //该注解的作用启动spring容器中,之后动态的获取对象
public class TestMybatis {
@Autowired //IDEA编译异常 不影响代码的执行
private UserMapper userMapper;
@Test
public void test01(){
System.out.println(userMapper.getClass());
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
/**
* 业务需求: 根据ID查询数据
* 参数: id = 1
*/
@Test
public void test02(){
int id = 1;
User user = userMapper.findUserById(id);
System.out.println(user);
}
/**
* 实现用户入库操作
*/
@Test
public void saveUser(){
User user = new User();
user.setName("元旦快乐").setAge(2022).setSex("女");
//如果需要返回值 则int接收
int rows = userMapper.saveUser(user);
//如果不需要返回值 则void标识
//userMapper.saveUser(user);
System.out.println("入库成功:影响:"+rows+"行");
}
/**
* 3.修改操作 将name="元旦快乐" 改为age=17,sex=男
*/
@Test
public void updateUser(){
User user = new User();
user.setName("元旦快乐").setAge(17).setSex("男");
userMapper.updateUser(user);
System.out.println("修改操作成功!!!");
}
//注意事项: 暂时练习时接口方法的参数只写1个. 否则程序必然报错....
//4.删除操作 将name="元旦快乐"的数据删除
@Test
public void deleteUser(){
String name = "元旦快乐";
userMapper.deleteUser(name);
System.out.println("删除成功!!!");
}
/**
* 业务: 查询age> 18岁 and age <100的用户.
* 知识点:
* 1.mybatis的参数可以是基本类型或者字符串.
* 2.如果遇到多个参数,应该使用对象(POJO)进行封装.
* 3.如果通过pojo封装不方便.则使用功能最为强大的Map进行封装
* 4.Mybatis的接口方法中只允许传递单值
*/
@Test
public void testFindUserByAge(){
Map<String,Object> map = new HashMap<>();
map.put("minAge",18);
map.put("maxAge",100);
List<User> userList = userMapper.findUserByAge(map);
System.out.println(userList);
}
@Test
public void testFindUserByAge2(){
int minAge = 18;
int maxAge = 100;
List<User> userList = userMapper.findUserByAge2(minAge,maxAge);
System.out.println(userList);
}
/**
* 需求: 查询name中 包含"君"字的数据
* Sql: where name like "%君%"
*/
@Test
public void findByLike(){
String key = "君";
List<User> userList = userMapper.findByLike(key);
System.out.println(userList);
}
/**
* 业务说明: 集合参数的用法
* 需求: 查询id=1,3,4,5,6的数据
* Sql: where id in (1,3,4,5,6)
*/
@Test
public void findInArray(){
Integer[] ids1 = {1,3,4,5,6};
List<Integer> list = Arrays.asList(ids1);
List<User> userList = userMapper.findInArray(list);
System.out.println(userList);
}
@Test
public void findInMap(){
//准备2个集合,测试map集合封装
Integer[] ids1 = {1,3};
Integer[] ids2 = {4,5,6};
List<User> list = userMapper.findInMap(ids1,ids2);
System.out.println(list);
}
2、Mybatis-动态Sql
if-where标签
编辑测试类
/**
* 需求: 根据用户不为null的属性充当where条件
*/
@Test
public void testSqlWhere(){
User user = new User();
user.setAge(3000).setSex("男");
List<User> userList = userMapper.findSqlWhere(user);
System.out.println(userList);
}
编辑UserMapper2接口
编辑UserMapper2映射文件
<!--
问题说明: 前端数据传递时可能会有null数据.
如果数据为null则不能充当where条件
解决方案: 动态Sql实现
语法:
<if test="判断条件"> id = #{id}</if>
true: 则拼接标签内容
false: 则不拼接标签内容
<where>标签: 去除where后边多余的and/or
-->
<select id="findSqlWhere" resultType="User">
select * from demo_user
<where>
<if test="id != null"> id = #{id}</if>
<if test="name !=null">and name = #{name}</if>
<if test="age !=null"> and age = #{age}</if>
<if test="sex !=null"> and sex = #{sex}</if>
</where>
</select>
SET标签
/**
* 需求: 修改id=1 的数据 name="北极熊",age=4000 sex="男"
*/
@Test
public void testUpdateUser(){
User user = new User();
user.setId(1).setAge(5000);
userMapper.updateUser(user);
System.out.println("更新成功!!!");
}
<!--根据对象中不为null的属性 当做set条件
语法: set标签 去除多余1个,号
-->
<update id="updateUser">
update demo_user
<set>
<if test="name !=null">name=#{name},</if>
<if test="age !=null"> age=#{age},</if>
<if test="sex !=null"> sex=#{sex},</if>
</set>
where id = #{id}
</update>
if-else
测试类
/**
* 如果name有值,则根据name查询.
* 如果name没有值,则根据age查询.
* 如果name/age都没有值,则根据sex查询
*/
@Test
public void testChoose(){
User user = new User();
user.setSex("男");
List<User> userList = userMapper.findChoose(user);
System.out.println(userList);
}
接口映射文件
<!--
* 如果name有值,则根据name查询.
* 如果name没有值,则根据age查询.
* 如果name/age都没有值,则根据sex查询
语法类似: if->else-if->else
-->
<select id="findUserByName" resultType="User">
select name,sex,age,id from demo_user
<where>
<choose>
<when test="name != null"> name = #{name} </when>
<when test="age != null">age = #{age} </when>
<otherwise> sex = #{sex} </otherwise>
</choose>
</where>
</select>
ResultMap语法(常用)
解释:
resultType能接收参数是因为POJO对象中的属性与数据库中的字段一样。
如果出现不一样的情况,拿pojo对象接收就会出问题。
这个时候可以用resultMap来自己手动映射,把数据库中的字段跟pojo中对象的属性进行绑定
测试文件
映射文件
<!--
规则:
1.如果结果集字段名称与POJO属性的名称不一致
则mybatis无法自动完成映射.
2.Mybatis提供了一个属性resultMap(使用最多的).
支持用户手动映射.
-->
<select id="findAll" resultType="Dog">
select * from dog
</select>
<!--
属性说明: id="唯一标识,不能重复"
type="映射的POJO对象的类型"
简化说明: 如果字段名称与属性名称一致则可以省略
autoMapping="true" 开启自动映射
-->
<resultMap id="dogRM" type="Dog" autoMapping="true">
<!--1.标识主键-->
<id column="dog_id" property="dogId"/>
<!--2.映射结果集-->
<result column="dog_name" property="dogName"/>
<!--<result column="age" property="age"/>-->
</resultMap>
3.Mybatis关联查询
常见关联关系
核心: 从一头出发,看向另一头
一对一 : 一个用户/一个ID 老公/老婆 一个员工对应一个部门
一对多: 一个老师对应多个学生, 一个部门对应多个员工
多对一: 多对一本质还是一对一
多对多: 一个老师对应多个学生 一对多
一个学生对应多个老师 一对多 双向一对多
一对一查询
一个员工对应一个部门
<mapper namespace="com.jt.mapper.EmpMapper">
<!--
规则:
1.使用关联查询时,不能出现同名字段,否则映射报错
-->
<select id="findAll" resultMap="empRM">
select emp.* , dept.dept_name from emp,dept
where emp.dept_id = dept.dept_id
</select>
<!--
知识点:
1.autoMapping="true"
如果字段名称和属性名称一致,则自动映射
2.association 一对一对象
3.javaType 固定搭配 封装对象的类型
总结:Mybatis可以实现关联查询的数据封装.
可以为主对象封装数据/同时可以为引用封装数据
-->
<!-- 1.先改映射名称 2.在emp中封装dept对象-->
<resultMap id="empRM" type="Emp" autoMapping="true">
<id column="emp_id" property="empId"/>
<!-- 一对一映射 封装-->
<association property="dept" javaType="Dept" autoMapping="true">
<id column="dept_id" property="deptId"/>
</association>
</resultMap>
一对多查询
一个部门对应多个员工
Mybatis注解形式
//鸡肋: 1.大公司一般不用, 2.只适用于单表操作.多表操作必须写映射文件
// 注解和映射文件二选一
@Select("select * from dept")
List<Dept> selectAll();
@Insert("insert into dept values (null,#{deptName})")
void saveDept(Dept dept);
4.Mybatis缓存实现
Mybatis-一级缓存
说明: 在同一个SqlSession内,实现数据库的共享.
解释: 用户使用同一个SqlSession时,进行多次数据库的查询,由于一级缓存的存在.所以数据库只查询一次.
开关状态: 一级缓存Mybatis默认开启.无需配置.
同一个数据对象
Mybatis-二级缓存
说明: 由同一个SqlSessionFactory(类比:链接池)生产的SqlSession(类比:数据库链接),可以实现数据共享
解释说明: 由同一个SqlSessionFactory生产多个SqlSession(多线程).可以在多线程的条件下,可以实现数据共享.
默认开关: 二级缓存默认条件下是开启的. 但是需要指定哪里使用二级缓存
一个池中多个数据对象共享
@SpringBootTest
public class TestCache {
@Autowired
private DeptMapper deptMapper;
/*
* 测试:mybatis的一级缓存, SqlSession级别
* SpringBoot测试说明:
* SpringBoot中用户在使用userMapper接口时,用户每调用一次.
* SpringBoot就会新创建一个SqlSession.
* 如何解决多个SqlSession的问题?
* 解决方案:
* 利用@Transactional的事务的注解,将多个SqlSession控制为一个.
*/
@Test
@Transactional//事务的注解
public void testCache(){
List<Dept> all = deptMapper.findAll();
List<Dept> all1 = deptMapper.findAll();
List<Dept> all2 = deptMapper.findAll();
System.out.println(all);
System.out.println(all1);
System.out.println(all2);
}
/*
* 测试二级缓存
* 总结: 多线程条件下共享数据,要求数据必须序列化.
*/
@Test
public void testCach2e(){
//第一次查询数据库获取的list1的集合对象,该对象需要保存到缓存中,为了后续线程使用,该对象必须序列化
List<Dept> all = deptMapper.findAll();//线程A
//第二个线程查询数据.有二级缓存的存在.所以从缓存中获取数据.所以直接反序列化该对象获取结果.
List<Dept> all1 = deptMapper.findAll();//线程B
//第三个线程查询数据,所以直接反序列化该对象获取结果.
List<Dept> all2 = deptMapper.findAll();//线程C
}
}
关于对象序列化问题
说明: 在多线程条件下.数据如果需要共享,必须序列化
关于Mybatis一二级缓存的说明
- 默认条件下一二级缓存是开启的. 但是二级缓存需要标记 cache
2.一级缓存在同一个SqlSession中共享数据(单线程)
3.二级缓存在同一个SqlSessionFactory生产的多个SqlSession内共享数据(多线程). 对象必须序列化
4.在真实的生产环境中(集群:多个服务器)使用二级缓存可能存在问题,使用Redis高级缓存服务器代替.
5.Mybatis底层实现原理
class MybatisApplicationTests {
/*
* Mysql入门实现步骤:
* 1.编辑mybatis-config.xml核心配置文件
* 1.1执行数据源配置
* 2.编辑POJO实体对象.要求与数据库表中的字段一一对应
* 3.编辑Mapper接口. 添加接口方法
* 4.编辑接口的实现类(配置文件方式) 要求namespace id resultType
* 5.mybatis加载指定的mapper映射文件
* 6.创建SqlSessionFactory工厂对象
* 7.获取SqlSession,开启数据库链接
* 8.获取接口对象(代理对象)
* 9.调用接口方法,获取返回值结果
* 10.关闭sqlSession链接.
* */
@Test
public void testDemo1() throws IOException {
/*创建SqlSessionFactory 类比:链接池 */
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//设计模式1:建造者模式-Builder-.build()
//设计模式2:工厂模式-Factory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/*从SqlSessionFactory中获取sqlSession*/
SqlSession sqlSession = sqlSessionFactory.openSession();
/*SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();*/
/*获取mapper接口,执行接口方法*/
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
/*Mybatis为接口创建了一个代理对象
知识点: 框架中通过接口调用方法时,如果没有实现类,则为其创建代理对象
代理对象~实现类
*/
System.out.println(userMapper.getClass());
List<User> userList = userMapper.findAll();
System.out.println(userList);
/*执行之后关闭SqlSession*/
sqlSession.close();
}
}
SpringBoot框架介绍
SpringBoot框架介绍
理解: 传统框架在使用时,特别的繁琐 Spring/SpringMVC/Mybatis在使用时需要大量的配置文件. 使用SpringBoot可以简化传统框架的配置文件. 以注解的方式简化开发过程. SpringBoot可以理解为框架的框架(框架的工具API).
优势: “开箱即用” 拿来就用 简化配置的过程.
pom.xml文件说明
/project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--项目的坐标
1.标识当前的项目
2.坐标的位置就是jar包文件的位置
3.通过坐标可以被其它项目引用
-->
<groupId>com.example</groupId>
<artifactId>springboot_demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_demo1</name>
<description>springboot_demo1</description>
<!--2.指定pom.xml中的配置信息-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!--指定springboot的版本-->
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<!--3.当前项目依赖的其它jar包文件 -->
<dependencies>
<!--3.1 添加依赖信息,其中版本号是默认的无序手写-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--版本号 <version></version>-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--4.依赖的管理器
历史: 早期项目使用时,需要自己手动的添加依赖jar包文件.可能导致jar包文件不兼容/冲突
直接导致项目启动出问题. 该问题是开发中的常见诟病.
SpringBoot优势:
SpringBoot将市面上常见的jar包都进行了兼容.并且在内部进行了测试.并且
使用其它第三方框架的时候,只需要简单的配置.可以使用其功能. (开箱即用)
-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.jt.SpringbootDemo1Application</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
关于主启动类说明
启动说明
说明: 主启动类运行,真正起作用的是注解@SpringBootApplication
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
主启动类注解说明
@Target(ElementType.TYPE) //注解对谁有效
@Retention(RetentionPolicy.RUNTIME) //注解的声明周期
@Documented //文档支持
@Inherited //是否可以被继承
@SpringBootConfiguration //springboot的配置类
@EnableAutoConfiguration //启动自动化的配置,加载pom.xml文件中的启动项
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), //包扫描路径,默认条件下是主启动类的包路径. 所以以后写代码在主启动类的同包及子包中编辑.
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
关于YML文件的说明
# 数据结构 key-value
# 语法结构 key:(空格)value
# 注意层级缩进
# 默认字符集: utf-8编码格式 支持中文
server:
port: 8080
框架小练习
整合说明
1.SpringBoot 平台
2.Spring框架
3.SpringMVC框架
4.Mybatis框架
框架的搭建
1 导入jar包
pom.xml
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--添加lombok的包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
2 框架层级结构
3 控制层
package com.jt.controller;
import com.jt.pojo.User;
import com.jt.service.UserService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController //@controller + @ResponseBody
@CrossOrigin //跨域
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
// http://localhost:8080/user/findAll 查询全部用户信息
@GetMapping ("/findAll")
public List<User> findAll(){
return userService.findAll();
}
// http://localhost:8080/user/春节/2022/女 实现用户新增 返回新增成功
@RequestMapping("add/{name}/{age}/{sex}")
public String add(User user){
userService.update(user);
return "新增成功";
}
// http://localhost:8080/user/deleteUserById?id=1 删除指定Id的数据 返回删除成功
@RequestMapping("deleteUserById")
public String delete(int id){
userService.delete(id);
return "删除成功";
}
// http://localhost:8080/user/update/元宵节/2022/男/99 将指定ID进行修改操作 返回修改成功
@RequestMapping("update/{name}/{age}/{sex}/{id}")
public String update(User user){
userService.updateFestival(user);
return "修改成功";
}
//http://localhost:8080/user/findUserById?id=xx 查询id=xx的数据 返回User对象
@GetMapping("findById")
public User findById(int id){
User user = userService.findById(id);
return user;
}
//http://localhost:8090/user/findUserBylike?name=王 模糊查询 返回List集合
@GetMapping("findUserBylike")
public List<User> findByName(String name){
List<User> userList = userService.findByName(name);
return userList;
}
//http://localhost:8080/user/findUserByIn?ids=1,3,4,5,6 批量查询 返回List集合
@GetMapping("findByIds")
public List<User> findByIds(Integer[] ids){
List<User> userList = userService.findByIds(ids);
return userList;
}
//http://localhost:8080/user/findUserByAge?minAge=10&maxAge=100 查询数据 返回List集合
/*
多个参数,mapper层加@param,创建成map集合形式
*/
@GetMapping("findUserByAge")
public List<User> findByAge(int minAge,int maxAge){
List<User> userList = userService.findByAge(minAge,maxAge);
return userList;
}
}
4 service 层 (接口我省略了)
package com.jt.service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.findAll();
}
@Override
@Transactional
public void update(User user) {
userMapper.update(user);
}
@Override
@Transactional
public void delete(int id) {
userMapper.delete(id);
}
@Override
@Transactional
public void updateFestival(User user) {
userMapper.updateFestival(user);
}
@Override
public User findById(int id) {
User user = userMapper.findById(id);
return user;
}
@Override
public List<User> findByName(String name) {
List<User> userList = userMapper.findByName(name);
return userList;
}
@Override
public List<User> findByIds(Integer[] ids) {
List<User> userList = userMapper.findByIds(ids);
return userList;
}
@Override
public List<User> findByAge(int minAge, int maxAge) {
List<User> userList = userMapper.findByAge(minAge,maxAge);
return userList;
}
}
5 mapper层
package com.jt.mapper;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
@Mapper //将接口交给Spring容器管理 Map<userMapper,JDK代理对象>
//@Repository //将持久层交给Spring容器管理
public interface UserMapper {
//查询所有的用户信息
List<User> findAll();
void update(User user);
void delete(int id);
void updateFestival(User user);
User findById(int id);
List<User> findByName(String name);
List<User> findByIds(Integer[] ids);
//一个map集合 put两次
List<User> findByAge(@Param("minAge") int minAge,
@Param("maxAge") int maxAge);
}
6 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
调用流程:
1.编辑Mapper接口 编辑接口方法
2.映射文件与Mapper接口绑定 namespace
-->
<mapper namespace="com.jt.mapper.UserMapper">
<!--标识使用二级缓存!!!-->
<cache/>
<!--
1.id与接口的方法名称绑定
2. 回顾:JDBC->resultSet->遍历结果集->手动封装对象
3. resultType: mybatis自动的将结果集的数据封装为对象
如果返回值List集合,则自动封装为List,User充当其中的泛型对象
如果返回值User对象.则直接返回User对象
-->
<select id="findAll" resultType="User">
select * from demo_user
</select>
<update id="update" >
update demo_user set age=#{age},sex=#{sex},name=#{name}
where id = 1 ;
</update>
<delete id="delete">
delete from demo_user
where id=#{id}
</delete>
<update id="updateFestival">
update demo_user set name = #{name} ,age = #{age}, sex = #{sex}
where id = #{id}
</update>
//
<select id="findByIds" resultType="User">
select id,name,age,sex from demo_user where id in(
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</select>
<select id="findByAge" resultType="User">
select * from demo_user where
age > #{minAge} and age < #{maxAge}
</select>
estival(User user);
User findById(int id);
List<User> findByName(String name);
List<User> findByIds(Integer[] ids);
//一个map集合 put两次
List<User> findByAge(@Param("minAge") int minAge,
@Param("maxAge") int maxAge);
}
### 6 映射文件
```java
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
调用流程:
1.编辑Mapper接口 编辑接口方法
2.映射文件与Mapper接口绑定 namespace
-->
<mapper namespace="com.jt.mapper.UserMapper">
<!--标识使用二级缓存!!!-->
<cache/>
<!--
1.id与接口的方法名称绑定
2. 回顾:JDBC->resultSet->遍历结果集->手动封装对象
3. resultType: mybatis自动的将结果集的数据封装为对象
如果返回值List集合,则自动封装为List,User充当其中的泛型对象
如果返回值User对象.则直接返回User对象
-->
<select id="findAll" resultType="User">
select * from demo_user
</select>
<update id="update" >
update demo_user set age=#{age},sex=#{sex},name=#{name}
where id = 1 ;
</update>
<delete id="delete">
delete from demo_user
where id=#{id}
</delete>
<update id="updateFestival">
update demo_user set name = #{name} ,age = #{age}, sex = #{sex}
where id = #{id}
</update>
//
<select id="findByIds" resultType="User">
select id,name,age,sex from demo_user where id in(
<foreach collection="array" item="id" separator=",">
#{id}
</foreach>
)
</select>
<select id="findByAge" resultType="User">
select * from demo_user where
age > #{minAge} and age < #{maxAge}
</select>
7.图片上传demo
- 业务思路:
- 1.校验图片的类型 jpg|png|gif (正则表达式)
- 2.校验是否为恶意程序 木马.exe.jpg
- 3.将图片进行分目录存储 hash方式存储|时间格式存储
- 4.防止图片重名,使用UUID.
正则表达式
- 匹配次数
- 匹配固定次
- 单个字符
- 区间字符
- 分组取值
图片demo
package com.jt.service;
import com.jt.vo.ImageVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService {
//定义根目录, Windows采用此 目录 Linux系统需要更换目录
private String preFilename = "E:/Workspace/JTImage";
private String preURLPath = "http://image.jt.com";//网络地址前缀
/*
* 业务思路:
* 1.校验图片的类型 jpg|png|gif
* 2.校验是否为恶意程序 木马.exe.jpg
* 3.将图片进行分目录存储 hash方式存储|时间格式存储
* 4.防止图片重名,使用UUID.
* @param file
* @return
*/
@Override
public ImageVO upload(MultipartFile file) throws IOException {
//1.读取文件 filename= abc.jpg
//文件名称大小写问题
// abc.exe.jpg
String filename = file.getOriginalFilename().toLowerCase();
if(!(filename.matches("^.+\\.(jpg||png||gif)$"))){
return null;//不匹配 不是照片格式 加入失败
}
//2.校验是否为恶意程序 abc.exe.jpg 读取图片的长宽
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
if (height == 0 || width == 0){
return null;
}
//3: 分目录存储 提高检索的效率 按照时间将目录划分 /yyyy/MM/dd/
//先获取日期路径
String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//"E:/Workspace/JTImage/yyyy/MM/dd/"
String fileDir = preFilename + datePath;
//上面就得到了目录所在的文件夹
File dirFile = new File(fileDir);
if (!dirFile.exists()){
dirFile.mkdirs();
}
//4.防止文件重名 uuid.jpg
String uuid = UUID.randomUUID().toString().replace("-", "");
//得到 .jpg
String fileType = filename.substring(filename.lastIndexOf("."));
filename = uuid + fileType;
//5.实现文件上传
//"E:/Workspace/JTImage/yyyy/MM/dd/uuid.jpg"
String filePath = fileDir + filename;
file.transferTo(new File(filePath));
//6.封装 imageVo返还数据
//2022/03/7/uuid.jpg
String virtualPath = datePath + filename;
System.out.println(virtualPath);
//"http://image.jt.com/2022/03/7/uuid.jpg"
String urlPath =preURLPath + virtualPath;
return new ImageVO(virtualPath,urlPath,filename);
//
}
@Override
public void deleteImage(ImageVO imageVO) {
String virtualPath = imageVO.getVirtualPath();
String path = preFilename + virtualPath ;
File file = new File(path);
if (file.exists()) {
file.delete();
}
}
}
/*
String filename = file.getOriginalFilename().toLowerCase();
//.+代表名字至少有一个字符
if (!(filename.matches("^.+\\.(jpg|pbg|gif)$"))){
return null;
}
//2.校验是否为图片
try {
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
int height = bufferedImage.getHeight();
int width = bufferedImage.getWidth();
//不是图片
if (height == 0 || width == 0){
return null;
}
} catch (IOException e) {
return null;
}
//3: 分目录存储 提高检索的效率 按照时间将目录划分 /yyyy/MM/dd/
String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
//E:/Workspace/JTImage/yyyy/MM/dd
String fileDir = preFilename + datePath;
File dirFile = new File(fileDir);
if (!dirFile.exists()){
dirFile.mkdirs();
}
//4.防止文件重名
String uuid = UUID.randomUUID().toString().replace("-", "");
int index = filename.lastIndexOf(".");
//获取 .jpg / png /gif
String fileType = filename.substring(index);
//新文件名称
filename = uuid+fileType;
//5.实现文件上传
String filePath = fileDir + filename;
file.transferTo(new File(filePath));
//6.封装 ImageVo 返回数据
//(E:/Workspace/JTImage)/yyyy/MM/dd/uuid.jpg
String virtualPath = datePath + filename;
//7.封装网络地址 "http://image.jt.com/yyyy/MM/dd/uuid.jpg"
String url = preURLPath + virtualPath;
System.out.println(url);
return new ImageVO(virtualPath,url,filename);
*/