Spring MVC程序开发

所谓的Spring MVC程序开发,其实也是一个Spring Boot项目。

MVC是Model View Controller的缩写,它是软件工程中的一种软件架构模式,它把软件系统分为模型,视图,控制器三个部分。

项目使用什么技术实现的??

  1. SSM项目

    Spring + Spring MVC + Mybatis(中期)

    Spring Boot + Spring web(Spring MVC)+ Mybatis(现在)

  2. SM项目

    Spring Boot(Spring web)+ Mybatis(现在)

  1. Spring MVC是一个Web框架
  2. Spring MVC是基于Servlet API构建的

MVC和Spring MVC的关系:

MVC是一种思想,而Spring MVC是对MVC思想的具体实现。

总结来说,Spring MVC是一个实现MVC模式,并继承了Servlet API的Web框架,既然是Web框架,那么当用户在浏览器输入url之后,我们的Spring MVC项目就可以感知到用户的请求。

现在绝大部分Java项目,都是基于Spring(或者Spring Boot)的,而Spring的核心就是Spring MVC。

Spring MVC是Spring框架的核心模块,Spring Boot是Spring的脚手架

怎么学Spring MVC?

学习Spring MVC我们只需要掌握以下3个功能:

  1. 连接的功能,将用户(浏览器)和Java程序连接起来,也就是访问一个地址能够调用到我们的Spring程序。
  2. 获取参数的功能,用户访问的时候会带一些参数,在程序中要想办法获取到。
  3. 输出数据的功能,执行了业务逻辑之后,要把程序执行的结果返回给用户。

对于Spring MVC来说,掌握了以上3个功能,就相当于掌握了Spring MVC。

创建Spring MVC项目:

在2018年之前,使用Maven项目添加Spring MVC框架的方式来进行创建(复杂,太麻烦),现在我们来使用Spring Boot来创建Spring MVC项目

创建的时候,选择lombok,Spring Web(可添加Spring MVC框架),Spring Boot DevTools(热部署)。

@RestController  //@RestController = @ResponseBody + @Controller
//通过注解
public class UserController {@RequestMapping("/say")  //一级路由,可设置多级路由public String sayHi(){return "hi Spring MVC";}
}

在上述代码中,我们使用了:   @RequestMapping("/say"),该注解支持GET,POST,PUT,DELETE等请求。

如下述仅支持POST类请求的代码:

    @RequestMapping(Value = "/sayhi", method = RequestMethod.POST)//这两个都可表示仅仅支持POST类请求:@PostMapper("/sayHello")public String sayHello() {return "hello Spring MVC ";}

如下述仅支持GET类请求的代码:

    @GetMapper("/hi")public String sayHello() {return "hi Spring MVC ";}

获取参数:

获取一个参数:

@RestController
public class UserController {@RequestMapping("/sayHi")public String sayHi(String name){return "hi " + name;}}

参数传递建议不要使用基础数据类型(容易报错),建议使用包装类

在浏览器输入:localhost:8080/sayHi?name=zhangsan(注意:参数名name一定要相同,否则会出错)

获取多个参数:

具体代码可参考获取一个参数的代码!

@RestController
public class UserController {@RequestMapping("/sayHi")public String sayHi(String name,String password){return "hi " + name +" " + password;}}

在浏览器输入:localhost:8080/sayHi?name=zhangsan&password=123456

获取对象:

首先,我们来自定义一个对象吧!

@Data  //@Data丰富java自动资源管理,自动生成getter、setter、equals、hashCode和toString等
public class Userinfo {private int id;private String name;private String password;private int age;
}

获取参数代码:

@RestController
public class UserController {@RequestMapping("/reg")public Object reg(Userinfo userinfo){  //框架会实现自动的参数映射System.out.println(userinfo);return userinfo;}}

在浏览器输入:localhost:8080/reg?name=zhangsan&password=123456&id=1&age=18(框架会实现自动的参数映射)

当然,也可以获取一个HTML标签:

获取一个HTML标签:

@RestController
public class UserController {@RequestMapping("/he")public Object getHe(){return "<h1>我是HTML中H1标签</h1>";//HTML的标签}}

在浏览器中输入:localhost:8080/he

后端参数重命名:

@RestController
public class UserController {@RequestMapping("/reg2")public Object reg(@RequestParam("username")String name,String password){//将前端传递来的名称(username)改为name(后端)//必传参数usernamereturn name+" "+password;}}

在上述代码中:

前端传递的参数username(必传参数)

后端使用的参数name

意思是:将前端传递来的参数username被后端更改为name

在浏览器中输入:localhost:8080/reg2?username=zhangsan&password=123456

在上述代码中:username属于必传参数,当然也可以变为非必传参数,如果不传的话,默认为null

@RestController
public class UserController {@RequestMapping("/reg2")public Object reg(@RequestParam(value = "username",required = false)String name,String password){//将前端传递来的名称(username)改为name(后端)//必传参数usernamereturn name+" "+password;}}

在浏览器中输入:localhost:8080/reg2?password=123456

获取JSON对象:

在这个操作中,我们来借助Postman来进行操作:

@RestController
public class UserController {@RequestMapping("/reg3")public Object reg3(@RequestBody  Userinfo userinfo){return userinfo;}
}

在Postman中,我们通过:Body——》raw——》JSON——》设置参数——》sign来进行操作:

所设置的参数为:

{"id":"1","name":"zhangsan","password":"123456","age":"18"}

运行程序,并点击sign后端的相应为:

从基础URL中获取参数:

从基础URL中获取参数(不是URL的参数部分的参数)

@RestController
public class UserController {@RequestMapping("/reg4/{name}/{password}")public Object reg4(@PathVariable String name,@PathVariable("password")String password){return "name = "+name+" | password ="+password;}}

在浏览器中输入:localhost:8080/reg4/zhangsan/123456(顺序需要一一对应)

当然,对于上述的必需参数,也可以更改为非必须参数:

@RestController
public class UserController {@RequestMapping("/reg4/{name}/{password}")public Object reg4(@PathVariable String name,@PathVariable(required = false,name = "password")String password){return "name = "+name+" | password ="+password;}}

那么,我们来看一下注解@PathVariable和注解@RequestParm吧!

  1. 注解@PathVariable:基础URL里面的参数(?之前的参数)
  2. 注解@RequestParm:URL参数部分的参数(?之后的参数)

http://localhost:8080/reg4?name=zhangsan&password=123456

获取上传图片:

@RestController
public class UserController {@RequestMapping("myupload")public Object upload(@RequestPart("mying")MultipartFile file){//@RequestPart("mying")拿到请求的文件,赋值给MultipartFile fileFile saveFile=new File("D:\\Data\\mying.png");//D:\Data\mying.png想要将请求的文件上传到的路径//mying.png上传后的文件名try {file.transferTo(saveFile);return true;//上传成功} catch (IOException e) {e.printStackTrace();}return false;//上传失败}}

本次也通过Postman来进行操作:

Boby,form-data,mying右侧选择file,mying.png

当然,在这个过程中,我们需要注意图片的大小,太大就容易上传失败(可以在配置文件中自行设置图片的最大范围)

spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB

最后的结果为:

那么,接下来又有个问题:

后面再次上传的图片会覆盖前面的图片,名称为:mying.png

因此,我们可以在获得的原文件名的后缀带有一个独一无二的UUID,那么这个问题不就解决了吗??

        String fileName= UUID.randomUUID()+ //文件名file.getOriginalFilename().substring(  //源文件进行分割file.getOriginalFilename().lastIndexOf(".")); //添加后缀File saveFile=new File("D:\\Data\\"+fileName);

通过上述的代码即可。

因此总的代码为:

@RestController
public class UserController {@RequestMapping("myupload")public Object upload(@RequestPart("mying")MultipartFile file){//@RequestPart("mying")拿到请求的文件,赋值给MultipartFile fileString fileName= UUID.randomUUID()+ //文件名file.getOriginalFilename().substring(  //源文件进行分割file.getOriginalFilename().lastIndexOf(".")); //添加后缀File saveFile=new File("D:\\Data\\"+fileName);//  File saveFile=new File("D:\\Data\\mying.png");//D:\Data\mying.png想要将请求的文件上传到的路径//mying.png上传后的文件名try {file.transferTo(saveFile);return true;//上传成功} catch (IOException e) {e.printStackTrace();}return false;//上传失败}}

当我们重新运行程序,再次上传图片的时候:

因此,这样才能多次获取新的图片,并且每次都能成功的保存下来!

获取Cookie

1.获取单个Cookie

@RestController
public class UserController {@RequestMapping("/getck")  //获取名称为java的Cookie,并赋值给javapublic Object getCk(@CookieValue(value ="java",required = false)String java){return java;}
}

2.获取所有Cookie

@RestController
public class UserController {@RequestMapping("/getck")public String getCk(HttpServletResponse response,HttpServletRequest request){String name=request.getParameter("name");//获取所有Cookie信息Cookie[] cookies=request.getCookies();return name+" 你好! ";}
}

获取Header中的某个信息:

@RestController
public class UserController {@RequestMapping("/gethd")public Object getHeader(@RequestHeader("User-Agent")String ua){return "header---->" + ua;}}

在浏览器中输入:http://localhost:8080/gethd

运行结果为:

获取Session:

在获取Session之前,一定要进行存储Session,才能进行获取,存Session没有捷径可走,不能通过注解的方式实现。

什么时候才会有Session的存储??只有当用户的用户名和密码都正确的情况下,才会存储Session。

在Servlet阶段,如何存储Session,那么,在现阶段也是如何存储Session的!!

@RestController
public class UserController {//定义全局变量private static final String SESSION_KEY="USERINFO_SESSION";//存储Session@RequestMapping("/setsess")public void setSess(HttpServletRequest request){HttpSession session=request.getSession();session.setAttribute(SESSION_KEY,"zhangsan");}//获取session@RequestMapping("/getsess")public Object getSession(@SessionAttribute(SESSION_KEY)String name){ //赋值给namereturn "session + "+name;}}

在浏览器中输入:http://localhost:8080/getsess

返回数据:

1.返回静态页面:

Java后端代码:

@Controller
@RequestMapping("/test")
public class TestController {@RequestMapping("/index")public Object getIndex(){return "/index.html"; //静态页面(VSCode)
//加个“/”(斜杠)表示从根路径取找index.html
//如果不加斜杠,则会404报错}
}

HTML静态页面代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>
<h1 style="color: red">我是 index.html</h1>
</body>
</html>

在浏览器输入:localhost:8080/test/index

请求转发和重定向:

请求转发和重定向:forward VS redirect

return不但可以返回一个视图,还可以实现跳转,跳转的方式有两个:

  1. forward :请求转发
  2. redirect :请求重定向

@Controller
@RequestMapping("/test")
public class TestController {//请求转发@RequestMapping("/fw")public String fw(){return "forward:/index.html";}//浏览器输入localhost:8080/test/fw//请求重定向@RequestMapping("/rd")public String rd(){return "redirect:/index.html";}//浏览器输入localhost:8080/test/rd会跳转到localhost:8080/index.html//请求重定向到百度《——》另一种写法@RequestMapping("/rd2")public void rd2(HttpServletResponse response) throws IOException{response.sendRedirect("https://www.baidu.com/");}//浏览器输入localhost:8080/test/rd2会跳转到百度}
  1. 浏览器输入localhost:8080/test/fw
  2. 浏览器输入localhost:8080/test/rd会跳转到localhost:8080/index.html
  3. 浏览器输入localhost:8080/test/rd2会跳转到百度

请求转发forward和请求重定向redirect的区别!!(面试题)

  1. 定义不同
  2. 跳转方不同
  3. 数据共享不同
  4. 最终URL不同
  5. 代码实现不同
  6. ……………………

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

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

相关文章

【nowcoder】BM3 链表中的节点每k个一组翻转

题目&#xff1a; 题目分析&#xff1a; 题目解析转载&#xff1a; 代码实现&#xff1a; package BMP3;import java.util.List;class ListNode {int val;ListNode next null;public ListNode(int val) {this.val val;} } public class BM3 {/*** 代码中的类名、方法名、参…

一般将来时

一般将来时 概念 表示将要发生的动作或打算、计划准备做某事 时间 tomorrow 明天 the day after tomorrow 后天 next week 下周 next weekend 下周末 next month 下个月 next year 明年 ...句子结构 主语 be&#xff08;am/is/are&#xff09;going to do … 计划,…

B树你需要了解一下

介绍B树的度数主要特点应用场景时间复杂度代码示例拓展 介绍 B树&#xff08;B-tree&#xff09;是一种自平衡的树&#xff0c;能够保持数据有序&#xff0c;常被用于数据库和文件系统的实现。 B树可以看作是一般化的二叉查找树&#xff0c;它允许拥有多于2个子节点。与自平衡…

2023.11.25 关于 MyBatis 的配置与使用

目录 引言 MyBatis 介绍 掌握两个点 在框架中的定位 创建数据库 配置 MyBatis 引入依赖 配置文件 创建实体类 构建 Mapper 层代码实现 添加 mapper 接口 添加 UserMapper.xml 实现 Service 层 实现 Controller 层 最终测验 阅读下面文章之前建议了解并创建…

树状数组专题

折叠 区间修改&#xff0c;区间查询&#xff0c;这一类题通常都可以使用线段树解决&#xff0c;但对于此题&#xff0c;树状数组同样可以&#xff0c;而且常数较小&#xff0c;代码简单。 思路&#xff1a; 考虑使用树状数组去维护差分数组&#xff0c;即对于 a i a_i ai​,我们…

使用qemu调试arm内核

参考书籍《奔跑吧Linux内核》–笨叔 下载Linux-5.0源码 https://benshushu.coding.net/public/runninglinuxkernel_5.0/runninglinuxkernel_5.0/git/files或者直接git源码 git clone https://e.coding.net/benshushu/runninglinuxkernel_5.0/runninglinuxkernel_5.0.git安装必…

【React】Memo

组件重新渲染时缓存计算的结果。 实例&#xff1a;count1计算斐波那契数列&#xff0c;count2和count1可以触发数值变化。使用memo可以使只有在count1变化时触发斐波那契数列计算函数&#xff0c;而count2变化时不触发斐波那契数列计算函数。 import { useMemo } from "r…

SpringCloud微服务网关Gateway:gateway基本实现、断言工厂、过滤器工厂、浏览器同源策略、跨域问题解决方案

Gateway网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0和Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API路由管理方式 为什么…

【面试题】介绍一下类加载过程,什么是双亲委派模型

背景 java 文件在运行之前&#xff0c;必须经过编译和类加载两个过程&#xff1a; 编译过程&#xff1a;把 .java 文件 编译成 .class 文件类加载过程&#xff1a;把 .class 文件加载到 JVM 内存里&#xff0c;加载完成后就会得到一个 class 对象&#xff0c;我们就可以使用 n…

Vue快速实践总结 · 上篇

文章目录 模板语法数据绑定事件处理计算属性监视属性&#xff08;监听器&#xff09;条件渲染列表渲染数据监视原理内置指令总结生命周期组件化编程组件使用步骤组件的嵌套this指向单文件组件ref、props 脚手架(Vue CLI)render函数 参考自己的Vue专栏以及Vue官方文档 模板语法 …

Java PriorityQueue

一般情况下, 我们使用队列是为了能够建造队列的先进先出 (First-In-First-Out) 模式的, 达到一种资源的公平分配, 先到达的任务 (元素) 先处理, 但有时需要在队列中基于优先级处理对象。 存入队列中的任务 (元素) 具有优先级, 需要根据优先级修复里面的数据。而在 JDK 1.5 引入…

Java 泛型知识总结

1、基础知识 泛型是 JDK5 引入的参数化类型特性&#xff0c;所谓参数化类型就是把类型当成参数一样传递&#xff0c;它使得一个类型在定义类、接口和方法时成为一个参数&#xff0c;类似于方法声明中的形式参数&#xff0c;不同之处在于形式参数的输入是值&#xff0c;而类型形…

微机原理_5

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 8086微处理器CLK引脚输入时钟信号是由(提供。 A. 8284 B. 8288 C.8287 D. 8289 2.下面4个寄存器中,不能作为间接寻址的寄存器是(…

Java + openCV更换证件照背景色

最近在小红书上看到很多更换证件照背景色的需求&#xff0c;联想到以前自己也更换过证件照背景色而且还是付费的&#xff0c;碰巧最近在看一本书《JavaOpenCV高效入门》&#xff0c;于是查找资料&#xff0c;找到了通过技术解决这个需求的办法。 先看效果图&#xff08;图片来自…

62 权限提升-烂土豆dll劫持引号路径服务权限

目录 演示案例:Win2012-烂士豆配合令牌窃取提权-Web权限Win2012-DLL劫持提权应用配合MSF-Web权限Win2012-不安全的服务权限配合MSF-本地权限Win2012-不带引号服务路径配合MSF-Web&#xff0c;本地权限补充说明: dll劫持提权及AlwaysInstallElevated等说明关于Windows相关知识点…

yo!这里是异常相关介绍

目录 前言 异常的概念 异常的抛出与捕获 捕获过程 重新抛出 规范 异常体系 自定义 标准库 异常的优缺点 后记 前言 对于程序运行时发生的错误&#xff0c;比如内存错误、除0错误等类型&#xff0c;你会如何处理&#xff1f;是使用assert终止程序或是使用exit返回错误…

Linux系统---僵尸进程、孤儿进程

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C/C》 键盘敲烂&#xff0c;年薪百万&#xff01; 有了上一篇博客的学习&#xff0c;我们已经简单了解了进程的基础知识&#xff0c;今天我们再来学习两个特殊的进程&#xff0c;僵尸进程和孤儿进程。 …

7000字详解 动态代理(JDK动态代理 CGLIB动态代理)与静态代理

代理模式 1. 代理模式 概念2. 静态代理3. 动态代理3.1.JDK动态代理3.2.CGLIB动态代理3.3. JDK动态代理和CGLIB动态代理区别 4.静态代理和动态代理区别5.篇末 1. 代理模式 概念 代理模式是一种设计模式。 使用代理对象来替代真实对象&#xff0c;用代理对象去访问目标对象。这样…

虚拟化逻辑架构: LBR 网桥基础管理

目录 一、理论 1.Linux Bridge 二、实验 1.LBR 网桥管理 三、问题 1.Linux虚拟交换机如何增删 一、理论 1.Linux Bridge Linux Bridge&#xff08;网桥&#xff09;是用纯软件实现的虚拟交换机&#xff0c;有着和物理交换机相同的功能&#xff0c;例如二层交换&#…

百面深度学习-自然语言处理

自然语言处理 神经机器翻译模型经历了哪些主要的结构变化&#xff1f;分别解决了哪些问题&#xff1f; 神经机器翻译&#xff08;Neural Machine Translation, NMT&#xff09;是一种使用深度学习技术来实现自动翻译的方法。自从提出以来&#xff0c;NMT模型经历了几个重要的…