👉 全文详细👈
下面内容有些简化的地方,因为上传文件不方便,请移步详细: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/