一:静态资源路径
首先我们要在项目中导入静态资源,但在导入之前我们需要知道项目中那些地方的资源才会被真正的访问。
找到我们的spring.factories文件,搜索webmvc相关。
点进去看源码,向下找到一个资源配置类。
继续深入后发现对方配置了如下几个扫描点:
classpath:/META-INF/resources/","classpath:/resources/", "classpath:/static/", "classpath:/public/
也就是说我们项目resources下指定文件夹里的内容都会被扫描到,优先级resources > static > public。
二:载入首页
因此,只要我们在这几个文件夹下的任意一个中放置index.html文件,进行访问的时候就会自动识别。
三:thymeleaf模板引擎
thymeleaf官方pdf:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.pdf
类似于jsp,模板引擎就是用来处理java数据和html页面内容转换的,springboot推荐的就是thymeleaf引擎,使用前需要导入依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
确认已经导入了3版本的引擎:
然后在templates文件夹下建立对应的文件:
Controller层:
访问:
同时thymeleaf也可以支持传参,语法是
th: 【参数名】=${key}
。
访问:
四:thymeleaf语法
- th:text="${msg}"展示元素,即便是标签也会转成字符串
- th:utext="${msg}"会将html标签转义并显示
- th:each=“user:${msg}” 循环,类似于vue的v-for
<!--写法一-->
<h1 th:each="user:${msg}" th:text="${user}"></h1>
<!--写法二-->
<h2 th:each="user:${msg}">[[ ${user} ]]</h2>
五:springmvc配置
springmvc内容在29.1.1小节:https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-developing-web-applications.html
我们来看一下springmvc的配置,它的配置可以写在config目录下。
配置信息:
package com.springboot.myweb.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/set").setViewName("test");
}
}
这里有点vue或者laravel路由的意思,addViewController("/set").setViewName(“test”);前一个路径是访问路径, 后一个是实际跳转到的模板路径。
这里还有一个需要在意的点已经体现在了官方文档上,也就是说配置文件上不可以加@EnableWebMvc注解。
原因是:@EnableWebMvc注解的源码中显示import了DelegatingWebMvcConfiguration.class,而这个类继承了WebMvcConfigurationSupport
但在webmvc的配置文件中,明确的提示了不能有WebMvcConfigurationSupport.class文件导入,否则该配置文件会被中断导入,从而导致许多功能失效。
六:模板导入
这里我采用的是x-admin模板:[http://x.xuebingsi.com/](http://x.xuebingsi.com/)
页面放在templates下,js,css等文件放在static文件夹下。
当然这时候有可能会遇到css,js文件导入失败的问题,这时候就需要引入thymeleaf的语法标准,在头部引入xmlns:th="http://www.thymeleaf.org约束。
然后url用th:href进行连接,/代表根目录,也就是static等放静态资源的目录。
而且因为我们的html文件都是放在templates文件夹下的,所以不能直接被项目读取到,因此我们在config下的Config文件中配置类似于路由的东西。
package com.springboot.myweb.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/admin").setViewName("admin-edit");
}
}
然后才能在浏览器上访问:
七:国际化
首选确定IDEA中setting的fileencoding都是utf8
然后在resources路径下建立i18n文件夹,i18n即国际化,在该文件夹先建立login.properties文件,然后建立login_zh_CN.properties,然后IDEA会默认将它们全都打包进同一个文件夹。
然后还可以新建en_US的properties文件。
以及对应的可视化预览。
进行配置。
然后在yaml中配置,默认的路径在spring.messages.basename下,配置我们的文件路径i18n.login。
根据thymeleaf官方文档,国际化的内容使用#{}配置。
在文件中配置。
<button class="layui-btn" lay-filter="save" lay-submit="" th:text="#{login.tips}">
</button>
于是前台出现。
当然最终要的还是要切换语言,但前提是我们有自己的配置文件,在config文件夹下添加如下配置文件
内容:
package com.springboot.myweb.config;
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;
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
//获取语言
String language = request.getParameter("lan");
Locale locale = Locale.getDefault();
//如果请求携带了国际化参数
if(!StringUtils.isEmpty(language)){
String[] split = language.split("_");
//国家地区
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
然后在MyMvcConfig中配置对应的bean:
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
前台添加如下:
<a th:href="@{/login(lan='zh_CN')}" th:text="中文"></a>
<a th:href="@{/login(lan='en_US')}" th:text="english"></a>
点击英文,url变化,语言变换
八:登录实现
登录实现的大体流程跟ssm流程类似,只需要将对应的页面设置好路由,以及将表单里的action修改陈th:action即可,url用模板引擎@{ }. 不过有一个可扩展的地方是th:if,即如果登录失败,将登录失败的信息动态的返回给页面,而页面接收也是有条件的,只有失败的时候才给提示,因此需要用到判断。
Controller:
package com.springboot.myweb.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.util.StringUtils;
@Controller
@RequestMapping("/login1")
public class LoginController {
@RequestMapping("/login1")
public String login1(@RequestParam String username, @RequestParam String password, Model model){
System.out.println(username+"username<<<");
if(!StringUtils.isEmpty(username) && password.equals("123456")){
return "index";
}else{
model.addAttribute("msg","用户名密码错误");
return "login";
}
}
}
前台提示:
判断返回的msg不为空才显示对应信息
<div style="text-align: center;color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></div>
这样一来登录失败给提示,成功进主页,但是如果真的成功了的话会发现我们输入的账号和密码都在url上显示,这显然不好,于是可以进一步修改。
MyMvcConfig.java文件中配置新路由:
registry.addViewController("/main.html").setViewName("index");
Controller修改:
@RequestMapping("/login1")
public String login1(@RequestParam String username, @RequestParam String password, Model model){
System.out.println(username+"username<<<");
if(!StringUtils.isEmpty(username) && password.equals("123456")){
return "redirect:/main.html";
}else{
model.addAttribute("msg","用户名密码错误");
return "login";
}
}
九:拦截器
在configer目录下建立对应的LoginHandlerInterceptor文件。
内容:
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取登录用户
Object loginUser = request.getSession().getAttribute("user");
if(loginUser==null){
request.setAttribute("msg","没有登录");
request.getRequestDispatcher("/").forward(request,response);
return false;
}else{
return true;
}
}
}
Controller:
@RequestMapping("/login1")
public String login1(@RequestParam String username, @RequestParam String password, Model model,HttpSession session){
if(!StringUtils.isEmpty(username) && password.equals("123456")){
session.setAttribute("user",username);
return "redirect:/main.html";
}else{
model.addAttribute("msg","用户名密码错误");
return "login";
}
}
MyMvcConfig文件:
addPathPatterns:配置要拦截的路径
excludePathPatterns:要放过的特殊路径
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/login1/login1","/css/**","/images/**","/js/**","/lib/**");
}
同样我们希望在登录以后右上角显示session里的名称。
html:
<a href="javascript:;">[[${session.user}]]</a>
十:fragment
这里的fragment就类似于mybatis中的sql片段,以及类似于vue的一些模板套用,用来解决代码重复度高的问题。 比如说这个模板有这样两个页面,它们的大体框架是相同的,而且重复的地方很多,于是就可以考虑写fragment。 与fragment有关的内容在官方文档4.5,语法介绍在第十节。
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#attribute-precedence
这里存在一端重复度很高的代码:
然后在另一个页面中insert引入,页面记得要有约束。
//~{这里是引用页面模板名称::这是定义的组件名}
<div th:insert="~{admin-list :: topshow}">...</div>
然后页面的内容仍然有效。
当然这是省事的写法,一般情况下这些重复的组件会被提取出来,然后放到一个专有的文件夹下,使用的时候直接从中引用。
以及一些额外的date转换,循环遍历之类的扩展内容也可以在官方文档中找到:
十一:404
在springboot中404页面只需要在templates文件夹下创建error文件夹, 然后写一个404.html文件,这样一来系统在找不到相应页面的时候就会访问这里的404页面。
资料参考:
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
https://space.bilibili.com/95256449?from=search&seid=4324821317013857560
https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/
http://x.xuebingsi.com/