SpringMVC程序开发

本文详细介绍了SpringMVC框架的基本概念,包括MVC模式的原理、如何在SpringMVC中实现连接、参数获取和数据输出,以及通过实例演示了计算器和登录功能。重点讲解了@RequestMapping注解、GET/POST请求、参数处理和返回数据的多种形式。
摘要由CSDN通过智能技术生成

1.什么是 Spring MVC?

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

从上述定义我们可以得出两个关键信息

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

1.1 MVC的定义

MVC 是 Model View Controller 的缩写,它是软件工程中的⼀种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。
在这里插入图片描述

  • Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。
  • View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。
  • Controller(控制器)是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。

1.2 MVC和Spring MVC的关系

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

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

2. 怎么学 Spring MVC?

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

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

2.1 Spring MVC 创建和连接

2.1.1 @RequestMapping 注解介绍

@RequestMapping是 Spring Web应用程序中最常被用到的注解之一,它是用来注册接口的路由映射的。

基础使用:
@RequestMapping 即可修饰类,也可以修饰方法,当修饰类和方法时,访问的地址是类 + 方法。
@RequestMapping 也可以直接修饰方法。

注意:@RequestMapping 默认是 get 方式的请求

import com.example.demo.model.Person;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@ResponseBody // 定义返回的数据格式为⾮视图(text/html)
@RequestMapping("/p")
public class PersonController {
    @RequestMapping("/index")
    public Object index(Person person){
        // 获取参数
        System.out.println(person.getName() +":"+
                person.getPassword());
        // 执⾏业务...
        return "/index.html";
    }
}

2.1.2 @GetMapping 和 PostMapping

@GetMapping 和 PostMapping只支持修饰方法,不能修饰类。

get 请求的 3 种写法:

// 写法1
@RequestMapping("/index")
// 写法2
@RequestMapping(value = "/index",method = RequestMethod.GET)
// 写法3
@GetMapping("/index")

post 请求的 2 种写法:

// 写法1
@RequestMapping(value = "/index",method = RequestMethod.POST)
// 写法2
@PostMapping("/index")

2.2 获取参数

2.2.1 传递单个参数

在 Spring MVC 中可以直接用方法中的参数来实现传参,比如以下代码:

@RequestMapping("/m1")
public Object method_1(String name){
    System.out.println("参数 name:"+name);
    return "/index.html";
}

2.2.2 传递多个参数(非对象)

@RequestMapping("/m3")
public Object method_3(String name, String pwd) {
    System.out.println("name 参数:" + name);
    System.out.println("pwd 参数:" + pwd);
    return "/index.html";
}

重要说明:当有多个参数时,前后端进行参数匹配时,是以参数的名称进行匹配的,因此参数的位置是不影响后端获取参数的结果。

2.2.3 传递对象

并且Spring MVC可以自动实现参数对象的赋值,比如Person对象:

import lombok.Data;

@Data
public class Person {
    private int id;
    private String name;
    private String password;
}

传递对象代码实现:

@RequestMapping("/m2")
public Object method_2(Person p){
    System.out.println("对象中的 name:"+p.getName());
    System.out.println("对象中的 password:"+p.getPassword());
    return "/index.html";
}

2.2.4 后端参数重命名(后端参数映射)

某些特殊的情况下,前端传递的参数key和我们后端接收的key可以不一致,比如前端传递了一个time给后端,而后端又是有createtime字段来接收的,这样就会出现参数接收不到的情况,如果出现这种情况,我们就可以使用@RequestParam来重命名前后端的参数值。

具体示例如下,后端实现代码︰

@RequestMapping("/m4")
public Object method_4(@RequestParam("time") String createtime) {
    System.out.println("时间:" + createtime);
    return "/index.html";
}

2.2.5 设置参数必传@RequestParam

RequestParam既能重命名请求参数,又能保证此参数为必传参数。

上面的列子,如果我们是前端传递一个非time的参数,就会出现程序报错的情况,如下图所示:
在这里插入图片描述
这是因为后端已经声明了前端必须传递一个time的参数,但是前端没有给后端传递,我们查看@RequestParam注解的实现细节就可以发现端倪,注解实现如下:
在这里插入图片描述
非必传参数设置

表示当前的参数为非必传参数,如果不设置此属性,那么它的默认值为true,也就是此参数为必传项(如果不传就会报错)。

如果我们的实际业务前端的参数是一个非必传的参数,我们可以通过设置@RequestParam中的required=false 来避免不传递时报错,具体实现如下:

@RequestMapping("/m4")
public Object method_4(@RequestParam(value = "time", required = false) String createtime) {
    System.out.println("时间:" + createtime);
    return "/index.html";
}

2.2.6 @RequestBody 接收JSON对象

后端实现代码:

@RequestMapping(value = "/m5", method = RequestMethod.POST)
public Object method_5(@RequestBody Person person) {
    System.out.println("Person:" + person);
    return "redirect:/index.html";
}

2.2.7 获取URL中参数@PathVariable

@PostMapping("/m6/{name}/{password}")
public Object method_6(@PathVariable String name, @PathVariable String 
password) {
    System.out.println("name:" + name);
    System.out.println("password:" + password);
    return "redirect:/index.html";
}

前端方法地址:
在这里插入图片描述

注意事项:@PostMapping(“/m6/{name}/{password}”) 中的 {password} 参数不能省略。

2.2.8 上传文件@RequestPart

上传文件目录一般在.properties文件中配置,确定保存路径

upload.path=D:\logs
    @Value("${upload.path}")
    private String uploadPath;
    @RequestMapping("/file")
    public String upload(@RequestPart("myfile") MultipartFile file) throws IOException {
        // 1.上传文件目录(从配置文件中读取)
        String basePath = uploadPath;
        // 2.生成动态的文件名(包含后缀) xxx.jpg
        String fileName = UUID.randomUUID() +
                (file.getOriginalFilename().substring(
                        file.getOriginalFilename().lastIndexOf(".")));
        // 保存文件
        file.transferTo(new File(basePath + fileName));
        return "上传成功";
    }  

或者

@RequestMapping("/param9")
public String param9(String name, @RequestPart("myfile") MultipartFile 
file) throws IOException {
    // 获取⽂件后缀名
    String fileName = 
file.getOriginalFilename().substring(file.getOriginalFilename().lastIndex
Of("."));
    // ⽂件保存地址
    String filePath = ClassUtils.getDefaultClassLoader().getResource("static").getPath() +
         "/" + UUID.randomUUID() + fileName; //项目打包后在target中的static路径
    // 保存⽂件
    file.transferTo(new File(filePath));
    //file.transferTo(new File("D:\\log\\test.jpg"));
    return filePath + " 上传成功.";
}

在这里插入图片描述

2.2.9 获取Cookie/Session/header

使用 Request 获取所有Cookies

@RequestMapping("/param10")
public String param10(HttpServletRequest request) {
    String name = request.getParameter("name");
    // 获取所有 cookie 信息
    Cookie[] cookies = request.getCookies();
    return name + " 你好.";
}

简洁的获取 Cookie—@CookieValue

@RequestMapping("/cookie")
@ResponseBody
public String cookie(@CookieValue("bite") String bite) {
    return "cookie:" + bite;
}

Session 的存储
Session 存储和 Servlet 类似,是使用 HttpServletRequest 中获取的,如下代码所示:

@RequestMapping("/setsess")
@ResponseBody
public String setsess(HttpServletRequest request) {
    // 获取 HttpSession 对象,参数设置为 true 表示如果没有 session 对象就创建⼀个session
    HttpSession session = request.getSession(true);
    if(session!=null){
        session.setAttribute("username","java");
    }
    return "session 存储成功";
}

简洁获取 Session —@SessionAttribute

@RequestMapping("/sess2")
@ResponseBody
public String sess2(@SessionAttribute(value="username",required = false) String username) {
//required设置为false,即使没有从request中获取到就忽略跳过,赋值为null,防止没有相关key值,默认必传而报错;
    return "username:"+username;
}

简洁获取 Header—@RequestHeader

@RequestMapping("/header")
@ResponseBody
public String header(@RequestHeader("User-Agent") String userAgent) {
    return "userAgent:"+userAgent;
}

2.3 返回数据

2.3.1 返回 text/html

@RequestMapping("/m7")
@ResponseBody
public String method_7() {
    return "<h1>Hello,HTML~</h1>";
}

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

练习:实现计算器功能。

可使用 postman 传递参数,或使用 form 表单的⽅式提交参数。

前端代码:

<html>
<head>
    <meta charset="utf8">
</head>
<body>
<h1>计算器</h1>
<form action="http://localhost:8080/calc/sum">
    数字1:<input type="text" name="num1">
    <p></p>
    数字2:<input type="text" name="num2">
    <p></p>
    <input type="submit" value=" 计 算 ">
</form>
</body>
</html>

controller 代码:

package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/calc")
public class Calc {
    @RequestMapping("/sum")
    public String sum(Integer num1, Integer num2) {
        return "<h1>结果:" + (num1 + num2) + "</h1><br><a href='javascript:history.go(-1);'>返回上一步</a>";
    }
}

2.3.2 返回 JSON 对象

@RequestMapping("/m8")
@ResponseBody
public HashMap<String, String> method_8() {
    HashMap<String, String> map = new HashMap<>();
    map.put("Java", "Java Value");
    map.put("MySQL", "MySQL Value");
    map.put("Redis", "Redis Value");
    return map;
}

在这里插入图片描述

在这里插入图片描述

练习:实现登录功能。

前端使用jQuery.getJSON("", {}, function(data){});发送ajax请求。
在这里插入图片描述
在这里插入图片描述
前端:

<script>
    function mysub(){
        // 1.得到用户名和密码控件
        var username = jQuery("#username");
        var password = jQuery("#password");
        // 2. 非空效验
        if(jQuery.trim(username.val())==""){
            alert("请先输入用户名!");
            username.focus(); // 光标设置到用户输入框
            return;
        }
        if(jQuery.trim(password.val())==""){
            alert("请先输入密码!");
            password.focus(); // 光标设置到用户输入框
            return;
        }
        // 3.发起 ajax 和后端进行交互
        jQuery.getJSON("/user/login",
        {
            "username":jQuery.trim(username.val()),
            "password":jQuery.trim(password.val())
        },
        function(data){
            if(data!=null && data.succ==200){ // 后端成功返回结果了
             if(data.state==1){
                 alert("登录成功");
                 // 跳转到列表页
                 location.href='http://127.0.0.1:8080/blog_list.html';
             }else{
                 alert(data.msg);
             }
            }else{
                alert("接口访问失败!");
            }
        });
    }
</script>

前端代码:

<!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">
    <script src="js/jquery-1.9.1.min.js"></script>
    <title>Document</title>
    <script>
        function mysub() {
            var username = jQuery("#username").val();
            var password = jQuery("#password").val();
            jQuery.getJSON("/user/login",
                {
                    "username":username,
                    "password":password
                },
                function (result) {
                if(result.succ==200){
                    alert("返回结果:"+result.msg);
                }else{
                    alert("操作失败,请重试。");
                }
            });
        }
    </script>
</head>
<body>
    <div style="text-align: center;">
        <h1>登录</h1>
        ⽤户:<input id="username">
        <br>
        密码:<input id="password" type="password">
        <br>
        <input type="button" value=" 提交 " onclick="mysub()" 
style="margin-top: 20px;margin-left: 50px;">
    </div>
</body>
</html>

controller 代码:

@RequestMapping(value = "/login")
    @ResponseBody
    public HashMap<String,Object> login(String username, String password)
{
        HashMap<String,Object> res = new HashMap<>();
        int succ = 200;
        if(username!=null && password!=null &&
        username.equals("admin") && password.equals("admin")){
            res.put("msg","登录成功");
        }else{
            res.put("msg","登录失败");
        }
        res.put("succ",succ);
        return res;
    }

2.3.3 转发或请求重定向

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

  • forward: 是请求转发;
  • redirect:请求重定向。

请求转发和重定向的使用对比:

// 请求重定向
@RequestMapping("/index")
public String index(){
    return "redirect:/index.html";
}
// 请求转发
@RequestMapping("/index2")
public String index2(){
    return "forward:/index.html";
}

forward和redirect具体区别如下︰

  1. 请求重定向(redirect)将请求重新定位到资源﹔请求转发(forward)服务器端转发。
  2. 请求重定向地址发生变化,请求转发地址不发生变化。
  3. 请求重定向与直接访问新地址效果一直,不存在原来的外部资源不能访问;请求转发服务器端转发有可能造成原外部资源不能访问。

注意:请求转发如果资源和转发的页面不在一个目录下,会导致外部资源不可访问。

2.3.4 @ResponseBody 说明

@ResponseBody返回的值如果是字符会转换成text/html,如果返回的是对象会转换成application/json返回给前端。

@ResponseBody可以用来修饰方法或者是修饰类,修饰类表示类中的所有方法都会返回html或者json,而不是视图。

2.3.5 组合注解:@RestController

@RestController = @Controller +@ResponseBody

查看更多注解:
官方 API:https://docs.spring.io/spring-
framework/docs/current/reference/html/web.html#mvc-ann-requestmapping

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值