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(后端)
        //必传参数username
        return 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(后端)
        //必传参数username
        return 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 file
        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;//上传失败
    }

}

本次也通过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 file

        String 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,并赋值给java
    public 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){ //赋值给name
        return "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会跳转到百度

    }

复制代码
浏览器输入localhost:8080/test/fw
复制代码
浏览器输入localhost:8080/test/rd会跳转到localhost:8080/index.html
复制代码
浏览器输入localhost:8080/test/rd2会跳转到百度

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

  1. 定义不同
  2. 跳转方不同
  3. 数据共享不同
  4. 最终URL不同
  5. 代码实现不同
  6. ........................
相关推荐
hqxstudying12 分钟前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·21 分钟前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
春生野草40 分钟前
关于SpringMVC的整理
spring
Bug退退退1231 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠1 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
Zz_waiting.2 小时前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象
全栈凯哥2 小时前
02.SpringBoot常用Utils工具类详解
java·spring boot·后端
兮动人2 小时前
获取终端外网IP地址
java·网络·网络协议·tcp/ip·获取终端外网ip地址
呆呆的小鳄鱼2 小时前
cin,cin.get()等异同点[面试题系列]
java·算法·面试
独立开阀者_FwtCoder2 小时前
"页面白屏了?别慌!前端工程师必备的排查技巧和面试攻略"
java·前端·javascript