【JavaEE】spring boot快速上手

SpringBoot快速上手

文章目录

  • SpringBoot快速上手
    • Maven
      • 会出现的一个官方bug
      • 创建完项目之后
      • 常用的的三个功能
      • 依赖管理
      • Maven仓库
        • 中央仓库
        • 本地仓库
        • 国内源配置
        • 私服
    • springboot项目创建
      • 什么是spring
      • spring boot项目的创建
      • Hello World
        • web服务器
    • SpringMVC
      • 什么是SpringWebMVC
        • 什么是MVC
      • SpringMVC
      • 学习Spring web mvc
        • 建立连接
          • @RequestMapping
      • 请求
        • 指定请求方式
        • 请求单个参数
        • 请求多个参数
        • 传递对象
        • 参数重命名
          • 设置参数为非必传的
        • 传递数组
        • 传递集合
        • 传递`JSON`数据
          • JSON与Javascript的关系
          • JSON 优点
        • 获取URL中的参数
        • 上传文件
        • 获取Cookie/Session
          • Cookie
          • Session
          • Cookie和Session的区别
          • 传统方式获取Cookie
          • SpringBoot获取Cookie
          • 传统方式获取Session
          • SpringBoot获取Session
        • 获取Header
          • 传统获取Header
          • springboot方式获取Header
      • 响应
        • 返回静态页面
          • `@RestContraller` 和 `@Controller`的区别
          • 路径问题
          • 一个项目部署多个服务
        • 返回数据@ResponseBody
        • 返回HTML片段
        • 返回JSON
        • 设置状态码
        • 设置Header
          • 设置Content-Type
          • 设置其他Header
  • 案例
    • 加法计算器
      • 前端代码
      • 后端代码
        • 接口定义
    • 用户登录
      • 前端代码
      • 后端代码
    • 留言板
      • 前端代码
      • 后端代码
        • lombok工具包介绍
    • 图书管理系统
      • 定义接口
      • MOCK
      • 应用分层
        • 命名规范
        • MVC和三层架构之间的关系
  • SpringMVC小结
    • 什么是springmvc
    • @RequestMapping
    • 请求
    • 响应
    • 注解总结
    • Cookie和Session

学习流程介绍:

  1. spring boot
  2. springmvc
  3. spring framework
  4. mybatis
  5. spring 源码

Maven

项目管理工具,idea中将他嵌入进来了

  1. 项目构建、打包
  2. 依赖管理

会出现的一个官方bug

就是当你创建maven项目的时候会卡死

那么怎么办呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

你只能先关闭原来项目,再重新去创建maven项目。

创建完项目之后

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建完maven项目之后,idea右边会出现一个maven的框

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么右键选择

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就可以解决这个问题.

常用的的三个功能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

clean:清理class文件(也就是清理缓存)

package:打包

install:在工作中常用于发布包到本地

依赖管理

通过poe.xml

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

依赖已经进来了.

  1. 会将当前的依赖引入到当前项目里面

  2. Maven Helper

    插件,可以查看依赖之间的关系

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Maven仓库

仓库:

  1. 本地仓库
  2. 远程仓库
    1. 中央仓库
    2. 私有仓库
中央仓库

中央仓库

中央仓库查询会有一定的滞后性

本地仓库

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需要自己配置噢

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

国内源配置

找到setting.xml文件,在 mirrors 节点上,添加内容如下:

<mirror>
 <id>aliyunmaven</id>
 <mirrorOf>central</mirrorOf>
 <name>阿⾥云公共仓库</name>
 <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
 </mirror>

然后再设置好新项目的setting.建议找一个存储空间大的盘,像我一样设置(如上图).因为随着时间推移,外卖做的项目的数量变多,本地仓库中的setting文件的占用的内存也会越来越多.

还有就是建议命名不要用中文!

私服

企业开发中一些代码具有一定的私密性,所以企业会建立自己的私服(需要账号密码)


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

springboot项目创建

建议是申请教育版本的ideaa或者专业版的idea噢~

如果是社区版的idea,那么就需要你去下载spring 插件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

别直接点击Install,除非你钱多~

插件地址

什么是spring

spring是一个非常好用的框架,快 简单 安全

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

spring是一个家族产品,在面试中提到spring,大多是指spring家族.

spring boot的诞生就是未来简化spring程序开发的


spring boot项目的创建

  1. 需要注意的是现在idea2023创建spring项目的时候,只有jdk17 jdk21,可以选择,这里我的解决办法是替换项目的源头,我们只知道IDEA页面创建Spring项目,其实是访问spring initializr去创建项目。故我们可以通过阿里云国服去间接创建Spring项目。将https://start.spring.io/或者http://start.springboot.io/替换为 https://start.aliyun.com/.即可解决这个问题.

  2. 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  3. 选择springboot版本,选择2.X版本,因为2.X使用的是JDK8,也不要选择snapshot版本.(不稳定版本)

    snapshot 程序有问题的话,可以修改,重新发包

    非 snapshot 是不能修改的,若需要修改,只能改版本号

  4. 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 在这里插入图片描述

  6. 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    此处的测试代码,和测试人员无关,是开发人员的测试代码,

    开发人员先进行简单测试,测试完成之后再提交给测试人员.单元测试代码

  7. 项目启动

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Hello World

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

创建HelloController

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "hello, SpringBoot";
    }
}

然后再网页中输入localhost:8080/hello

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

web服务器

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

常⻅的Web服务器有: Apache,Nginx, IIS, Tomcat, Jboss

SpringBoot 内置了Tomcat服务器, ⽆需配置即可直接运⾏

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tocmat默认端⼝号是8080, 所以我们程序访问时的端⼝号也是8080


SpringMVC

本小节将会了解到的:

  1. 学习常见的Spring MVC Web注解
  2. 了解SPring MVC来完成基础功能开发
  3. 了解MVC和三层架构的设计模式
  4. 掌握企业开发的命名规范

什么是SpringWebMVC

Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就包含在Spring框架中。它的正式名称“Spring Web MVC”来自其源模块的名称(Spring-webmvc),但它通常被称为"SpringMVC".

什么是MVC

Model模型:是应⽤程序的主体部分,⽤来处理程序中数据逻辑的部分

View视图:指在应⽤程序中专⻔⽤来与浏览器进⾏交互,展⽰数据的资源

Controller控制器:可以理解为⼀个分发器,⽤来决定对于视图发来的请求,需要⽤哪⼀个模型来处理,以及处理完后需要跳回到哪⼀个视图。即⽤来连接视图和模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MVC是一种思想,而Spring MVCMVC的一种实现


SpringMVC

SpringMVC项目的创建和上面创建SpringBoot项目一样.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不过目前推崇的前后端分离已经不需要View层了,于是乎:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

学习Spring web mvc

  1. 建立连接
  2. 请求
  3. 响应
建立连接
@RequestMapping

类注解、方法注解

作用范围:

  1. 当一个类有多个注解的时候,这些注解没有先后顺序

    类路径+方法路径

    @RequestMapping("/user")// /可加可不加 但是我建议你加
    @RestController
    public class UserController {
     @RequestMapping("/hello")
     public String hello()
     {
         return "hello";
     }
    }
    
    

    此时访问路径:[127.0.0.1:8080/user/hello](http://127.0.0.1:8080/user/hello)

  2. 方法上

    @RestController
    public class UserController {
        @RequestMapping("/hello")
        public String hello()
        {
            return "hello";
        }
    }
    

请求方式是Get还是Post

  1. get通过浏览器访问的方式为get
  2. post

请求

指定请求方式
@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    // 注解里,双引号的值会赋给"value"这个属性
    // 只有一个属性的时候,且属性名为value,可以省略
    public String hello()
    {
        return "hello";
    }
}
请求单个参数
@RequestMapping("/r1")
    public String r1(String name){
        return "接受到参数 name:" + name;
    }

    @RequestMapping("/r2")
    public String r2(int age){
        return "接受到参数 age:" + age;
    }
请求多个参数
@RequestMapping("/r3")
    public String r3(String name,Integer age){
        return "name:"+name+" "+"age:"+age;
        // 参数请求 顺序先后不分
    }
传递对象
// 创建userInfo
public class UserInfo {
    private Integer id;
    private String name;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

@RequestMapping("/r4")
    public String r4(UserInfo user){
        return user.toString();
    }
参数重命名

@RequestParam

@RequestMapping("/r5")
    public String r4(@RequestParam("name") String username, Integer age){
        return "username: " + username+ ", age: " + age;
    }

@RequestParam(“name”) 从请求中获取 name 的参数,并且赋值给 username 参数 且默认这个参数是必传的

设置参数为非必传的

我们先看一下RequestParam

public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

于是乎我们可以:将required设置为false

@RequestMapping("/r5")
    public String r5(@RequestParam(value = "name", required = false) String username, Integer age){
        return "username: " + username+ ", age: " + age;
    }
传递数组
@RequestMapping("/r7")
    public String r7(String[]arr){
        return Arrays.toString(arr);
    }
传递集合
@RequestMapping("/r8")
    public String r8(@RequestParam("list") List<String> list){
        return list.toString();
    }

在Spring MVC中,@RequestParam 注解用于从请求中提取参数值。@RequestParam("list") List<String> list 表示从请求中获取名为 “list” 的参数,并将其绑定到一个 List<String> 类型的变量 list 上。

这种方式常用于接收前端传递的多个相同类型的参数,例如,前端通过 URL 或者表单提交将多个字符串参数传递给后端。通过将它们绑定到一个 List<String> 类型的参数上,你可以轻松地处理多个相同类型的参数。

请求 URL 如下:

/r8?list=value1&list=value2&list=value3

通过上述的 @RequestParam("list") List<String> list,Spring 将自动将这些值绑定到一个列表中,你可以在方法体内使用这个 list 参数来访问传递的多个值。

总的来说,这是一种方便的方式,用于处理请求中包含多个相同类型参数的场景。

在Web开发中,有时候我们需要从前端接收一组相同类型的参数。使用 List<String> 类型的参数绑定可以方便地处理这种情况,而不需要为每个参数定义一个独立的变量。

考虑以下情景:

  1. 表单提交: 当用户通过表单提交多个相同类型的数据时,可以将这些数据绑定到一个 List<String> 中。例如,一个多选框(Checkbox)的多个选项。

  2. URL参数: 当通过URL传递多个相同类型的参数时,使用List<String> 可以更清晰地表达意图。例如,/r8?list=value1&list=value2&list=value3

  3. RESTful风格的请求: 在RESTful风格的API中,有时需要从请求体或路径中接收多个相同类型的数据。

绑定到 List<String> 的好处包括:

  • 代码简洁: 不需要为每个参数定义一个变量,通过一个 List 就可以容纳所有的值。

  • 可扩展性: 如果前端需要传递更多的相同类型的参数,代码不需要做太多修改。

  • 清晰明了: 通过命名为 list,表达了这是一组相同类型的数据。

传递JSON数据
JSON与Javascript的关系

没有关系, 只是语法相似, js开发者能更快的上⼿⽽已, 但是他的语法本⾝⽐较简单, 所以也很好学

JSON 优点
  1. 简单易⽤: 语法简单,易于理解和编写,可以快速地进⾏数据交换

  2. 跨平台⽀持: JSON可以被多种编程语⾔解析和⽣成, 可以在不同的平台和语⾔之间进⾏数据交换和传输

  3. 轻量级: 相较于XML格式, JSON数据格式更加轻量级, 传输数据时占⽤带宽较⼩, 可以提⾼数据传输速度

  4. 易于扩展: JSON的数据结构灵活,⽀持嵌套对象和数组等复杂的数据结构,便于扩展和使⽤

  5. 安全性: JSON数据格式是⼀种纯⽂本格式,不包含可执⾏代码, 不会执⾏恶意代码,因此具有较⾼的安全性

public class JSONUtils {
    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        UserInfo userInfo = new UserInfo();
        userInfo.setName("zhangsan");
        userInfo.setAge(18);
        userInfo.setId(12);

        // 对象转 JSON
        String s = objectMapper.writeValueAsString(userInfo);
        System.out.println(s);

        // JSON 转成 java 对象
        UserInfo userInfo1 = objectMapper.readValue(s,UserInfo.class);
        System.out.println(userInfo1);
    }
}

@RequestMapping("/r9")
    public String r9(@RequestBody UserInfo userInfo){
        return userInfo.toString();
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取URL中的参数

@PathVariable

@RequestMapping("/r10/{articleId}")
    public String r10(@PathVariable Integer articleId){
        return "articleId:"+articleId;
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上传文件

@RequestPart

@RequestMapping("/r11")
    public String r11(@RequestPart MultipartFile file){
        return "获取上传文件:" + file.getOriginalFilename();
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

@RequestMapping("/r11")
    public String r11(@RequestPart MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        file.transferTo(new File("D:/temp/"+fileName));
        return "获取上传文件:" + file.getOriginalFilename();
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这段代码虽然也可以不加注解,但是建议还是将注解加上去

获取Cookie/Session
Cookie

HTTP 协议⾃⾝是属于 “⽆状态” 协议.

无状态协议:

默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信, 和下次通信之间没有直接的联系.

但是实际开发中, 我们很多时候是需要知道请求之间的关联关系的.

例如登陆⽹站成功后, 第⼆次访问的时候服务器就能知道该请求是否是已经登陆过了.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Session

会话:对话的意思

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在计算机领域, 会话是⼀个客⼾与服务器之间的不中断的请求响应. 对客⼾的每个请求,服务器能够识

别出请求来⾃于同⼀个客⼾. 当⼀个未知的客⼾向Web应⽤程序发送第⼀个请求时就开始了⼀个会话.

当客⼾明确结束会话或服务器在⼀个时限内没有接受到客⼾的任何请求时,会话就结束了.

⽐如我们打客服电话

每次打客服电话, 是⼀个会话. 挂断电话, 会话就结束了

下次再打客服电话, ⼜是⼀个新的会话.

如果我们⻓时间不说话, 没有新的请求, 会话也会结束

服务器同⼀时刻收到的请求是很多的. 服务器需要清楚的区分每个请求是从属于哪个⽤⼾, 也就是属于哪个会话, 就需要在服务器这边记录每个会话以及与⽤⼾的信息的对应关系.

Session是服务器为了保存⽤⼾信息⽽创建的⼀个特殊的对象.

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Session的本质就是⼀个 “哈希表”, 存储了⼀些键值对结构. Key 就是SessionID, Value 就是⽤⼾信息(⽤⼾信息可以根据需求灵活设计).

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SessionIsd是由服务器生成的一个"唯一性字符串",从Session机制的角度来看,这个唯一性字符串称为"Sessionld".但是站在整个登录流程中看待,也可以把这个唯一性字符串称为"token".
上述例子中的令牌ID,就可以看做是Sessionld,只不过令牌除了ID之外,还会带一些其他信息,比如时间,签名等.

  1. 当⽤⼾登陆的时候, 服务器在 Session 中新增⼀个新记录, 并把 sessionId返回给客⼾端. (通过HTTP 响应中的 Set-Cookie 字段返回).

  2. 客⼾端后续再给服务器发送请求的时候, 需要在请求中带上 sessionId. (通过 HTTP 请求中的Cookie 字段带上).

  3. 服务器收到请求之后, 根据请求中的 sessionId在 Session 信息中获取到对应的⽤⼾信息, 再进⾏后续操作.找不到则重新创建Session, 并把SessionID返回

Session默认是保存在内存中的.如果重启服务器则Session数据就会丢失.

Cookie和Session的区别

在此之前我们可以举一个例子

学生入学

学校收集学生信息,姓名,班级,身份证号等等

那么学校该如何存储呢?

NumberNameAgeAttribute
1张三18CS
2李四17CS
3王五20CS

学校存储信息之后,给学生发学生证

学生出入学校,使用学生证(就好比是Cookie)来证明身份

但是,学生证可以造假,但是学校的教务系统的信息是造假不了的

于是乎:Cookie是可以造假的,但是Session不行

  1. 用户提供账号和密码,服务器进行验证。

  2. 服务器验证通过,会把信息存储在Session中,把SessionId返回给客户端(通过Set-Cookie的方式)

  3. 客户端收到响应,把sessionID存储在Cookie

  4. 后续的请求中,客户端带着SessionID去请求(带着Cookie信息去请求)

    request.getSession就是从Cookie中获取SessionID,并且根据SessionID获取Session信息

区别如下:

  • Cookie是客户端保存用户信息的一种机制.Session是服务器端保存用户信息的一种机制:
  • CookieSession之间主要是通过Sessionld关联起来的,SessionldCookieSession之间的桥梁
  • CookieSession经常会在一起配合使用.但是不是必须配合.
    • 完全可以用Cookie来保存一些数据在客户端.这些数据不一定是用户身份信息,也不一定是Sessionld
    • Session中的sessionld也不需要非得通过Cookie/Set-Cookie传递,比如通过URL传递

共同点:都是会话机制

Cookie是客户端机制

Session是服务器机制

Cookie存储的信息由程序员而定

Session也不一定必须存在Cookie

传统方式获取Cookie
@RestController
@RequestMapping("/request")
public class RequestController {
    @RequestMapping("/getCookie")
    public String getCookie(HttpServletRequest request) // 内置对象,有需要就加上,没需要就不加 需要几个就加几个
    {
        Cookie[] cookies = request.getCookies();

//        Arrays.stream(cookies).forEach(x->{
//            System.out.println(x.getName()+":"+x.getValue());
//        });

        // 等价于
        if (cookies != null){
        for(Cookie c:cookies){
            System.out.println(c.getName()+":"+c.getValue());
        }
        return "获取Cookies成功";
        }
        else
            return "获取Cookies不成功";
    }
}
SpringBoot获取Cookie
@RequestMapping("/getCookie2")
    public String getCookie2(@CookieValue ("riyewuxiushi")String riyewuxiushi){
        return "riyewuxiushi"+riyewuxiushi;
    }
传统方式获取Session
	@RequestMapping("/setSession")
    public String setSession(HttpServletRequest request){
        HttpSession session = request.getSession(); // 默认值为 true
        session.setAttribute("userName","zhangsan");
        return "设置session成功";
    }

    @RequestMapping("/getSession")
    public String getSession(HttpServletRequest request){
        HttpSession session = request.getSession();
        String userName = (String) session.getAttribute("userName");
        return "登录用户:"+ userName;
    }
SpringBoot获取Session
@RequestMapping("/getSession2")
    public String getSession2(HttpSession session){ // 内置对象
        String userName = (String) session.getAttribute("userName");
        return "登录用户:"+ userName;
    }
	@RequestMapping("/getSession3")
    public String getSession3(@SessionAttribute(value = "userName",required = false) String userName){
        return "登录用户:"+ userName;
    }
获取Header
传统获取Header
	@RequestMapping("/getheader")
    public String getheader(HttpServletRequest request){
        String userAgent = request.getHeader("User-Agent");
        return "userAgent"+userAgent;
    }
springboot方式获取Header
	@RequestMapping("/getheader2")
    public String getheader2(@RequestHeader("User-Agent")String userAgent){
        return "userAgent"+userAgent;
    }

响应

返回静态页面
@RequestMapping("/return")
//@RestController
@Controller
// 多个注解的时候 注解不分先后顺序
public class ReturnController {
    @RequestMapping("/r1")
    public String r1(){
        return "/index.html";
    }
}
@RestContraller@Controller的区别

@RestController@Controller 是 Spring Framework 中用于标记类的注解,用于定义处理 HTTP 请求的控制器。它们之间有一些区别和联系。

区别:

  1. 返回值处理:@Controller 通常用于创建传统的基于视图的 Web 应用程序,它的方法可以返回模型数据和视图名称,最终由视图解析器解析为具体的视图。而 @RestController 则是用于创建 RESTful Web 服务的控制器,它的方法返回的是数据对象,会自动通过消息转换器将数据转为 JSON/XML 等格式,不会经过视图解析器。
  2. 默认行为:@RestController 组合了 @Controller@ResponseBody 注解的功能。@ResponseBody 注解表示方法的返回值将直接写入 HTTP 响应体中,而不是通过视图解析器解析为视图。因此,@RestController 类的每个方法都默认返回数据对象,而不是视图。
  3. 使用场景:@Controller 适用于传统的基于视图的 Web 应用程序,例如使用 Thymeleaf、JSP 或者其他模板引擎渲染视图。@RestController 适用于构建 RESTful Web 服务,响应 JSON 或 XML 格式的数据。

联系:

  1. 标记作用:@RestController@Controller 都是用于标记类的注解,将类声明为 Spring Framework 的组件,用于处理 HTTP 请求。
  2. 注解继承:@RestController@Controller 注解的特殊化,可以认为是 @Controller 的增强版本。@RestController 继承了 @Controller 的所有功能,同时还提供了自动将方法返回值转换为数据格式的能力。
// @RestController 源码
@Target({ElementType.TYPE}) // 表示注解的范围
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期
@Documented // 
// 上面三个是元注解:是可以注解到 其他注解 的注解
@Controller // ----> 这说明 RestContraller 是基于 Controller 实现的
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}

@RestController = @Controller + @ResponseBody

@Controller : 告诉Spring帮我们管理那些程序

@ResponseBody:返回数据

路径问题
  • servlet路径有项目名,是因为一个tomcat下面可以部署多个项目,我们需要通过路径来进行区分
  • spring路径不需要有项目名,是因为springboot内置了tomcat,一个tomcat下面就部署当前这一个项目
  • 如果部署多个项目,就启动多个tomcat
一个项目部署多个服务

IDEA 2023.2新版如何将同一个项目开启多个

返回数据@ResponseBody
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}

即可以修饰类,又可以修饰方法

修饰类:表示该类所有的方法 返回的是数据

修饰方法:表示该方法返回的是数据

	@RequestMapping("/r1")
    public String r1(){
        return "/index.html";
    }

    @ResponseBody
    @RequestMapping("/r2")
    public String r2(){
        return "hello spring";
    }
返回HTML片段
	@ResponseBody
    @RequestMapping("/r3")
    public String r3(){
        return "<h1>我是返回的片段</h1>";
    }
  • get可以被缓存 幂等
  • post不可以被缓存
返回JSON
	@ResponseBody
    @RequestMapping("/r4")
    public UserInfo r4(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("zhangsan");
        userInfo.setAge(19);
        return userInfo;
    }
	@ResponseBody
    @RequestMapping("/r5")
    public Map<String ,String> r5(){
        HashMap map = new HashMap();
        map.put("k1","v1");
        map.put("k2","v2");
        return map;
    }

    //@ResponseBody
    @RequestMapping("/r6")
    public String r6(){
        return "/a.js";
    }

    @RequestMapping("/r7")
    public String r7(){
        return "/b.css";
    }
设置状态码
	@ResponseBody
    @RequestMapping("/r8")
    public String r8(HttpServletResponse response){
        response.setStatus(401);
        return "设置状态码成功";
    }

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

状态码的设置不影响页面的显示

设置Header
设置Content-Type

我们通过设置 produces属性的值, 设置响应的报头Content-Type

// @RequestMapping源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}
  1. value: 指定映射的URL

  2. method: 指定请求的method类型, 如GET, POST

  3. consumes: 指定处理请求(request)的提交内容类型(Content-Type),例如application/json,text/html;

  4. produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回

  5. Params: 指定request中必须包含某些参数值时,才让该⽅法处理

  6. headers: 指定request中必须包含某些指定的header值,才能让该⽅法处理请求

 	@ResponseBody
    @RequestMapping("/r9")
    public String r9(){
        return "123333";
    }

	@ResponseBody
    @RequestMapping(value = "/r9",produces = "application/json")
    public String r9(){
        return "123333";
    }
设置其他Header

设置其他Header的话, 需要使⽤Spring MVC的内置对象HttpServletResponse 提供的⽅法来进⾏设置

	@ResponseBody
    @RequestMapping(value = "/r10",produces = "application/json")
    public String r10(HttpServletResponse response){
        response.setHeader("myHeader","myHeaderValue");
        return "设置Header成功";
    }

void setHeader(String name, String value) 设置⼀个带有给定的名称和值的 header. 如果 name已经存在, 则覆盖旧的值

案例

学习建议:

最开始学习的时候:小步慢跑

每次写少量的代码,就进行测试

不要一次把代码全部写完,一次性进行测试

随着对代码的熟悉,可以逐渐加大步伐

加法计算器

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
     <form action="calc/sum" method="post">
        <h1>计算器</h1>
        数字1:<input name="num1" type="text"><br>
        数字2:<input name="num2" type="text"><br>
        <input type="submit" value=" 点击相加 ">
    </form>
</body>

</html>

后端接到需求的时候

  1. 需求评审
  2. 开发
    1. 接口的定义
    2. 开发
    3. 测试(自行测试,与测试人员无关)
  3. 联调(后端和前端联调)
  4. 提测(测试人员的工作)
  5. 上线
  6. 维护
  7. 下线

后端代码

接口定义

两个原则

  1. 看我需要什么(请求参数)
  2. 看对方需要什么(响应结果)

请求参数:参与计算的两个数字

响应结果:计算结果

/calc/sum

参数:num1 , num2

返回结果:两者计算的数据


请求路径:calc/sum

请求⽅式:GET/POST

接⼝描述:计算两个整数相加

请求参数:

参数名类型是否必须备注
num1Integer参与计算的第一个数
num2Integer参与计算的第二个数

响应数据:

Content-Type : text/html

@RestController
@RequestMapping("/calc")
public class CalcController {
    @RequestMapping("/sum")
    public String sum(Integer num1, Integer num2){
        Integer sum  = num1 + num2;
        return "<h1>计算机计算结果: "+sum+"</h1>";
    }
}

问题可能出现的地方:

  1. 前端
  2. 后端
  3. 前后端交互
    1. 请求有没有发出去
    2. 后端有没有收到请求

用户登录

前端代码

// login.html
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
    </head>

    <body>
        <h1>用户登录</h1>
        用户名:<input name="userName" type="text" id="userName"><br>
        密码:<input name="password" type="password" id="password"><br>
        <input type="button" value="登录" onclick="login()">

        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
        <script>
            function login() {
               $.ajax({
                   type:"post",
                   url:"/login/check",
                   data:{
                       userName:$("#userName").val(),
                       password:$("#password").val()
                   },
                   success:function(result){
                       if (result == true){
                           // 用户名和密码正确
                           location.href = "/index.html";
                           // location.assign("index.html");
                           // location.replace("index.html");
                       }else{
                           alert("用户名或密码错误");
                       }
                   }
               });

            }

        </script>
    </body>

</html>
// index.html
<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>用户登录首页</title>
    </head>

    <body>
        登录人: <span id="loginUser"></span>

        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
        <script>
            $.ajax({
                url:"/login/index",
                type:"get",
                success:function (result) {
                    $("#loginUser").text(result);
                }
            });
        </script>
    </body>

</html>

后端代码

用户验证:

/login/check

参数:

userName

password

响应:

用户和密码是否正确

true

false


获取登录的用户

/login/index

参数:

响应:

登录的用户

@RequestMapping("/login")
@RestController
public class LoginController {
    @RequestMapping("/check")
    public boolean check(String userName, String password, HttpSession session){
        // 校验账号和密码是否为空
//        if (userName == null || "".equals(userName) || password == null || "".equals(password)){
//            return false;
//        }
        if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        // 校验账号和密码是否正确
        // 模拟数据
        if("zhangsan".equals(userName) && "123456".equals(password)){ // 防止空指针,养成习惯 常量写在前面
            session.setAttribute("userName",userName);
            return true;
        }
        return false;
    }

    @RequestMapping("/index")
    public String index(HttpSession session){
        String userName = (String) session.getAttribute("userName");
        return userName;
    }
}

留言板

前端代码

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>留言板</title>
        <style>
            .container {
                width: 350px;
                height: 300px;
                margin: 0 auto;
                /* border: 1px black solid; */
                text-align: center;
            }

            .grey {
                color: grey;
            }

            .container .row {
                width: 350px;
                height: 40px;

                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .container .row input {
                width: 260px;
                height: 30px;
            }

            #submit {
                width: 350px;
                height: 40px;
                background-color: orange;
                color: white;
                border: none;
                margin: 10px;
                border-radius: 5px;
                font-size: 20px;
            }
        </style>
    </head>

    <body>
        <div class="container">
            <h1>留言板</h1>
            <p class="grey">输入后点击提交, 会将信息显示下方空白处</p>
            <div class="row">
                <span>谁:</span> <input type="text" name="" id="from">
            </div>
            <div class="row">
                <span>对谁:</span> <input type="text" name="" id="to">
            </div>
            <div class="row">
                <span>说什么:</span> <input type="text" name="" id="say">
            </div>
            <input type="button" value="提交" id="submit" onclick="submit()">
            <!-- <div>A 对 B 说: hello</div> -->
        </div>

        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
        <script>
            // 页面加载时,显示留言信息
            // 从后端获取留言信息,显示在页面上
            $.ajax({
                type:"get",
                url:"/message/getList",
                success:function (messages) {
                    for (var message of messages){
                        var html = "<div>"+message.from+"对"+message.to+"说:"+message.message+"</div>";
                        $(".container").append(html);
                    }
                }
            });
            function submit(){
                //1. 获取留言的内容
                var from = $('#from').val();
                var to = $('#to').val();
                var say = $('#say').val();
                if (from== '' || to == '' || say == '') {
                    return;
                }
                $.ajax({
                    type:"post",
                    url:"/message/publish",
                    data:{
                        from:from,
                        to:to,
                        message:say
                    },
                    success:function (result) {
                        if (result == true){
                            // 添加成功
                            //2. 构造节点
                            var divE = "<div>"+from +"对" + to + "说:" + say+"</div>";
                            //3. 把节点添加到页面上
                            $(".container").append(divE);
                            //4. 清空输入框的值
                            $('#from').val("");
                            $('#to').val("");
                            $('#say').val("");
                        }else{
                            alert("发表失败");
                        }
                    }
                });

            }

        </script>
    </body>

</html>

后端代码

  1. 提交留言:用户输入留言信息的时候,后端需要将留言信息保存起来

    URL:/message/publish

    参数

    • from:发表人
    • to:接收人
    • message:信息

    返回:提交成功/失败

    true、false

  2. 展示留言:页面展示的时候,需要从后端获取到所有的留言信息

    URL:/message/getList

    参数

    返回:全部的留言信息

    List<MessageInfo>

lombok工具包介绍
  1. 新项目

    创建项目的时候直接加入依赖

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  2. 老项目

    在poe.xml中引入依赖,去maven中央仓库找

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
                <scope>provided</scope>
            </dependency>
    
@Data
public class MessageInfo {
 private String from;
 private String to;
 private String message;
 }

@Data 会自动生成 get、set方法

idea会自己进行反编译

单独使用可以@Getter @Setter

注解作用
@Getter自动添加getter方法
@Setter自动添加setter方法
@ToString自动添加toString方法
@EqualsAndHashCode⾃动添加 equals 和 hashCode ⽅法
@NoArgsConstructor自动添加无参构造方法
@AllArgsConstructor自动添加全属性构造方法,顺序按照属性的定义顺序
@NonNull属性不能为null
@RequiredArgsConstructor自动添加必需属性的构造方法,final+@NonNull的属性为必需

@Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor

+ @NoArgsConstructor

  1. 更快地引入依赖

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    下载这个就好啦~然后重启IDEA

    使用方法

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

package org.example.springmvc_demo;

import lombok.Data;

/**
 * @author 日夜无休时
 * @date 2024/1/29
 */
@Data
public class MessageInfo {
    
    private String from;
    private String to;
    private String message;

    // 换一个新工具 lombook @Data
//    public String getFrom() {
//        return from;
//    }
//
//    public void setFrom(String from) {
//        this.from = from;
//    }
//
//    public String getTo() {
//        return to;
//    }
//
//    public void setTo(String to) {
//        this.to = to;
//    }
//
//    public String getMessage() {
//        return message;
//    }
//
//    public void setMessage(String message) {
//        this.message = message;
//    }

}

package org.example.springmvc_demo;

import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 日夜无休时
 * @date 2024/1/29
 */
@RestController
@RequestMapping("/message")
public class MessageController {
    private  List<MessageInfo>messageInfos = new ArrayList<>();

    @RequestMapping("/publish")
    public boolean publishMessage(MessageInfo messageInfo){
        if (!StringUtils.hasLength(messageInfo.getFrom())
                || !StringUtils.hasLength(messageInfo.getTo())
                || !StringUtils.hasLength((messageInfo.getMessage()))){
            return false;
        }
        // 暂时存放在内存中
        messageInfos.add(messageInfo);
        return true;
    }

    @RequestMapping("/getList")
    public List<MessageInfo> getList(){
        for (MessageInfo messageInfo : messageInfos){

        }

        return messageInfos;
    }
}

图书管理系统

定义接口

接口定义:

  • 服务提供方:

    1. 提供什么服务

    2. 提供服务时,需要什么参数

    3. 处理之后,需要给对方什么响应

  • 客户端角度:

    1. 我需要什么服务
    2. 服务端的参数 我是否有
    3. 对方给我提供的信息,能否满足我的需求
  1. 登录

    URL: /user/login

    参数:用户名和密码

    userName

    password

    返回:

    true:用户名和密码正确

    false:用户名和密码错误

  2. 图书列表

    URL:/book/getList

    参数:无

    返回:图书列表

    List

MOCK

虚拟的、假的。开发的时候通常是几个团队并行开发,开发后需要进行测试(自测),如果测试时,依赖方还没完成开发,调用方就采用mock的方式,先进行测试。

应用分层

一种开发规范

三层架构(软件设计架构方式)

  1. 表现层:就是展示数据结果和接受用户指令的,是最靠近用户的一层
  2. 业务逻辑层:负责处理业务逻辑,里面有复杂业务的具体实现
  3. 数据层:负责存储和管理与应用程序相关的数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

命名规范
  1. 类名 大驼峰
  2. 变量名 小驼峰
MVC和三层架构之间的关系

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

共同点

  • 解耦(高内聚,低耦合)

    模块内 关系尽量紧密(高内聚)

    模块间 关系尽量关联低(低耦合)

    比如说:公司与公司之间,关联应该越小越好,公司内部,员工应该团结

SpringMVC小结

什么是springmvc

spring web mvc

@RequestMapping

既是类注解,也是方法注解

访问的URL路径 = 类路径 + 方法路径

默认支持 get/post,可以使用method属性来限制请求方式

请求

  1. 请求当个参数
  2. 请求多个参数
  3. 请求参数为对象
  4. 对参数重命名 @RequestParam 默认是必传参数,设置 required = false 就是非必传
  5. 设置参数为非必传
  6. 请求参数为JSON @RequestBody
  7. Cookie & Session
  8. 传递数组
  9. 传递集合@RequestParam
  10. 获取Header

响应

  1. 返回静态页面
  2. 返回数据@ResponseBody
  3. 返回HTML片段
  4. 返回JSON
  5. 设置响应头(状态码、编码、其他header

注解总结

  1. @RequestMapping: 路由映射
  2. @RequestParam: 后端参数重命名
  3. @RequestBody: 接收JSON类型的参数
  4. @PathVariable: 接收路径参数
  5. @RequestPart: 上传⽂件
  6. @ResponseBody: 返回数据
  7. @CookieValue: 从Cookie中获取值
  8. @SessionAttribute: 从Session中获取值
  9. @RequestHeader: 从Header中获取值
  10. @Controller: 定义⼀个控制器, Spring 框架启动时加载, 把这个对象交给Spring管理. 默认返回视图.
  11. @RestController: @ResponseBody + @Controller 返回数据

Cookie和Session

Cookie 和Session都是会话机制, Cookie是客⼾端机制, Session是服务端机制. ⼆者通过SessionId来关联. Spring MVC内置HttpServletRequest, HttpServletResponse两个对象. 需要使⽤时, 直接在⽅法中添加对应参数即可, Cookie和Session可以从HttpServletRequest中来获取, 也可以直接使⽤HttpServletResponse设置Http响应状态码.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/389528.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

变分自编码器(VAE)PyTorch Lightning 实现

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

165基于matlab的各类滤波器

基于matlab的各类滤波器。汉宁窗设计Ⅰ型数字高通滤波器、切比雪夫一致逼近法设计FIR数字低通滤波器、模拟Butterworth滤波器设计数字低通滤波器、频域抽样法的FIR数字带阻滤波器设计、频域抽样法的FIR数字带通滤波器设计、汉宁窗的FIR数字高通滤波器设计、双线性法设计巴特沃斯…

关于java的网图下载

关于java的网图下载 我们在上篇文章中&#xff0c;学习到了用Thread类去创建多线程&#xff0c;我们本篇文章来向大家介绍一下网图下载功能&#xff0c;利用多线程同时下载多个图片&#x1f609; 一、下载器 我们下载网络图片的时候&#xff0c;首先需要自己定义一个下载器&…

可变参数(c/c++)

目录 一、C语言版本 二、C的实现方法 2.1数据包 2.2sizeof...运算符 2.3可变参数模板的使用 2.4emplace_back() 有时候我们在编写函数时&#xff0c;可能不知道要传入的参数个数&#xff0c;类型 。比如我们要实现一个叠加函数&#xff0c;再比如c语言中的printf,c中的emp…

WebGPT与WebGLM

WebGPT paper: WebGPT&#xff1a;Browser-assisted question-answering with human feedbackDemo: https://openaipublic.blob.core.windows.net/webgpt-answer-viewer/index.html webgpt的论文发表最早&#xff0c;但论文本身写的比较"高山仰止"&#xff0c;可能先…

汇报工作时,你的工作会让领导满意吗?

当前你正在做的事 众所周知&#xff0c;跟领导汇报&#xff0c;第一件事需着重汇报你正在做的事&#xff0c;否则领导会感觉你无所事事。 举个例子&#xff1a; 完成了某某项目&#xff0c;在这项目中我负责&#xff1a;协调不同科室之间的纠纷&#xff0c;并把问题集中上报给…

《春山》中的贝叶斯统计——白敬亭衣服合理概率及决策比重。

目录 1. 全身黑衣服合理概率2. 真的是导演组允许&#xff1f;3. 粉丝的证据是否站得住&#xff1f;4.总结 感谢up主链接: 【理工春山学】只谈事实 从统计角度深度剖析春山学&#xff0c;她使用贝叶斯统计合理分析了在舞台中白敬亭、双魏、导演组出错的概率。接下来我采用一个新…

Acwing---846. 树的重心

树的重心 1.题目2.基本思想3.代码实现 1.题目 给定一颗树&#xff0c;树中包含 n n n 个结点&#xff08;编号 1 ∼ n 1∼n 1∼n&#xff09;和 n − 1 n−1 n−1 条无向边。 请你找到树的重心&#xff0c;并输出将重心删除后&#xff0c;剩余各个连通块中点数的最大值。 …

百度云AI

百度云AI概述 Face腾讯优图科大讯飞 百度人脸识别基于深度学习的人脸识别方案&#xff0c;准确识别图片中的人脸信息&#xff0c;提供如下功能&#xff1a; 人脸检测&#xff1a;精准定位图中人脸&#xff0c;获得眼、口、鼻等72个关键点位置&#xff0c;分析性别、年龄、表…

【JAVA-Day89】Java字符串和XML数据结构的转换

Java字符串和XML数据结构的转换 Java字符串和XML数据结构的转换&#xff0c;高效灵活转变数据摘要引言一、什么是XML二、XML格式的应用场景三、XML字符串转对象3.1 使用 DOM 解析器实现 XML 字符串转对象3.2 使用 JAXB 实现 XML 字符串转对象 四、XML对象转字符串4.1 使用 DOM …

【实战】一、Jest 前端自动化测试框架基础入门(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(一)

文章目录 一、前端要学的测试课1.前端要学的测试2.前端工程化的一部分3.前端自动化测试的例子4.前端为什么需要自动化测试&#xff1f;5.课程涵盖内容6.前置技能7.学习收获 二、Jest 前端自动化测试框架基础入门1. 自动化测试背景及原理前端自动化测试产生的背景及原理 2.前端自…

Linux中sigaction函数和SIGCHLD信号的使用

sigaction函数&#xff1a; 函数说明&#xff1a;注册一个信号处理函数 函数原型&#xff1a;int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 函数参数&#xff1a; signum:捕捉的信号act:传入参数&#xff0c;…

IDEA工程与模块管理

一、IDEA项目结构 层级关系&#xff1a; project(工程) - module(模块) - package(包) - class(类)具体的&#xff1a; 一个project中可以创建多个module一个module中可以创建多个package一个package中可以创建多个class二、Project和Module的概念 在 IntelliJ IDEA 中&…

HTTP特性

大家好我是苏麟 , 今天说说HTTP特性. 资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) 到目前为止&#xff0c;HTTP 常见到版本有 HTTP/1.1&#xff0c;HTTP/2.0,HTTP/3.0&#xff0c;不同版本的 HTTP 特性是不一样的。 这里先用 HTTP/1.1 版本给大家介…

第6讲自定义icon实现

自定义icon实现 component下新建SvgIcon目录&#xff0c;再新建index.vue 定义svg-icon组件 <template><svg class"svg-icon" aria-hidden"true"><use :xlink:href"iconName"></use></svg> </template>&…

Kafka King 推荐一款漂亮、现代、实用的kafka客户端

Kafka King 一个漂亮、现代、实用的kafka客户端&#xff0c;使用python flet、flutter构建。 Github主页&#xff1a;https://github.com/Bronya0/Kafka-King 下载&#xff1a;https://github.com/Bronya0/Kafka-King/releases 功能清单 查看集群节点列表创建主题&#xf…

Spring Resource

java.net.URL 类可用于访问带有各种URL前缀的资源&#xff0c;但是对于访问一些资源还是不够方便。比如不能从类路径或者相对于ServletContext来获取资源。而Spring 的Resource接口&#xff0c;则可以通过类路径等方式来访问资源。 1 Resource接口 图 Resource接口及方法 getI…

Java 和 JavaScript 的奇妙协同:语法结构的对比与探索(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

数学建模:BP神经网络(含python实现)

原理 BP 神经网络&#xff0c;也称为多层感知机&#xff08;Multilayer Perceptron&#xff0c;MLP&#xff09;&#xff0c;是一种常见的神经网络模型&#xff0c;用于解决各种机器学习问题&#xff0c;包括分类和回归。BP 代表“反向传播”&#xff08;Backpropagation&#…

使用redis-insight连接到服务器上的redis数据库

一、安装redis&#xff1a; 安装 Redis。你可以通过运行下面的命令来使用 yum 安装 Redis&#xff1a; sudo yum install redis 启动 Redis 服务。安装完成后&#xff0c;你可以通过运行下面的命令来启动 Redis 服务&#xff1a; sudo systemctl start redis 设置 Redis 服务…