SpringBoot
一、基础篇
1.1 入手项目
注意:如果这里SpringBoot1Application(启动程序)是灰色的,你右键点击pom.xml把它作为Maven项目就可以启动
BookController类中的代码,启动后访问路径是http://localhost:8080/book就可以看到有显示了
package com.itheima.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/book")
public class BookController {
@GetMapping
public String getById(){
System.out.println("hello,springboot");
return "springzBoot run";
}
}
小技巧隐藏文件夹
1.2 springboot模块了解
- 入门案例解析—查看pom.xml
- 开发SpringBoot程序要继承spring-boot-starter-parent
- spring-boot-starter-parent中定义了若干个依赖管理
- 继承parent模块可以避免多个依赖使用相同技术时出现依赖版本冲突
- 继承parent的形式也可以采用引入依赖的形式实现效果
<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>
- starter
1.开发SpringBoot程序需要导入坐标时通常导入对应的starter
2.每个不同的starter根据功能不同,通常包含多个依赖坐标
3.使用starter可以实现快速配置的效果,达到简化配置的目的
◆SpringBoot中常见项目名称,定义了当前项目使用的所有依赖坐标,以达到减少依赖配置的目的
●parent
◆所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
◆spring-boot-starter-parent各版本间存在着诸多坐标版本不同
●
实际开发
◆使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供,除非SpringBoot未提供对应版本V
◆如发生坐标错误,再指定Version(要小心版本冲突)
<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>
- 启动方式
@SpringBootApplication
public class SpringBoot1Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot1Application.class, args);
}
}
SpringBoot的引导类是Boot工程的执行入口,运行main方法就可以启动项目
·SpringBoot工程运行后初始化Spring容器,扫描引导类所在包加载bean
- springboot的辅助功能
l.内嵌Tomcat服务器是SpringBoot辅助功能之一
2.内嵌Tomcat工作原理是将Tomcat服务器作为对象运行,并
将该对象交给Spring容器管理
3.变更内嵌服务器思想是去除现有服务器,添加全新的服务器
去除Tomcat依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
导入新的服务器----jetty
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
1.3 知识加油站REST风格
REST简介
REST(Representational State Transfer),表现形式状态转换
■传统风格资源描述形式
http://localhost/user/getById?id=1
http://localhost/user/saveUser
■REST风格描述形式
http://localhost/user/1
http://localhost/user
优点:
■隐藏资源的访问行为,无法通过地址得知对资源是何种操作
■书写简化
REST风格简介
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作,根据REST风格对资源进行访问称为RESTfu1
http://localhost/users | 查询全部用户信息GET(查询) |
---|---|
http://localhost/users/1 | 查询指定用户信息GET(查询) |
http://localhost/users | 添加用户信息 P0ST(新增/保存) |
http://localhost/users | 修改用户信息 PUT(修改/更新) |
http://localhost/users/1 | 删除用户信息 DELETE(删除) |
上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范
描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、accounts.…
接受参数的三种方式
@RequestBody @RequestParam @PathVariable
区别
■@RequestParam用于接收urI地址传参或表单传参
■@RequestBody用于接收json数据
■@PathVariable/用于接收路径参数,使用{参数名称)描述路径参数
应用
■后期开发中,发送请求参数超过1个时,以json格式为主,@RequestBody应用较广
■如果发送非json格式数据,选用@RequestParam接收请求参数
■采用RESTful:进行开发,当参数数量较少时,例如1个,可以采用@PathVariable接收请求路径变量,通常用于传递id值
@Controller
public class UserController {
@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String save(){
System.out.println("user save");
return "user save";
}
@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
System.out.println("user delete"+id);
return "user delete";
}
@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(User user){
System.out.println("user update"+user);
return "user update";
}
@RequestMapping(value = "/users/{id}" , method = RequestMethod.GET)
@ResponseBody
public String getById(Integer id){
System.out.println("user getById"+id);
return "user getById";
}
@RequestMapping(value = "/users" , method = RequestMethod.GET)
@ResponseBody
public String getAll(){
System.out.println("user getAll");
return "user getAll";
}
}
●名称:@RestController
●类型:类注解
·位置:基于SpringMVC的RESTful开发控制器类定义上方
·作用:设置当前控制器类为RESTful风格,等同于@Controller与@ResponseBody两个注解组合功能
·范例:
@RestController public class BookController{
}
简化上述代码
//@ResponseBody+@Controller=@RestController
@RestController
@RequestMapping("/users")
public class UserController {
// @RequestMapping(value = "/users",method = RequestMethod.POST)
@PostMapping
public String save(){
System.out.println("user save");
return "user save";
}
// @RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@DeleteMapping("/{id}")
public String delete(@PathVariable Integer id){
System.out.println("user delete"+id);
return "user delete";
}
// @RequestMapping(value = "/users",method = RequestMethod.PUT)
@PutMapping
public String update(User user){
System.out.println("user update"+user);
return "user update";
}
// @RequestMapping(value = "/users/{id}" , method = RequestMethod.GET)
@GetMapping("/{id}")
public String getById(Integer id){
System.out.println("user getById"+id);
return "user getById";
}
// @RequestMapping(value = "/users" , method = RequestMethod.GET)
@GetMapping
public String getAll(){
System.out.println("user getAll");
return "user getAll";
}
}
1.4 复制工程
- 在工作空间中复制对应工程,并修改工程名称
- 删除与Idea相关配置文件,仅保留src目录与pom.xml文件
- 修改pom.xml文件中的artifactId与新工程/模块名相同
- 删除name标签(可选)
- 保留备份工程供后期使用
1.5 修改配置文件
SpringBoot默认配置文件application.properties
注意:加入什么技术模块依赖,才能有什么配置。没有这个依赖就没有这项配置。
spring.application.name=SpringBoot1
# 服务器端口配置
server.port=8080
# 修改运行日志图标
spring.main.banner-mode=off
# 日志默认info,还有debug、error
logging.level.root = info
SpringBoot内置属性查询
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties
官方文档中参考文档第一项:Application Properties
- SpringBoot:提供了多种属性配置方式
application.properties
server.port=80
application.yml
server:
port:81
application.yaml
server:
port:82
优先级:application.properties>application.yml>application.yaml
常用:application.yml
不同配置文件中相同配置按照加载优先级相互覆盖,不同配
置文件中不同配置全部保留
1.6 yaml数据格式
yaml语法规则
- 大小写敏感
- 属性层级关系使用多行描述,每行结尾使用冒号结束
- 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
- 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
- #表示注释
- 核心规则:数据前面要加空格与冒号隔开
读取yaml单一属性数据
yaml中的数据
server:
port: 8080
like2: [game,music,sleep]
othor:
- name: zhangsan
age: 18
- name: lisi
age: 17
party: true
user:
name: itcast
age: 89
baseDir: c:/win10
tempDir: ${baseDir}/temp
tempDir2: "${baseDir}/temp \t2 \t4"
bookController类
@RestController
@RequestMapping("/book")
public class BookController {
@Value("${like2[1]}")
private String like2;
@Value("${tempDir}")
private String tempDir;
@Value("${tempDir2}")
private String tempDir2;
@Value("${othor[1].name}")
private String name;
@GetMapping
public String getById(){
System.out.println("hello,springboot");
System.out.println(like2);
System.out.println(name);
System.out.println(tempDir);
System.out.println(tempDir2);
return "springBoot run";
}
}
输出
yaml文件中数据获取
读取全部属性数据
- 使用Environment对象封装全部配置信息
- 使用@Autowired自动装配数据到Environment对象中
读取引用类型数据
- 使用@ConfigurationProperties注解绑定配置信息到封装类中
- 封装类需要定义为Spring管理的bean,否则无法进行属性注入
datasource:
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost/xzp
username: root
password: xzp
@Component
@ConfigurationProperties(prefix = "datasource")
public class MydataSource {
private String driver;
private String url;
private String username;
private String password;
@Override
public String toString() {
return "MydataSource{" +
"driver='" + driver + '\'' +
", url='" + url + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
1.7 整合第三方技术
1. Junit
@Repository
public class BookDaoImpl implements BookDao {
@Override
public void save() {
System.out.println("保存成功");
}
}
测试一下
@SpringBootTest
class SpringBoot03JunitApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
bookDao.save();
}
}
classes属性
- 测试类如果存在于引导类所在包或子包中无需指定引导类
- 测试类如果不存在于引导类所在的包或子包中需要通过classes属
性指定引导类
@SpringBootTest(classes = SpringBoot03JunitApplication.class)
//@ContextConfiguration(classes = SpringBoot03JunitApplication.class)
class SpringBoot03JunitApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
bookDao.save();
}
}
2 . Mybatis
1.勾选MyBatis技术,也就是导入MyBatis.对应的starter
2.数据库连接相关信息转换成配置
3.数据库SQL映射需要添加@Mapper被容器识别到
实体类
public class Book {
private Integer id;
private int stuNum;
private String stuName;
private String stuGender;
private int stuAge;
@Override
public String toString() {
return "Book{" +
"id=" + id +
", stuNum=" + stuNum +
", stuName='" + stuName + '\'' +
", stuGender='" + stuGender + '\'' +
", stuAge=" + stuAge +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getStuNum() {
return stuNum;
}
public void setStuNum(int stuNum) {
this.stuNum = stuNum;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuGender() {
return stuGender;
}
public void setStuGender(String stuGender) {
this.stuGender = stuGender;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
}
dao层
@Mapper
public interface BookDao {
@Select("select * from book where sid = #{id}")
public Book getById(Integer id);
}
测试
@SpringBootTest
class SpringBoot04MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.getById(3));
}
}
配置文件
# 应用名称
spring.application.name=SpringBoot_04_Mybatis
#下面这些内容是为了让MyBatis映射
#指定Mybatis的Mapper文件
mybatis.mapper-locations=classpath:mappers/*xml
#指定Mybatis的实体目录
mybatis.type-aliases-package=com.itheima.mybatis.entity
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址
spring.datasource.url=jdbc:mysql://localhost:3306/xzp?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=123456
3. MyBatisPlus
dao层修改
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
测试
@SpringBootTest
class SpringBoot05MybatisPlusApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void contextLoads() {
System.out.println(bookDao.selectById(1));
}
}
4.Druid
1.整合Druid需要导入Druid对应的starter
2.根据Druid提供的配置方式进行配置
3.整合第三方技术通用方式
导入对应的starter
根据提供的配置格式,配置非默认值对应的配置项
1.8 SSMP整合案例
案例效果演示
案例实现方案分析
实体类开发一使用Lombok快速制作实体类
Dao开发一整合MyBatisPlus,制作数据层测试类
Service开发一基于MyBatisPlusi进行增量开发,制作业务层测试类
Controller开发一基于Restful开发,使用PostMan测试接口功能
Controller开发一前后端开发协议制作
页面开发一基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
列表、新增、修改、删除、分页、查询
项目异常处理
按条件查询一页面功能调整、Controller修正功能、Service修正功能
SSMP案例制作流程解析
先开发基础CRUD功能,做一层测一层
调通页面,确认异步提交成功后,制作所有功能
添加分页功能与查询功能
引入Druid依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
修改配置文件为yml格式
server:
port: 80
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/xzp?serverTimezone=UTC
username: root
password: 123456
实体类开发
- Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发
- lombok版本由SpringBoot提供,无需指定版本
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
常用注解:@Data为当前实体类在编译期设置对应的get/set方法,toString.方法,hashCode方法,equals.方法等
表名
@TableName("student")
@Data
public class Student {
主键自增
@TableId(value = "stu_id", type = IdType.AUTO)
private Integer stuId;
属性
@TableField("stu_name")
private String stuName;
属性
@TableField("stu_sex")
private int stuSex;
属性
@TableField("stu_age")
private int stuAge;
属性
@TableField("class_id")
private String classId;
}
数据层开发
StudentMapper接口
package com.itheima.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.entity.Student;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}
增删改查测试
@SpringBootTest
class SpringBoot07SsmpApplicationTests {
@Autowired
private StudentMapper studentMapper;
@Test
void testGetById() {
System.out.println(studentMapper.selectById(1));
}
@Test
void testAdd() {
Student student = new Student();
student.setStuName("hhh");
student.setStuSex(2);
student.setStuAge(18);
student.setClassId("20软件1班");
studentMapper.insert(student);
}
@Test
void testDelete() {
studentMapper.deleteById(1);
}
@Test
void testUpdate() {
Student student = new Student();
student.setStuId(4);
student.setStuName("一拉");
student.setStuSex(2);
student.setStuAge(22);
student.setClassId("20软件1班");
studentMapper.updateById(student);
}
@Test
void testGetAll(){
System.out.println(studentMapper.selectList(null));
}
}
使用配置方式开启日志,设置日志输出方式为标准输出
#开启MyBatisPlus的日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
开启后控制台输出效果是列表形式出现
分页功能
- 使用IPage封装分页数据
- 分页操作依赖MyBatisPlus分页拦截器实现功能
- 借助MyBatisPlus日志查阅执行SQL语句
分页操作需要设定分页对象IPage
@Test
void testGetPage(){
IPage page = new Page(1,3);
studentMapper.selectPage(page,null);
}
IPage对象中封装了分页操作中的所有数据
数据
当前页码值
每页数据总量
最大页码值
数据总量
设置MyBatisPlus拦截器类
分页操作是在MyBatisPlus的常规操作基础上增强得到,内部是动态的拼写SQL语句,因此需要增强对应的功能,使用MyBatisPlus拦截器实现
@Configuration
public class MPconfig {
@Bean
public MybatisPlusInterceptor mpIntercepto() {
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加具体的拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
实现效果
条件查询
1.使用QueryWrapperi对象封装查询条件
2.推荐使用LambdaQueryWrapper对象
3.所有查询操作封装成方法调用
4.查询条件支持动态条件拼装
@Test
void testGetBy(){
QueryWrapper<Student> queryWrapper =new QueryWrapper<>();
queryWrapper.like("stu_name","一拉");
studentMapper.selectList(queryWrapper);
}
@Test
void testGetBy2(){
String name = "1";
LambdaQueryWrapper<Student> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//第一种 if (name != null) lambdaQueryWrapper.like(Student::getStuName,name);
lambdaQueryWrapper.like(name!=null,Student::getStuName,name);
//第二种 lambdaQueryWrapper.like(Strings.isNotEmpty(null),Student::getStuName,name);
studentMapper.selectList(lambdaQueryWrapper);
}
业务层开发
1.Service接口名称定义成业务名称,并与Dao接口名称进行区分
2.制作测试类测试Service功能是否有效
接口StudentSerivce
public interface StudentSerivce {
Boolean save(Student student);
Boolean delete(Integer id);
Boolean update(Student student);
Student GetById(Integer id);
List<Student> getAll();
IPage<Student> getPage(int currentPage , int pageSize);
}
实现类IStudentSerivceImpl
@Service
public class IStudentSerivceImpl implements StudentSerivce{
@Autowired
private StudentMapper studentMapper;
@Override
public Boolean save(Student student) {
return studentMapper.insert(student) > 0;
}
@Override
public Boolean delete(Integer id) {
return studentMapper.deleteById(id) > 0;
}
@Override
public Boolean update(Student student) {
return studentMapper.update(student , null) > 0;
}
@Override
public Student GetById(Integer id) {
return studentMapper.selectById(id);
}
@Override
public List<Student> getAll() {
return studentMapper.selectList(null);
}
@Override
public IPage<Student> getPage(int currentPage, int pageSize) {
IPage page = new Page(currentPage , pageSize);
return studentMapper.selectPage(page,null);
}
}
测试
@SpringBootTest
class SpringBoot07SsmpApplicationTests {
@Autowired
private StudentSerivce studentSerivce;
@Autowired
private StudentMapper studentMapper;
@Test
void testGetById() {
System.out.println(studentSerivce.GetById(1));
}
@Test
void testAdd() {
Student student = new Student();
student.setStuName("hhh");
student.setStuSex(2);
student.setStuAge(18);
student.setClassId(1);
studentSerivce.save(student);
}
@Test
void testDelete() {studentSerivce.delete(3);
}
@Test
void testUpdate() {
Student student = new Student();
student.setStuId(2);
student.setStuName("展鹏");
student.setStuSex(2);
student.setStuAge(22);
student.setClassId(1);
studentSerivce.update(student);
}
@Test
void testGetAll(){
System.out.println(studentSerivce.getAll());
}
@Test
void testGetPage(){
IPage<Student> page = studentSerivce.getPage(1,3);
System.out.println(page);
}
业务层由MyBatis提供的简写
1.使用通用接口(ISerivce)快速开发Service
2.使用通用实现类(ServiceImpl<M,T>)快速开发ServiceImpl
3.可以在通用接口基础上做功能重载或功能追加
4.注意重载时不要覆盖原始操作,避免原始提供的功能丢失
使用MyBatisPlus提供有业务层通用接口(ISerivce)与业务层通用实现类(ServiceImpl<M,T>)
在通用类基础上做功能重载或功能追加 注意重载时不要覆盖原始操作,避免原始提供的功能丢失
直接使用MyBatisPlust提供的泛型
public interface StudentSerivce extends IService<Student> {
}
public class IStudentSerivceImpl extends ServiceImpl<StudentMapper,Student> implements StudentSerivce{
}
表现层开发
1.基于Restfu1制作表现层接口
新增:POST
删除:DELETE
修改:PUT
查询:GET
2.接收参数
实体数据:@RequestBody
路径变量:@PathVariable
StudentController类
@RestController
@RequestMapping("/students")
public class StudentController {
@Autowired
private StudentSerivce studentSerivce;
@GetMapping
public List<Student> GetAll(){
return studentSerivce.list();
}
@PostMapping
public Boolean Save(@RequestBody Student student){
return studentSerivce.save(student);
}
@DeleteMapping("/{id}")
public Boolean Delete(@PathVariable Integer id){
return studentSerivce.removeById(id);
}
@PutMapping
public Boolean Update(@RequestBody Student student){
return studentSerivce.updateById(student);
}
@GetMapping("/{id}")
public Student GetById(@PathVariable Integer id){
return studentSerivce.getById(id);
}
@GetMapping("/{currentPage}/{pageSize}")
public Page<Student> GetPage(@PathVariable int currentPage, @PathVariable int pageSize ){
return (Page<Student>) studentSerivce.getPage(currentPage ,pageSize);
}
}
表现层数据一致性处理
1.设计统一的返回值结果类型便于前端开发读取数据
2.返回值结果类型可以根据需求自行设定,没有固定格式
3.返回值结果模型类用于后端与前端进行数据格式统一,也称为前后
端数据协议
设计一个类
@Data
public class jsonPattern {
private Boolean flag;
private Object data;
public jsonPattern(){}
public jsonPattern(Boolean flag){
this.flag = flag;
}
public jsonPattern(Boolean flag, Object data) {
this.flag = flag;
this.data = data;
}
}
StudentController2类改变
@RestController
@RequestMapping("/students")
public class StudentController2 {
@Autowired
private StudentSerivce studentSerivce;
@GetMapping
public jsonPattern GetAll(){
return new jsonPattern(null,studentSerivce.list());
}
@PostMapping
public jsonPattern Save(@RequestBody Student student){
return new jsonPattern(studentSerivce.save(student));
}
@DeleteMapping("/{id}")
public jsonPattern Delete(@PathVariable Integer id){
return new jsonPattern(studentSerivce.removeById(id));
}
@PutMapping
public jsonPattern Update(@RequestBody Student student){
return new jsonPattern(studentSerivce.updateById(student));
}
@GetMapping("/{id}")
public jsonPattern GetById(@PathVariable Integer id){
return new jsonPattern( null, studentSerivce.getById(id));
}
@GetMapping("/{currentPage}/{pageSize}")
public jsonPattern GetPage(@PathVariable int currentPage, @PathVariable int pageSize ){
return new jsonPattern(null,(Page<Student>) studentSerivce.getPage(currentPage ,pageSize));
}
}