Spring Web MVC起源

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

1.1 什么是 MVC?
Model View Controller(模型,视图,控制器),他是一种设计模式,这种设计模式将软件(项目)分为三部分: 模型,视图,控制器

MVC思想

springboot 获取 profile Springboot 获取页面转为图片_后端


MVC 是一种设计思想,而 SpringMVC 是一个 具体的实现框架.

SpringMVC 是一个 基于 MVC 设计模式 和 Servlet API 实现的 Web 框架,同时 SpringMVC 又是 Spring 框架中的一个 WEB 模块,他是随着 Spring 的诞生而存在的一个框架.
Spring 和 SpringMVC 诞生历史比较久远,在他们之后才有了 Spring boot.

SpringMVC流程

springboot 获取 profile Springboot 获取页面转为图片_spring boot_02

为什么需要这么多类注解?

  • 让代码的可读性更高,能够让程序员能够直观的判断当前类的用途

@Controller:表示的是业务逻辑层;
@Servie:服务层;
@Repository:持久层;
@Configuration:配置层;

springboot 获取 profile Springboot 获取页面转为图片_MVC_03

springboot 获取 profile Springboot 获取页面转为图片_spring_04

springboot 获取 profile Springboot 获取页面转为图片_spring_05


pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springboot_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>

    </dependencies>
</project>

UserController.java

package com.itterence.controller;

import com.itterence.model.UserInfo;
import lombok.extern.java.Log;
import lombok.extern.jbosslog.JBossLog;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;
import java.util.logging.Logger;

@Slf4j
@Controller
@ResponseBody // 表示的是返回一个非静态页面的数据
@RequestMapping("/user") //类上面的 RequestMapping 可以省略
public class UserController {

    @RequestMapping("/sayhi")
    public String sayHi(){
        return "Hello World!";
    }

    @RequestMapping("/login")
    public String login(String username,String password){
        return "用户名 : "+username +"密码 : " +password;
    }

    @RequestMapping("/getuserbyid")
    public UserInfo getUserById(Integer id){
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("张三");
        userInfo.setAge(18);
        return userInfo;
    }
    @RequestMapping("/getinfo/{id}/{name}")
    public String getInfo(@PathVariable Integer id,@PathVariable String name){
        return "ID: "+id+"| Name: "+name;
    }

    @RequestMapping("/upload")
    public boolean upload(Integer uid, @RequestPart("img")MultipartFile file){
        boolean result = false;
        try{
            file.transferTo(new File("C:\\Users\\U100926\\Desktop\\spt\\img.jpg"));
            result = true;
        }catch (IOException e){
            log.error("上传失败");
        }
        return result;
    }

    // 从配置文件中读取图片的保存路径
    @Value("${img.path}")
    private String imgPath;

    @RequestMapping("/upimg")
    public boolean upImg(Integer uid, @RequestPart("img") MultipartFile file) {
        boolean result = false;
        String fileName = file.getOriginalFilename(); // 得到原图片的名称(xxx.png)
        fileName = fileName.substring(fileName.lastIndexOf(".")); // 得到图片后缀(png)
        fileName = UUID.randomUUID().toString() + fileName;
        // 保存图片到本地目录
        try {
            file.transferTo(new File(imgPath + fileName));
            result = true;
        } catch (IOException e) {
            log.error("上传图片失败:" + e.getMessage());
        }
        return result;
    }

}

TestController.java

package com.itterence.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
//@ResponseBody
public class TestController {
    @RequestMapping("/hi")
    public String hii(){
        return "index.html";
    }
}

CalcController.java

package com.itterence.controller;

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

@RestController
public class CalcController {
    @RequestMapping("/calc")
    public String calc(Integer num1, Integer num2) {
        if (num1 == null || num2 == null) {
            return "<h1>参数错误</h1><a href = 'javascript:history.go(-1);'>返回</a>";
        }
        return "<h1>结果: " + (num1 + num2) + "</h1><a href = 'javascript:history.go(-1);'>返回</a>";
    }
}

HelloController.java

package com.itterence.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping("hello")
    public String helloo(){
        return "hello,springboot!";
    }
}

UserInfo.java

package com.itterence.model;

import lombok.Data;

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private int age;
}

Application.java

package com.itterence;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--彩色日志输出格式-->
    <property name="CONSOLE_LOG_PATTERN" value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%level){blue} %clr(${PID}){magenta} %clr([%thread]){orange} %clr(%logger){cyan} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <!--非彩色日志输出格式-->
    <property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />

    <!--dev文件路径:src同级目录logs,如果上级目录不存在会自动创建-->
    <property name="DEV_FILE_PATH" value="./logs" />
    <!-- pro文件路径 -->
    <property name="PRO_FILE_PATH" value="/opt/prod/logs" />

    <!-- 控制台输出 -->
    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- 按照每天生成输出日志文件 -->
    <appender name="fileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程,%-5level:级别从左显示五个字符宽度,%logger{36}:logger是class的全名,后面的数字代表限制最长的字符,%msg:日志消息,%n换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <!--滚动策略按照时间滚动-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily 文件名称 -->
            <fileNamePattern>${DEV_FILE_PATH}/output-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
            <!--单个文件大小-->
            <maxFileSize>10MB</maxFileSize>
            <!--日志文件保留天数-->
            <maxHistory>60</maxHistory>
            <!--用来指定日志文件的上限大小,到了这个值就会删除旧日志-->a
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <!-- 按照每天生成错误日志文件 -->
    <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
        <!--输出日志到src同级目录logs中的error.log文件中-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--基于大小和时间的轮转策略,当日志内容超出文件大小限制后,会自动生成一个文件来继续记录和重命名-->
            <fileNamePattern>${DEV_FILE_PATH}/error-%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- each file should be at most 10MB, keep 60 days worth of history, but at most 2GB -->
            <maxFileSize>10MB</maxFileSize>
            <maxHistory>60</maxHistory>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
    </appender>

    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="consoleAppender" />
            <appender-ref ref="fileAppender" />
            <appender-ref ref="errorAppender" />
        </root>
    </springProfile>

    <!--生产环境:输出到文件-->
    <springProfile name="pro">
        <!-- root日志以INFO级别输出,指定日志信息输出到哪个地方-->
        <root level="INFO">
            <appender-ref ref="consoleAppender" />
            <appender-ref ref="fileAppender" />
            <appender-ref ref="errorAppender" />
        </root>
    </springProfile>

</configuration>

calc.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/calc">
    <h1>计算器</h1>
    数字1 : <input name = "num1" type="text"><br>
    数字2 : <input name = "num2" type="text"><br>
    <input type="submit" value="点击相加">
</form>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: indianred">
    hello springMvc
</h1>
</body>
</html>

springboot 获取 profile Springboot 获取页面转为图片_java_06

springboot 获取 profile Springboot 获取页面转为图片_MVC_07


http://localhost:8080/calc.html

springboot 获取 profile Springboot 获取页面转为图片_java_08


http://localhost:8080/user/getuserbyid

springboot 获取 profile Springboot 获取页面转为图片_java_09


springboot 获取 profile Springboot 获取页面转为图片_spring_10

LoginController.java

package com.itterence.controller;

import com.itterence.model.UserInfo;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;


import java.util.HashMap;
@RestController
/*
或者这么写
@Controller
@ResponseBody // 表示的是返回一个非静态页面的数据
*/
public class LoginController {
    /**
     * 获取前端的 json 数据
     *
     * @param userInfo
     * @return
     */
    @RequestMapping("/login")
    public HashMap<String, Object> login(@RequestBody UserInfo userInfo) {
        HashMap<String, Object> result = new HashMap<String, Object>();
        int state = 200;
        int data = -1; // 等于 1,登录成功,否则登录失败
        String msg = "未知错误";
        if (StringUtils.hasLength(userInfo.getUsername()) && StringUtils.hasLength(userInfo.getPassword())) {
            if (userInfo.getUsername().equals("admin") && userInfo.getPassword().equals("admin")) {
                data = 1;
                msg = "";
            } else {
                msg = "用户名或密码失败!";
            }
        } else { // 参数为空
            msg = "非法参数";
        }
        result.put("state", state);
        result.put("data", data);
        result.put("msg", msg);
        return result;
    }

}
<!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>
        // ajax 提交
        function mysub(){
            // 1.判空
            var username = jQuery("#username");
            var password = jQuery("#password");
            if(jQuery.trim(username.val())==""){
                alert("请先输入用户名!");
                username.focus(); // 光标重制到此元素
                return;
            }
            if(jQuery.trim(password.val())==""){
                alert("请先输入密码!");
                password.focus(); // 光标重制到此元素
                return;
            }
            jQuery.ajax({
                url:"/login",
                type:"POST",
                contentType:"application/json",
                data:JSON.stringify({"username":username.val(),
                    "password":password.val()}),
                success:function(result){
                    alert(JSON.stringify(result));
                }
            });
        }
    </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>

http://localhost:8080/login.html

springboot 获取 profile Springboot 获取页面转为图片_spring boot_11


springboot 获取 profile Springboot 获取页面转为图片_后端_12


ForwardController.java

package com.itterence.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
//RestController不能用这个
public class ForwardController {
  @RequestMapping("/fw")
  public String myForward(){
      return "forward:/hello.html";
  }
    @RequestMapping("/fw1")
    public String myForward1(){
        return "hello.html";
    }
    @RequestMapping("/rd")
    public String myRedirect(){
      return "redirect:/hi.html";
    }
}

hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: indianred">
hello springmvc forward
</h1>
</body>
</html>

hi.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1 style="color: royalblue">
    hello springmvc redirect
</h1>
</body>
</html>

http://localhost:8080/fw

springboot 获取 profile Springboot 获取页面转为图片_MVC_13


http://localhost:8080/rd

springboot 获取 profile Springboot 获取页面转为图片_MVC_14