[Java]SpringBoot快速入门

快速入门

使用SpringBoot开发一个web应用, 浏览器发起请求后,给浏览器返回字符串"Hello World"

1.创建工程

专业版

专业版IDEA自带插件, 可以快速创建项目

社区版

社区版IEDA需要自己安装插件, 才能创建项目, 并且IDEA版本不高于2022

第三方网站

速度较快,官网打不开时备选 https://start.aliyun.com/

官网网站

官方网站可能比较慢,但是比较推荐 https://start.spring.io/

2.目录解析

简化代码

代码结构

1.启动类: SpringHelloWoreldApplication.java

2.配置文件:

3.依赖文件:

// 继承父工程
<parent>
  <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>3.2.2</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

// 项目信息
<groupId>com.itheima</groupId>
<artifactId>Day02_springboot_hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Day02_springboot_hello</name>
<description>Day02_springboot_hello</description>

// JDK版本 
<properties>
    <java.version>17</java.version>
</properties>

// 项目依赖
<dependencies>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
      </dependency>
</dependencies>

// 项目插件
<build>
  <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
  </plugins>
</build>

4.源代码文件:

3.入门程序

创建请求处理类

启动类所在包下, 添加controller包和类, 连包带类一次创建

编写代码

// 定义请求处理类
@RestController
public class hellocontroller {
    // 定义请求处理方法
    @RequestMapping("/hello")
    public String hello(){
        System.out.println("hello world~");
        return "hello world~";
    }
}}

测试运行

  1. 执行启动类的main方法
  2. 程序默认运行在8080端口

Http协议

超文本传输协议, 规定了浏览器和服务器之间数据传输的规则

特点

  1. 基于TCP协议, 面相连接,安全可靠
  2. 基于请求-响应模型, 一次请求对应一次响应
  3. HTTP协议是无状态的协议, 对于事务处理没有记忆能力, 每次请求响应都是独立的
  • 缺点: 多次请求间不能共享数据
  • 优点: 速度快

请求协议

规定了浏览器向服务器发送请求的格式

请求行: 请求数据的第一行, 包含 请求方式, 资源路径, 协议等信息

请求头: 第二行开始, 以 key: value 的格式携带客户端信息信息

请求空行: 用来分隔请求头和请求体

请求体: 存放请求的参数, 只有POST请求有请求体

请求头详解

GET和POST

  1. GET请求的参数放在请求行中, 没有请求体
  2. GET请求携带的参数是有大小限制的
  3. POST请求的参数放在请求体中
  4. POST请求大小是没有限制的

响应协议

规定了服务器向浏览器发送请求和格式

响应行: 响应数据的第一行, 包含协议, 状态码, 描述等信息

响应头: 从第二行开始, 以 key: value 的格式, 描述响应信息

响应空行: 分隔响应头和响应体

响应体: 存放响应的数据

响应码

状态码大全: 状态 | Status - HTTP 中文开发手册 - 开发者手册 - 腾讯云开发者社区-腾讯云

响应头

协议解析

浏览器自带HTTP解析程序, 可以自动封装请求, 解析响应

服务器也需要HTTP解析程序, 解析请求报文, 封装响应报文

web服务器原理:

  1. 通过ServerSocket接受HTTP请求,
  2. 通过输入流获取请求报文
  3. 根据请求协议解析请求报文
  4. 根据响应协议封装响应报文,
  5. 通过输出流给浏览器响应数据

常见的web服务器:

web服务器

web服务器是一个软件程序, 对HTTP协议的操作进行封装, 使得程序员不用直接对协议进行操作,让Web开发更加便捷, 主要就是用于部署项目, 对外提供网上信息浏览服务

基本使用

入门程序解析

Tomcat

Apache软件基金会开源的免费的轻量级的Web服务器

  1. 官网: Apache Tomcat® - Welcome!
  2. Tomcat也被称为web容器, servlet容器
  3. servlet程序需要依赖Tomcart才能运行
  4. 轻量级: 支持Server/JSP等少量的javaEE规范
  5. javaEE指java企业版
  6. javaEE规范就是企业级开发的技术规范总和
  7. javaEE规范总共13项, 包括 JDBC, JNDI, EJB, RMI, JSP, Servlet, XML, JMS, Java IDL, JTA, JavaMail, JAF, 其中有些规范已经过时

基本使用

下载

官网下载, 或者使用资料中的软件包

安装

绿色版软件, 直接解压皆可

卸载

删除软件文件即可

目录结构

启动

双击 bin/startup.bat 启动程序

关闭

  1. 点击 x 号强制关闭
  2. 双击 bin/shutdown.bat 正常关闭
  3. Ctrl+C 正常关闭

部署

把项目复制到webapps目录, 部署完成, 访问localhost:8080/dome/index.html

排错

  1. 启动窗口一闪而过: 检查JAVA_HOME环境变量是否正确配置
  1. 控制台中文乱码: 修改conf/logging.properties 文件中的编码格式 (第51行)

  1. 端口冲突: 配置Tomcat运行端口, conf/server.xml

  • HTTP协议默认端口号为80, 如果将Tomcat端口改为80, 则将来访问Tomcat时, 将不用输入端口号
  • 说明: springboot工程会内嵌Tomcat

SpingBoot程序解析

起步依赖

我们创建Spingbott项目,勾选web开发依赖, 实际就是引入官方的起步依赖

  1. spring-boot-web: 包含了web应用开发所需要的常见依赖
  2. spring-boot-test: 包含了单元测试所需要的常见依赖
  3. 官方提供的起步依赖, 聚合了web开发中常用的依赖, 只需要引入这个依赖, 就可以愉快的进行开发了
  4. 起步依赖并不需要指定版本, 因为起步依赖会继承, 因为所有的spingboot工程都要基础springboot父工程, 父工程会统一管理起步依赖的版本

内嵌Tomcat

基于SpringBoot创建的web应用程序, 内置了Tomcat服务器, 当启动类运行时, 会自动启动Tomcat服务器

请求响应

流程

概念: 浏览器.服务器架构模式,

执行过程

  1. 当通过启动类启动springboot程序时, 内置的tomcat服务器随之启动
  2. tomcat服务器的核心就是前端控制器
  • 前端控制器提供了DispatcherServlet程序,
  • 程序中的HttpServletRequest对象(请求对象)用来解析浏览器的请求,
  • 浏览器的请求经过解析后会传给Controller控制器
  • 在Controller中通过请求对象就可以拿到前端的请求数据
  • 程序中的HttpServletResponse对象(响应对象)用来封装响应给浏览器的数据,
  • Controller中的数据经过响应对象的封装响应给浏览器
  1. 有了前端控制器程序帮助我们和浏览器通信,
  • 程序员就不必关心Http协议的解析和封装
  • 而是专注于Controller控制器的业务开发
  • 极大提高了我们的工作效率

重点说明

  1. 请求对象(HttpServletRequest): 获取请求数据
  2. 响应对象(HttpServletResponse): 设置响应数据
  3. BS架构: Browser/Server架构即 浏览器.服务器架构模式
  4. 客户端只需要浏览器, 应用程序的逻辑和数据都存在服务端口
  5. CS架构: Client/Server架构即 客户端/服务器架构模式
  6. 客户端根据不同设备下载使用, 客户端拥有更强的数据和处理处理能力

postman

当前项目主流的开发方式是前后端分类模式, 前后端基于接口文档进行协作开发, 后端要保证接口的可用, 就需要进行接口测试

postman就是专门用于接口测试的工具, 起初是Chrome插件, 发展成网页调试与发送HTTP请求的工具

其他工具:

基本使用

  1. 官网: Postman 下载及安装教程
  2. 下载: 官网下载或者使用提供好的安装包
  3. 安装: 傻瓜式安装
  4. 登录注册: 第一次使用先注册再登录
  5. 使用:

请求

目标: 获取各种请求参数

1.简单参数

1.1原始方式

在原始的web程序中, 获得请求参数, 需要通过HttpServletRequest对象手动获取

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/simpleParam")
     public String simpleParam(HttpServletRequest request) {
        // 获取请求参数
        String nameStr = request.getParameter("name");
        String ageStr = request.getParameter("age");

        int age = Integer.parselInt(ageStr);
        System.out.println("name:" + name);
        System.out.println("age:" + age);

        return "ok";
    }
}
  1. 通过请求处理对象HttpServletRequest获取前端数据比较繁琐
  2. 而且拿到的都是字符串数据, 还需要手动类型转换
1.2 SpringBoot
a.定义同名形参

参数名称与形参变量名相同, 定义形参即可接收参数

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/simpleParam")
    public String simpleParam(String name, Integer age) {
     // 获取请求参数
        System.out.println("name:" + name);
        System.out.println("age:" + age);
        return "ok";
    }
}
b.修改形参映射

如果方法形参名称与请求参数名称不匹配, 可以使用@RequestParam完成映射

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/simpleParam")
    public String simpleParam(@RequestParam(name="username", required=false) String name, Integer age) {
       // 获取请求参数
        System.out.println("name:" + name);
        System.out.println("age:" + age);
        return "ok";
    }
}
  1. username是前端传递的参数名, name是后端接收的参数名
  2. @RequestParam中的erquired属性默认为true, 表示参数必传,
  3. 如果参数是可选的, 设置为false即可

2.实体参数

2.1简单实体对象

规则: 请求参数名与形参对象属性名相同, 即可直接通过POJO接收

实体类

public class User 
    public String name;
    public String age;

    //生成get/set方法
    //重写toString()方法 
}

方法

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/simplePojo")
    public String simpleParam(User user) {
        // 获取请求参数
        System.out.println(user);
        return "ok";
   }
}

传参

2.2复杂实体对象

规则: 请求参数名与形参对象属性名相同, 按照对象层次结构关系即可接收嵌套POJO属性参数

实体类

public class User {
    public String name;
    public String age;
    public Address address;
    //生成get/set方法
    //重写toString()方法 
}
 public class Address {
    public String province;
    public String city;
    //生成get/set方法
    //重写toString()方法 
}

方法

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/simplePojo")
    public String simpleParam(User user) {
       // 获取请求参数
       System.out.println(user);
       return "ok";
    } 
}

传参

3.数组集合参数

3.1数组

规则: 请求参数名称与形参中数组变量名相同, 就可以直接通过数组接收参数

作用: 把多个数据接收到数组中

方法

// 声明请求处理类
@RestController
public class RequestController {
    // 声明请求处理方法
    @RequestMapping("/arrayParam")
    public String simpleParam(String[] hobby) {
       // 获取请求参数
       System.out.println(Arrays.toString(hobby));
       return "ok";
    }
}

传参

3.2集合

请求参数名称与形参中集合名称相同, 通过@RequestParam绑定参数关系

作用: 把多个数据接收到集合中

方法

// 声明请求处理类
@RestController
public class RequestController {
     // 声明请求处理方法
     @RequestMapping("/listParam")
     public String simpleParam(@RequestParam ArrayList<String> hobby) {
         // 获取请求参数
         System.out.println(hobby);
         return "ok";
    }
}

传参

4.时间日期参数

规则: 使用@DateTimeFormat注解完成日期参数格式转换

方法

// 声明请求处理类
@RestController
public class RequestController {
     // 声明请求处理方法
     @RequestMapping("/dataParam")
     public String dataParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime) {
        //接收时间类型的数据
        System.out.println(updateTime);
        return "ok";
     }
}

传参

5. JSON参数

规则: JSON数据键名与形参对象属性名相同, 定义POJO类型参数即可接收参数, 使用@RequestBody标识

实体类

public class User {
    public String name;
    public String age;
    public Address address;
    //生成get/set方法
    //重写toString()方法 
}
 public class Address {
    public String province;
    public String city;
    //生成get/set方法
    //重写toString()方法 
}

方法

// 声明请求处理类
@RestController
public class RequestController {
     // 声明请求处理方法
     @RequestMapping("/jsonParam")
     public String jsonParam(@RequestBody User user) {
       //接收JSON类型的数据
       System.out.println(user);
       return "ok";
     }
}

传参

步骤: POST -> Body -> Json 或 raw

6.路径参数

规则: 通过请求Url直接传递参数, 使用 { } 来标识路径参数, 再使用@PathVariable来获取路径参数

方法

// 声明请求处理类
@RestController
public class RequestController {
     // 声明请求处理方法
     @RequestMapping("/simpleParam/{id}/{name}")
     public String simpleParam(@PathVariable String id, @PathVariable String name) {
         // 获取请求参数
         System.out.println(id);
         System.out.println(name);
         return "ok";
     }
}

传参

响应

目标: 设置响应数据

3.1设置响应

当我们使用 @RestController 注解, 声明请求处理类时, 类中的方法默认就会把返回值作为参数响应给前端

注解: @ResponseBody

类型: 方法注解,类注解

位置: Controller方法上/类上

作用: 将方法返回值直接响应, 如果返回值类型是 实体对象或集合, 将会转成JSON格式响应

说明: @RestController = @Controller + @ResponseBody

示例

// 声明请求处理类
@RestController
public class ResponseController {
    //声明请求处理方法
    @RequestMapping("/hello")
    public String hello(){
        //响应简单字符串
        return "hello world";
    }
}
// 声明请求处理类
@RestController
public class ResponseController {
    //声明请求处理方法
    @RequestMapping("/getAddr")
    public Address getAddr(){
        //响应对象信息
        Address address = new Address();
        address.setProvince("广东");
        address.setCity("深圳");
        return address;
    }
}
// 声明请求处理类
@RestController
public class ResponseController {
    //声明请求处理方法
    @RequestMapping("/listAddr")
    public List<Address> listAddr(){
        //响应集合信息
      List<Address> list = new ArrayList<Address>();
      Address addr = new Address();
      addr.setCity("广东");
      addr.setProvince("广州");
      Address addr2 = new Address();
      addr2.setProvince("山东");
      addr2.setCity("济南");
      list.add(addr);
      list.add(addr2);
      return list;
    }

}

3.2统一响应

如果后端的响应结果是随意返回的, 那么就会增加前端的处理成本, 所以需要设置统一的数据响应格式

引入Result.java类, 作为统一的响应结果

@RestController
public class ResponseController {
    @RequestMapping("/hello")
    public Result hello() {
        //不管什么类型的数据, 都封装到Result中, 响应给前端
        return Result.success("hello world");
    }
}

案例

目标: 响应员工数据给前端,前端正确展示列表

实现步骤

  1. 在pom.xmll文件中引入dom4j依赖, 用于解析xml文件

  1. 引入工具类XMLParserUtils, 实体类Emp, xml文件emp.xml

  1. 引入前端静态资源, 放在resources下的static目录中
  2. springboot项目的静态资源默认存放目录为: classpath:/static或classpath:/public或classpath:/resources

  1. 编写controller程序, 处理请求, 解析xml文件, 把解析结果封装到实体类中, 响应给前端
package com.itheima.controller;

import com.itheima.pojo.Emp;
import com.itheima.pojo.Result;
import com.itheima.utils.XmlParserUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class EmpController {

    @RequestMapping("/listEmp")
    public Result list(){
        //1. 加载并解析emp.xml
        String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();
        System.out.println(file);
        List<Emp> empList = XmlParserUtils.parse(file, Emp.class);

        //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("就业指导");
            }
        });

        //3. 响应数据
        return Result.success(empList);
    }

}
  1. 测试接口
  2. 访问页面: http://localhost:8080/emp.html

分层解耦

三层架构

如果我们把所有的代码都写在一个类中, 那么程序的可阅读和可维护性是极差的, 也不利于代码的复用

为了提高程序的维护效率, 设计的对象要符合单一职责原则

  1. Controller层: 控制层,负责接收前端请求, 并响应数据
  2. Service层: 业务逻辑层, 负责业务逻辑处理
  3. Dao层: 数据访问层, 负责数据访问操作, 包括数据的增,删,改,差

内聚耦合

内聚: 软件中各个功能模块内部的功能联系

耦合: 衡量软件中各个层/模块之间的依赖和关联的程度

软件设计原则: 高内聚, 低耦合

高耦合

  1. 通过三层架构拆分的代码, 提高了程序的内聚, 但是模块之间依然是耦合的
  2. 如果controller需要切换不同的server代码, 依然要改动controller

低耦合

  1. 为了实现模块之间的解耦合, 就出现了控制反转和依赖注入思想
  2. 所谓控制反转就是把对象交给容器管理, 对象的创建控制权由程序转移到容器, 简称IOC
  3. 所谓依赖注入, 就是程序运行时,所依赖的资源, 由容器提供, 简称DI
  4. 比如我们把A对象交给容器管理, 当程序中需要使用A类型的对象时, 容器自动创建A类型的对象
  5. 由IOC容器创建/管理的对象, 称之为bean对象

程序改造

通过Springboot提供的注解, 完成程序的解耦和

  1. 将Server层和Dao层的实现类,交给IOC容器管理,使用 @Component 注解
  2. 在Controller层 和 server层中, 注入运行时依赖的对象, 使用 @Autowired 注解
  3. 在程序运行时, IOC容器会自动创建使用到的对象, 并根据类型赋值给对应的变量
  4. 运行测试

IOC详解

介绍

对象的创建控制权由程序转移到外部容器, 这种思想称为控制反转, 简称IOC

为了降低程序的耦合度, SpringBoot提供了IOC和DI的相关注解

注解

作用: 将当前对象交给IOC容器管理, 成为IOC容器的Bean对象

  1. @Component注解是声明ben对象的基础注解, 其他注解都是衍生品

命名规则

声明Bean的时候可以通过value属性指定Bean的名字, 不指定默认为 类名首字母小写

@Repository(value = "daoA") 或 @Repository("daoA")
  1. 在springboot集成web开发中, 声明控制器Bean只能用@Controller注解
  2. 查看ben对象

组件扫描

@ComponentScan注解用于指定IOC容器的扫描范围, Bean对象想要生效. 就需要被组件扫描到

  1. 隐式配置: 启动类的 @SpringBootApplication注解 中,集成了@ComponentScan()注解
  2. 默认范围: 扫描启动类所在包及其子包
  3. 强烈建议: 把所有的bean对都放在启动类的包下, 避免麻烦

  1. 手动指定: 通过注解可以指定IOC容器扫描哪些包
@ComponentScan({ "dao", "com.itheima" })
@SpringBootApplication
public class SpringbootWebReqResApplication {
    ... ...
}

DI详解

容器为应用程序提供运行时所依赖的资源, 称为依赖注入

springboot提供了 @Autowired 注解, 用于依赖注入,

  1. 程序运行时, IOC容器会创建bean对象, 根据对象的类型, 赋值给变量, 供程序使用

类型注入

@Autowired注解, 默认是按照类型装配对象, 如果容器中存在多个同类型的Bean, 就会报错,

  1. 提升Bean的优先级

  1. 指定Bean的名称

  1. 按照名称装配

  1. 注解对比
  • @Autowired是spring框架提供的注解, @Resource是JDK提供的注解
  • @Autowired默认按照类型注入对象, @Resource默认按照名称注入对象
  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值