Spring Boot 第四章 视图技术 / Swagger API 文档

11 篇文章 3 订阅
10 篇文章 11 订阅

👉 全文详细👈


下面内容有些简化的地方,因为上传文件不方便,请移步详细:http://wx0725.top/index.php/archives/508

终于到了大多数同学感兴趣的地方,终于不再面对黑乎乎的测试窗口了,开始试图学习。

功能简介:

  • 暂时这一章实现的目的是一个登录界面,并且点击登录之后可以跳转到一个欢迎界面,没有登录验证。

  • 国际化:支持语言切换功能。

  • swagger依赖,API文档生成,一个插件,支持自动生成文档、还可以在线测试你的接口。方便得很。

模板标签相关介绍:

  • th:insert 插入,将置顶的片段插入一个HTML标签“内”,会替换掉标签内已有的内容。

  • th:replace 替换,直接将片段替换当前标签。会替换掉标签内已有的内容。

  • th:include 导入,将指定片段“内”的内容插入当前标签内。会替换掉标签内已有的内容。

  • th:href、th:src 标签内属性,使用@{}标识符,访问static目录下静态资源、@{/css/style.css},同样以/开头访问控制器。为什么都是/开头呢,根目录到底是谁,其实这个你把项目编译成jar或者war包之后,查看包结构大概就能理解,不要被表面的文件夹结构诱导。底层机制还待学习。

  • [[ m s g ] ] 标 签 内 容 文 本 , {msg}]] 标签内容文本, msg]]msg 为后台定义的属性值。

  • th:text 标签内属性值,#{page.title} 引入配置文件中的属性值。

  • template::footer 在 th:insert 类似的之中引入 template 域中的 footer 片段。

  • @{/login(language=‘en_US’)} 将language使用get方式传参。

  • 变量表达式
    选择变量表达式
    消息表达式
    连接URL表达式
    片段表达式
  • 等等吧。要学的东西太多了,只能日积月累了。下面代码其实也不多,但是知识点还是挺过的,代码也可以不断的优化,创新,将已知和未知相结合。

代码:

  • 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>wx0725.top</groupId>
    <artifactId>visualization</artifactId>
    <version>1.0.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- Spring Boot提供的配置处理器依赖,代码提示 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--        web 开发场景-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--        热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

        <!--        lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--        可视化接口API-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.4.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.4.0</version>
        </dependency>

        <!--    静态模板依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>
</project>
  • application.properties
server.port=8082
server.tomcat.uri-encoding=UTF-8
spring.application.name=visualization

# 模板基本
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=utf-8
spring.thymeleaf.mode=HTML5
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.servlet.content-type=text/html


# 配置国际化文件基础名
spring.messages.basename=wx0725.language.page
  • login.java
    登录控制器、检查转发、显示简单的首页、简单的传参
package wx0725.top.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.Calendar;

/**
 * @author WEN
 * @version 1.0
 * @description: Wen Xuan
 * @date 2021/3/26 下午 18:04
 * @link http://wx0725.top
 */

@Api(tags = {"Login 测试接口"})
@Controller
@EnableSwagger2
public class Login {

    /**
     * 获取登录界面
     * @param model
     * @return
     */
    @GetMapping(value = "/login")
    public String toLogin(Model model) {
        model = this.foot(model);
        model.addAttribute("msg", "请输入用户名/密码");
        return "login";
    }

    /**
     * 访问首页 返回index域
     * @return
     */
    @GetMapping({"/", "/index"})
    public String index() {
        return "index";
    }

    /**
     * 检查登录信息
     * @param model
     * @param username
     * @param password
     * @return
     */

    @PostMapping(value = "/loginCheck")
    @ApiResponses({@ApiResponse(code = 200, message = "OK")})
    public String toLoginCheck(Model model, @RequestParam(value = "username") String username, @RequestParam(value = "password") String password) {
        model = this.foot(model);
        if (username != null && password != null) {
            model.addAttribute("username", username);
            return "index";
        } else {
            model.addAttribute("msg", "登录失败┭┮﹏┭┮");
            return "login";
        }
    }

    //    设置底部版权时间
    public Model foot(Model model) {
        model.addAttribute("currentYear", Calendar.getInstance().get(Calendar.YEAR));
        return model;
    }
}
  • MyLocalResovel.java
    定制区域信息解析器:该类会继承解析器,通过自定义的解析分割请求头,来切换当前的语言配置的文件。
package wx0725.top.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * @author WEN
 * @version 1.0
 * @description: Wen Xuan
 * @date 2021/3/26 下午 21:24
 * @link http://wx0725.top
 */

@Configuration
public class MyLocalResovel implements LocaleResolver {
    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String language = request.getParameter("language");
        String header = request.getHeader("Accept-language");
        Locale locale = null;
        if (!StringUtils.isEmpty(language)) {
            String[] strings = language.split("_");
            locale = new Locale(strings[0], strings[1]);
        } else {
            String[] strings = header.split(",");
            String[] string = strings[0].split("-");
            locale = new Locale(string[0], string[1]);
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {

    }

    @Bean
    public LocaleResolver localeResolver() {
        return new MyLocalResovel();
    }
}
  • SwaggerConfig.java
    API文档配置
package wx0725.top.config;

import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author WEN
 * @version 1.0
 * @description: Wen Xuan
 * @date 2021/3/27 下午 22:15
 * @link http://wx0725.top
 */
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket webApiConfig() {

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("Api")
                .apiInfo(webApiInfo())
                .select()
                .paths(Predicates.not(PathSelectors.regex("/admin/.*")))
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build();
    }

    private ApiInfo webApiInfo() {

        return new ApiInfoBuilder()
                .title("swagger效果演示文档")
                .description("测试")
                .version("1.1")
                .contact(new Contact("流星蝴蝶没有剑", "http://wx0725.top", "2659098658@qq.com"))
                .build();
    }
}
  • page.properties
page.login.title=登录界面
page.login.tip=请登录
page.login.username=用户名
page.login.password=密码
page.login.rememberme=记住我
page.login.button=登录
  • page_en_US.properties
page.login.title=login Page
page.login.tip=Please log in
page.login.username=The user name
page.login.password=The password
page.login.rememberme=Remember me
page.login.button=Login
  • page_zh_CN.properties
page.login.title=登录界面
page.login.tip=请登录
page.login.username=用户名
page.login.password=密码
page.login.rememberme=记住我
page.login.button=登录
  • template.html 定义一个模板页面,也是为了测试模板的标签
    个人在第一次使用的时候是按照微信小程序模板来学习的,其实“表面”理解是一样的。
<!-- 待引用的模板 -->
<template xmlns:th = "http://www.thymeleaf.org">

    <!--顶部共有meta-->
    <head th:fragment = "meta">
        <meta http-equiv = "Content-Type" content = "text/html;charset=UTF-8">
        <meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1">
        <meta name = "viewport"
              content = "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
        <meta charset = "UTF-8">
        <link th:href = "@{/css/bootstrap.min.css}" rel = "stylesheet" />
    </head>

    <!--底部模板-->
    <footer th:fragment = "footer" class = "col-md-12 footer">
        <div>
            <p class = "mt-5 mb-3">
                © <span th:text = "${currentYear}"></span>
                -<span th:text = "${currentYear}+1"></span>
            </p>
        </div>
        <script th:src = "@{/js/jquery.min.js}"></script>
        <script th:src = "@{/js/bootstrap.min.js}"></script>
    </footer>
</template>
  • login.html
    可以看注释
<!DOCTYPE html>
<html lang = "en" xmlns:th = "http://www.thymeleaf.org">
    <head th:replace = "template::meta">
    </head>
    <!--    需要下载下面,不然会被替换。 -->
    <title th:text = "#{page.login.title}"></title>
    <!--        自定义样式-->
    <link th:href = "@{/css/login.css}" rel = "stylesheet">

    <body>
        <div class = "container text-center">
            <div class = "col-md-1"></div>
            <form class = "form col-md-10 center-block" action = "/loginCheck" method = "post">
                <div class = "row text-center">
                    <img class = "col-md-2" th:src = "@{/img/login.png}" width = "72" height = "72">
                </div>
                <h1 class = "col-md-12" th:text = "#{page.login.tip}"></h1>
                <small>[[${msg}]]</small>
                <label for = "username" th:text = "#{page.login.username}"></label>
                <input name = "username" id = "username" type = "text" class = "form-control"
                       th:placeholder = "#{page.login.username}" required = "" autofocus = "">

                <label for = "password" th:text = "#{page.login.password}"></label>
                <input name = "password" id = "password" type = "password" class = "form-control"
                       th:placeholder = "#{page.login.password}" required = "">
                <div class = "checkbox mb-3">
                    <label>
                        <input type = "checkbox" value = "remember-me">
                        [[#{page.login.rememberme}]]
                    </label>
                </div>
                <button class = "btn btn-lg btn-primary btn-block" type = "submit" th:text = "#{page.login.button}">
                    登录
                </button>
                <div>
                    <a class = "btn btn-sm" th:href = "@{/login(language='zh_CN')}">中文</a>
                    <a class = "btn btn-sm" th:href = "@{/login(language='en_US')}">English</a>
                </div>
            </form>
            <!--  footer 片段包含-->
            <div th:insert = "template::footer"></div>
        </div>
    </body>

</html>
  • index.html
<!DOCTYPE html>
<html lang = "en" xmlns:th = "http://www.thymeleaf.org">
    <head th:replace="template::meta">
    </head>
    <title>首页</title>
    <body>
        <h1>Spring Boot 欢迎 <small th:text = "${username}"></small> 入坑成功!</h1>
        <div th:insert = "template::footer"></div>
    </body>
</html>
  • bootstrap.min.css
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
  • bootstrap.min.js \ jquery.min.js
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
  • font
https://static.runoob.com/assets/font-awesome/4.7.0/fonts/fontawesome-webfont.woff2?v=4.7.0
https://cdn.staticfile.org/twitter-bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff

如果您的理解能力还可以,实现到此处您可能也大致了解了前后台交互的一个方式,个人觉得自己还是入门较快,因为两年前学“了”Javaweb,只不过是把基本结构框架化,习惯就好。

有待学习

  • Spring Boot 框架,在后台实现页面跳转、转发的实现?
  • 传递参数直接映射实体?
  • 为什么自定义的区域信息解析类会被访问两次?
  • 框架内区域信息解析器如何实现访问的?
  • 模板在导入的时候如何将片段插入但是仍然保存现存的片段?
  • 有没有一个依赖可以自动识别当前项目没有用到的依赖,忽略这个依赖的加载?

因为在博客还需要上传挺费事,源码在站点发布了:http://wx0725.top/index.php/archives/508/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流星蝴蝶没有剑

篮球弹弹弹

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值