首页 > 编程语言 >SpringBootWeb最新相关技术(上接maven):IDEA2023-Spring环境,http协议复习概览,web服务器Tomcat,请求响应java服务器项目编写(BS模型,IOC,DI等)

SpringBootWeb最新相关技术(上接maven):IDEA2023-Spring环境,http协议复习概览,web服务器Tomcat,请求响应java服务器项目编写(BS模型,IOC,DI等)

时间:2024-03-27 12:59:55浏览次数:29  
标签:String DI age SpringBootWeb 请求 注解 服务器 public name

Spring

官网HTTPs://spring.io
spring生态(全家桶)基于Spring Framework基础框架。但如果我们基于该基础框架开发,会面临配置繁琐,入门难度大的问题,SpringBoot则可以快速开发(简化配置,快速开发)。

1.SpringBootWeb入门

使用SpringBoot开发一个Web应用,浏览器发起请求/hello之后,给浏览器返回字符串"hello world~"

步骤:

  1. 创建SpringBoot工程,并勾选web开发相关依赖(New Project/Module的时候Spring Initializer)。
    在这里插入图片描述

    在这里插入图片描述

  2. 定义HelloController类,添加方法hello,并添加注解

    @RestController
    public class HelloController {
        @RequestMapping("/hello")
        public String hello(){
            System.out.println("Hello World~");
            return "Hello World~";
        }
    }
    
  3. 运行测试

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.HTTP协议

2.1HTTP概述(简略)

规定了浏览器与服务器之间数据传输的规则
基于tcp面向连接;

基于请求响应模型:一次请求一次响应;

http是无状态的协议:对事物处理没有记忆能力。每一次请求响应都是独立的(优点:速度快;缺点:多次请求之间不能共享数据)——可以通过web会话技术解决记忆问题(比如用户是否处于登录状态)。

2.2HTTP请求协议

GET /hello HTTP/1.1  请求行:方式,路径,协议
以下为请求头
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 浏览器接受的资源类型:text/*表示文本,image/*表示图片,*/*表示所有
Accept-Encoding: gzip, deflate, br 浏览器支持的压缩类型
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 浏览器偏好的语言
Cache-Control: max-age=0
Connection: keep-alive
Host: localhost:8080 主机名
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0 浏览器类型
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Microsoft Edge";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"

常见的请求头还包括:content-length请求主体大小,content-type请求主题数据类型,例如json

请求体是post请求特有的部分,post分为请求行,请求头,请求体;而get只有前两个部分?k=v&k=v

2.3HTTP响应协议

HTTP/1.1 200 相应行,响应状态码
Content-Type: text/html;charset=UTF-8
Content-Length: 12
Date: Mon, 25 Mar 2024 06:48:18 GMT
Keep-Alive: timeout=60
Connection: keep-alive

2.4HTTP协议解析

协议解析(浏览器作为客户端是不需用我们去解析协议的,而服务端则需要按照请求格式对http协议进行解析,并按照响应格式,对http协议进行响应)

服务端开发工程师用serverSocket接收请求,按照字符串组成规则进行解析。手写解析http的代码IO加socket是可以实现的,但很复杂。由于格式固定,就可以用jetty,weblogic以及tomcat等写好的软件进行解析。

3.Web服务器-Tomcat

web服务器是一个软件程序,对http协议的操作进行封装,使程序员不必直接对协议进行操作,使web开发更搞笑。主要功能是提供网上信息浏览服务

springboot已经内置了tomcat

3.1 tomcat简介

apache
支持少量javaEE规范servlet/jsp
也被成为web容器,servlet容器

3.2 基本使用

官网安装绿色版本之后改成gbk编码(conf/logging)
startup.bat双击就可以运行脚本文件/停止的话shutdown.bat

想要改端口号(conf/server.xml)端口号改为80(http默认端口的话,输入url就不用输入端口号了)
将项目放在webapps目录下

不用安装了,因为SpringBoot已经内置了

3.3 入门程序解析

maven有许多起步依赖starter,比如spring-boot-starter-aop,spring-boot-starter-web等(其余许多被依赖传递,而web就依赖了内嵌的tomcat)

本来只是自己编写一个Controller类,tomcat不识别;但是tomcat识别servlet(一项javaEE规范里的技术)DispatcherServlet(SpringBoot底层支持的一个核心的Servlet接口的实现类,称之为核心控制器或者前端控制器)

请求响应都会先经过Dispatcher:tomcat将接受到的协议信息进行解析,并将结果封装在一个httpServletRequest对象中,应用程序就可通过该对象获取请求数据了,然后对于该数据进行处理,处理完了之后再响应httpServletResponse。

BS架构(broswer-server)用户只要一个browser
CS架构,需要安装客户端。

4.请求响应

4.1请求

controller中获取请求数据(参数)


接口测试工具,postman。前后端分离之后,后端接口测试需求,浏览器直接地址测试只能get,又得单独去写前端post。
postman是一款功能强大的网页调试与发送网页http请求的chrome插件;作用:常用于进行接口测试(有一些apipost以及apifox的衍生大差不差)
可以下载vscode同名插件,可以用网页版(注意网页版访问本地地址需要下载代理),也可以下载到本地。


简单参数:

原始方式接收

@RestController
public class RequestController {
    @RequestMapping("/simpleParam")
    public String simpleParameter(HttpServletRequest request){
        String name = request.getParameter("name");
        String age = request.getParameter("age");
        System.out.println("name:"+name+"&"+"age:"+age);
        return "ok";
    }
}

在这里插入图片描述

get方式request的时候
在这里插入图片描述

post方式request的时候
在这里插入图片描述

如果想操作上述获得的数据,还需要手动类型转换和分开写接受,比较麻烦;但是有更为简单的方式:基于SpringBoot框架。

@RestController
public class RequestController {
    @RequestMapping("/simpleParam")
    public String simpleParameter(String name,Integer age){//注意参数名与请求数据名保持一致!!!
    //参数名对应不上的话,不会报错,但是值为null
    //参数名不一致想要修改,需要使用@RequestParam(name = "name")String username来进行映射
    //@RequestParam的属性required默认为true,表示参数必须传递,否则会报错

        //age是Integer会自动类型转换
        System.out.println("name:"+name+"&"+"age:"+age);
        return "ok";
    }
}

实体参数(将上述参数封装到一个对象中去),要求对象属性名与参数名保持一致

    @RequestMapping("/simplePO")
    public String simplePO(User user){
        System.out.println(user);
        return "OK";
    }
public class User {
    String name;
    int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

在之前的类中写方法并写对应User类。
注意:如果是复杂实体,一个对象的属性就是对象,例如user有属性是Address类的实体address;则需要按照address.province,address.city传递


数组集合参数(B端传递的时候如果有多选,例如hobby可以勾选java以及game,就可以是?hobby=java&hobby=game)
服务器端就使用数组集合来接收(默认用数组接收,但是如果要用集合来接受的话就需要用注解@RequestParam)

@RequestMapping("/arrayParam")
    public String arrayParam(String[] hobby){
        System.out.println(Arrays.toString(hobby));
        return "OK";
    }
    @RequestMapping("/listParam")
    public String listParam(@RequestParam List<String> hobby){
        System.out.println(hobby);
        return "OK";
    }

时期时间类,封装到Date或1.8之后提供的LocalDateTime中由于前端日期格式也多种多样,则需要通过注解@DateTimeFormat(pattern = …)
注意:同样要求名字一致。

    @RequestMapping("/dateParam")
    public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime time){
        System.out.println(time);
        return "OK";
    }

json格式
B端效果如下:

在这里插入图片描述

S端则需要通过对象接收,接收对象属性名需要与key保持一致,同时需要加注解@RequestBody

    @RequestMapping("/jsonParam")
    public String jsonParam(@RequestBody User user){
        System.out.println(user);
        return "OK";
    }

路径参数,既是路径的一部分也是参数(like:localhost:8080/path/1),S端需要使用@PathVariable注解

//like:localhost:8080/path/1
@RequestMapping("/path/{id}")//用id来接收
    public String pathParam(@PathVariable Integer id){//上面是id,这里就业的事id
        System.out.println(id);
        return "OK";
    }

注意如果想要多个路径,like:localhost:8080/path/1/marc

//like:localhost:8080/path/1/marc
@RequestMapping("/path/{id}/{name}")//用id来接收
    public String pathParam(@PathVariable Integer id,@PathVariable String name){//上面是id,这里就业的事id
        System.out.println(id+","+name);
        return "OK";
    }

4.2响应

controller程序中获取响应数据


关键:ResponseBody注解
类型:类注解,方法注解
作用:将方法的返回值直接返回给B端,如果方法的返回值类型是对象或者是集合,将会先将其转换为json格式的数据再响应给客户端浏览器

注意:@RestController=@Controller+@ResponseBody(这也是在之前写请求代码的时候,类前面加了RestController就没加ResponseBody注解还依旧可以响应的原因),@RestController源码如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

响应示例:

    @RestController
public class ResponseController {
    @RequestMapping("/helloResp")
    public String hello(){
        System.out.println("Hello World~");
        return "HelloWorld~";
    }
}

响应体:

HTTP/1.1 undefined
Content-Type: text/plain;charset=UTF-8
Content-Length: 11
Date: Mon, 25 Mar 2024 16:56:51 GMT
Keep-Alive: timeout=60
Connection: keep-alive
 
HelloWorld~

注意:如果返回值是一个实体,则会转为json格式再返回;返回集合的话,如list,和返回数组的json格式一样,这里就不举例了。

4.2.1统一响应

如果按照之前每个函数作为api,api的返回值各不相同,且自由度太高,会造成项目管理难度太大。
故而想出一种统一的返回值

public class Result{
    //响应码,1代表成功,0代表失败
    private Integer code;
    //提示信息
    private String msg;
    //返回的数据
    private Object data;
    //...
}//然后把所有方法的返回值统一为result

改造如下:

public class ResponseController {
    @RequestMapping("/helloResp")
    public Result hello(){
        System.out.println("Hello World~");
        return new Result(1,"success","Hello World");//可以在Result里面加静态方法返回new Result
    }
}

4.3分层解耦

依照上述方式写代码(如果要,将前后端分离+dom4j解析xml中的数据)依旧复用性差。难以维护。
->分层解耦

4.3.1 web开发三层架构

数据访问;逻辑处理;接受请求,响应数据
->分开(单一职责原则)

  1. Controller:控制层,接收前端发送的请求,对请求进行处理,并响应数据
  2. Service:业务逻辑层,处理具体的业务逻辑
  3. Dao:数据访问层(持久层),负责数据访问操作,包括数据的增删改查(面向接口编程,获取不同类型的数据)

1->2->3->db/file
1<-2<-3<-db/file

4.3.2 IOC & DI入门

内聚:指的是软件中各个功能模块内部的功能联系。
耦合:衡量软件中各个层、模块之间的依赖关联程度。

controller层调用service层的实现类,所以一旦其类名发生变化就程序整体就会出错,称之为耦合。
设计原则是高内聚低耦合(模块内部功能联系越紧密越好,但是模块之间、层与层之间的耦合降低->最好是解除耦合

设置一个容器,把所需对象放在容器中,容器再为依赖提供所需资源。(实现起来需要用到Spring中两个重要的概念-控制反转/依赖注入)

  • IOC:inversion of control,控制反转。把对象的创建控制权由程序自身转移到 外部(IOC容器或者叫Spring容器)
  • DI:dependency injection,依赖注入。容器为应用程序提供运行时,所需要依赖的资源。
  • Bean对象:IOC容器中创建、管理的对象,称之为Bean。

将service以及dao的实现类交给IOC管理->加上类注解@Component;删掉Controller以及Service对于Service和Dao实现类的new(只声明,不实例化)然后在成员变量上加上Autowired注解,表示运行时,IOC容器会提供该类型的bean对象,并赋值给该变量,称之为依赖注入。

这样是实现解耦的好处是,如果要切换Service实现类,主需要给新的类前面加Component注解,并注释掉之前的

4.3.3 IOC

Spring框架为了更好地标识bean对象到底归属于哪一层,还提供了Component的三个衍生注解——@Controller,@Service,@Repository(一般不属于三层的时候,用Component,一般是一些工具类;且Repository用得少了,与MyBatis整合)

(Service等衍生注解都只是封装了一个Component。)

bean对象命名
bean对象默认为类名首字母小写,也是可以人为规定名字like:@Repository(value="daoA")// or @Repository("daoA")->可以通过IDEA 的Actuator->Beans查看(老版本为Endpoints->Beans)

注意
注意之前提到的RestController等价于ResponseBody和Controller两个注解;注意四个注解都可以声明bean,但是在SpringBoot集成Web中,声明控制器bean只能用@Controller.

组件扫描注解
声明的bean,不一定会生效,涉及bean组件扫描。想要生效,还需要被组件扫描注解@ComponentScan扫描(Spring框架提供的用来扫描前面所说的四个注解的)
之前没有显示配置ComponentScan注解是因为已经被包含在了启动类声明注解@SpringBootApplication中,默认扫描范围是启动类所在包及其子包。

也就是说,如果一个IOC注解写在了包外,就需要,自己在启动类前加ComponentScan注解,该注解是可以通过数组表示路径,来确定包名(但是要注意如果自己加了ComponentScan,原有的隐式就被覆盖,还需要再加包名)。
例如@ComponentScan({"dao","com.javaLearning"})

4.3.4 DI

对于autowired自动装配,默认按照类型装配,如果有多个类型的bean在容器中且类型符合要求,就会报错。解决方案有三种:

  • @Primary:设置bean的优先级,谁优先,给谁加,在component处。
  • @Qualifier:在装配处Autowired前面加的注解,指定bean对象名赋给value,like:@Qualifier("serviceValName")
  • @Resource:去掉Autowired注解,直接@Resource(name = "beanName")->前面的注解都是有Spring提供的,本注解是由jdk提供;与Autowired的不同是,Resource默认按照名称注解,而Autowired默认是按照类型注解。

标签:String,DI,age,SpringBootWeb,请求,注解,服务器,public,name
From: https://blog.csdn.net/m0_53190754/article/details/137052739

相关文章

  • could not read Username for 'https://github.com': terminal prompts disabled on w
    https://stackoverflow.com/questions/75990435/could-not-read-username-for-https-github-com-terminal-prompts-disabled-on-w  TrysettingatemporarycredentialhandlerforGitHub:GIT_USER="your-github-username-or-email"GIT_PASS="PAT"......
  • John Deere Service Advisor EDL V3 Electronic Data Link Diagnostic Kit
    JohnDeereServiceAdvisorEDLV3ElectronicDataLinkDiagnosticKitisapowerfultooldesignedspecificallyforheavy-dutymachineryusedinconstruction,agriculture,enginesbyJohnDeere.Thisdiagnosticadapterisessentialfortechniciansandoper......
  • redis 数据库一致性策略
    参考常见的缓存更新策略共有3种:CacheAside(旁路缓存)策略;Read/WriteThrough(读穿/写穿)策略;WriteBack(写回)策略;CacheAside(旁路缓存)策略CacheAside(旁路缓存)策略是最常用的,应用程序直接与「数据库、缓存」交互,并负责对缓存的维护,该策略又可以细分为「读策略」和「写策略」......
  • uniapp开发iOS——Xcode无法运行到运行真机提示 Executable Path is a Directory
    软件版本:Xcode14模拟器型号:Apple14Pro真机型号:Apple6sPlus异常描述:模拟器都能正常运行,Apple6sPlus运行就报错如下:解决方法:TARGET->BuildSettings->Architectures->ExcludeArchitectures里面把arm64都删掉,重新building就好了。注:删除这两个配置的时候双击会出现......
  • 在创建的Vue工程中使用el-radio定义单选框,点击不显示效果
    之前在vue工程中的组件时下面这样的<template><el-radiov-model="radio"value="0">男</el-radio><el-radiov-model="radio"value="1">女</el-radio></template> 结果是点击不显示已选中 需要在script中引入vu......
  • MogDB SQLdiag 使用指南
    MogDBSQLdiag使用指南本文出处:https://www.modb.pro/db/411957前提条件需要保证用户提供训练数据。如果用户通过提供的工具收集训练数据,则需要启用WDR功能,涉及到的参数为track_stmt_stat_level和log_min_duration_statement,具体情况见下面小节。为保证预测准确率,用户......
  • Radix UI 3.0 发布,新的布局引擎
    RadixUI3.0刚刚发布,带来了新的布局引擎、新的组件和自定义调色板生成器,这个版本的发布是向着成为构建现代应用程序的最佳组件库迈出了一大步。我们将在本文中介绍主要亮点。自定义调色板RadixThemes配备了近30种颜色比例,每种都有自己的浅色、深色和alpha变体。在......
  • aardio教程) 搭建自己的扩展库仓库
    前言aardio中有些经常使用的库,换个项目总需要复制一下,还不便于修改。虽然可以直接把它放到aardio\lib目录下,也是不便于共享给其他人使用。最近偶然翻到编辑器里的工具->开发环境->扩展库发布工具,就想着可以像官方一样,发布自己的扩展库,也便于分享给大家使用,最好能像官方扩展库一......
  • 03 QDir目录操作
    QDir用于获取电脑的磁盘,目录,文件等信息,以及目录相关创建删除等操作1.判断目录是否存在1//判断目录是否存在2QDirmdir("D:/w800");3if(mdir.exists()){4qInfo()<<"dirw800exist";5}6else{7qInfo()<<"dirw800no......
  • 服务器运维新手的第一台服务器学习教程
    目前刚接触服务器这一块的学习,这里记录一下解如何获取自己的第一台虚拟云服务器,给刚入行服务器开发的小伙伴做一个参考。具体的步骤如下:一、服务器的注册和获取1、打开bwg88服务器平台地址:点击进入https://bwh88.net/aff.php?aff=743202、进入到官网界面后如下图:3、点击注......