【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;}@Overridepublic 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);// 对象转 JSONString 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成功";}elsereturn "获取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(); // 默认值为 truesession.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响应状态码.

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

111. 二叉树的最小深度

给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2示例 2&#xff1a; 输入…

Three.js学习9:Three.js 响应式设计

-----------------------------华丽的分割线--------------------- 相关代码均已上传到 gitee 中&#xff1a;myThree: 学习 Three.js &#xff0c;努力加油~&#xff01; Gitee 静态演示地址&#xff1a;Three JS 演示页面 -----------------------------华丽的分割线------…

相机图像质量研究(17)常见问题总结:CMOS期间对成像的影响--靶面尺寸

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

【AIGC】Stable Diffusion的常见错误

Stable Diffusion 在使用过程中可能会遇到各种各样的错误。以下是一些常见的错误以及可能的解决方案&#xff1a; 模型加载错误&#xff1a;可能出现模型文件损坏或缺失的情况。解决方案包括重新下载模型文件&#xff0c;确保文件完整并放置在正确的位置。 依赖项错误&#x…

009集——磁盘详解——电脑数据如何存储在磁盘

很多人也知道数据能够保存是由于设备中有一个叫做「硬盘」的组件存在&#xff0c;但也有很多人不知道硬盘是怎样储存这些数据的。这里给大家讲讲其中的原理。 首先我们要明白的是&#xff0c;计算机中只有0和1&#xff0c;那么我们存入硬盘的数据&#xff0c;实际上也就是一堆0…

Python三级考试笔记

Python三级考试笔记【源源老师】 三级标准 一、 理解编码、数制的基本概念&#xff0c;并且会应用。 1. 能够进行二进制、十进制以及十六进制之间的转换&#xff1b; 2. 理解Python中的数制转换函数。 二、 掌握一维数据的表示和读写方法&#xff0c;能够编写程序处理一维数据…

【C++】C++11上

C11上 1.C11简介2.统一的列表初始化2.1 {} 初始化2.2 initializer_list 3.变量类型推导3.1auto3.2decltype3.3nullptr 4.范围for循环5.final与override6.智能指针7. STL中一些变化8.右值引用和移动语义8.1左值引用和右值引用8.2左值引用与右值引用比较8.3右值引用使用场景和意义…

【算法设计与分析】搜索旋转排序数组

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff…

什么是“感知机”?

感知机&#xff08;神经网络和支持向量机的理论基础&#xff09; 概念&#xff1a;简单来说&#xff0c;感知机就是一个旨在建立一个线性超平面对线性可分的数据集进行分类的线性模型 分类&#xff1a; 单层感知机多层感知机&#xff08; Multi-Layer Perceptron&#xff0c…

【lesson55】线程同步

线程同步 同步&#xff1a;在保证数据安全的前提下&#xff0c;让线程能够按照某种特定的顺序访问临界资源&#xff0c;从而有效避免饥饿问题&#xff0c;叫做同步 例一&#xff1a;我们之前的抢票代码&#xff0c;一个线程把票全抢完了&#xff0c;它错了吗&#xff1f;没错…

Qt Creator 继承分文件编写代码流程实现简单案列

Qt Creator 继承分文件流程实现简单案列 打开Qt Creator&#xff0c;新建c项目 添加类 完成之后&#xff0c;会自动生成.h和.cpp文件 一、animal.h文件 主要用来写类&#xff0c;包括成员变量和函数 #ifndef ANIMAL_H #define ANIMAL_H #include <iostream> #inclu…

高效货运 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 老李是货运公司承运人&#xff0c;老李的货车额定载货重量为wt&#xff1b;现有两种货物&#xff0c;货物A单件重量为wa&#xff0c;单件运费利润为pa&#xff0c…

【matalab】基于Octave的信号处理与滤波分析案例

一、基于Octave的信号处理与滤波分析案例 GNU Octave是一款开源软件&#xff0c;类似于MATLAB&#xff0c;广泛用于数值计算和信号处理。 一个简单的信号处理与滤波分析案例&#xff0c;说明如何在Octave中生成一个有噪声的信号&#xff0c;并设计一个滤波器来去除噪声。 首…

从数字孪生到智慧城市:科技引领下的城市未来展望

一、引言 随着科技的飞速发展&#xff0c;数字孪生和智慧城市已成为当今世界城市发展的重要趋势。数字孪生通过建立物理世界的数字模型&#xff0c;为城市管理和规划提供了前所未有的可能性&#xff1b;而智慧城市则借助先进的信息通信技术&#xff0c;使城市运行更加高效、便…

python调用智谱ai 大模型的完整步骤 (国内的 AI 大模型 对话)

要使用Python调用智谱AI的API进行异步调用&#xff0c;您需要遵循以下步骤&#xff1a; 1. **获取API密钥**&#xff1a; - 您需要从智谱AI平台获取一个API密钥&#xff08;API Key&#xff09;&#xff0c;这个密钥将用于所有API请求的身份验证。 2. **安装…

Springmvc 的参数绑定之list集合

标签中name属性的值就是pojo类的属性名 参数绑定4 list [对象] <form action"teaupd.do" method"post"> <c:forEach items"${list}" var"tea" varStatus "status"> 教师编号&#xff1a;<input…

C语言学习day14:跳转语句

今天学习的跳转语句主要是三种&#xff1a; break continue goto 上一篇文章已经说过了break和continue break&#xff1a;结束这个循环 continue&#xff1a;结束当前的循环迭代&#xff0c;进行下一次的迭代 看看二者代码的区别 代码&#xff08;break&#xff09;&am…

嵌入式I2C 信号线为何加上拉电阻(图文并茂)

IIC 是一个两线串行通信总线&#xff0c;包含一个 SCL 信号和 SDA 信号&#xff0c;SCL 是时钟信号&#xff0c;从主设备发出&#xff0c;SDA 是数据信号&#xff0c;是一个双向的&#xff0c;设备发送数据和接收数据都是通过 SDA 信号。 在设计 IIC 信号电路的时候我们会在 SC…

相机图像质量研究(19)常见问题总结:CMOS期间对成像的影响--Sensor Noise

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

C# VS2022+WinForm+Oracle19.3+Excel,根据数据库表定义书生成SQL

目标&#xff1a; 用Excel写数据库的表的定义书&#xff0c;用该工具生成SQL&#xff0c;在客户端执行&#xff0c;把表结构导入数据库&#xff0c;生成真正的表 Github代码下载 目录 0.完成下面开发环境的准备1 操作系统Win11 专业版 21H22 oracle 19.33 Visual Studio Commun…