ID | 姓名 | 邮箱 | 性别 | 部门 | 生日 | 操作 |
---|---|---|---|---|---|---|
注意:我们前面在public目录下放置了一个index.html的文件,所以默认访问的首页文件会是public目录下的index.html文件,那么我们需要访问template目录下的index.html文件,该怎么处理了?
我们可以在Controller中定义一个映射,跳转到index.html页面。
@RequestMapping({"/","/index.html"})
public String toIndex(){
return "index";
}
但是,我们仅仅是为了跳转一个页面,就写一个地址映射方法,有点麻烦
因为所有的WebMvcConfigurerAdapter组件都会一起起作用,所以我们可以定义一个WebMvcConfigurerAdapter,然后使用@Bean将该组件注册在容器中。
package com.bjc.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
/** 视图解析器 */
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// super.addViewControllers(registry);
// 浏览器发送 /bjc 请求,跳转到success页面
registry.addViewController("/bjc").setViewName("test");
}
public WebMvcConfigurerAdapter getWebMvcConfigurerAdapter(){
WebMvcConfigurerAdapter web = new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
};
return web;
}
}
这里咱们使用webjars引入bootstrap,在官网找到bootstrap的maven依赖,粘贴到pom.xml文件中
org.webjars
bootstrap
4.0.0
修改login.html的插件地址
操作步骤:
1)在resources目录下新建目录i18n
2)新建配置文件login.properties文件
3)新建login_zh_CN.properties文件,这时候idea工具会自动识别i18n目录为国际化目录,同时生成资源目录“Resource Bundle ‘login’”目录
4)鼠标右键该目录,新建英文版的配置文件,如图:
在弹窗中点击加号,如图:
在输入框中输入需要国际化的语言,例如,如图:
点击ok,如图:
点击ok,在i18n目录下就生成了一个新的文件login_en_US.properties,如图:
5)添加国际化内容
鼠标单击login.properties文件,点击Resource Bundle,如图:
再点击加号,如图:
在弹窗中输入关键信息,如图:
点击ok,然后输入提示信息,如图:
配置后最终效果如下:
在全局配置文件中配置如下代码
spring.messages.basename=i18n.login
原理:SpringBoot自动配置好了管理国家化资源文件的组件
@Conditional({MessageSourceAutoConfiguration.ResourceBundleCondition.class})
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
在MessageSourceAutoConfiguration.ResourceBundleCondition.class中有相关的配置,如图:
在该类中有个组件,用于设置国际化的基础路径
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
// 设置国际化基础名(去掉语言国家代码的)
messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if (properties.getEncoding() != null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if (cacheDuration != null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}
在thymeleaf模板文件中,获取国际化的内容可以通过#{}的方式来获取
现在的效果是:浏览器语言是中文就显示中文,浏览器语言是英文就显示英文
我们现在希望可以用户点击中文显示中文,点击英文显示英文。前面我们的国际化是根据浏览器语言来完成的国际化,该实现的原理是通过自动配置类获取浏览器请求头中的区域语言信息来设置的,现在我们根据这个原理,只需要让boot在加载的时候,使用我们自己的区域解析器即可。这里用到了两个类国际化Locale(区域信息对象)和LocaleResolver(获取区域信息对象)
Boot在WebMvcAutoConfiguration中定义区域解析器定义如下:
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
prefix = "spring.mvc",
name = {"locale"}
)
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
} else {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
}
该解析器有个注解@ConditionalOnMissingBean,表示容器不存在LocaleResolver的时候,才执行该代码,所以我们只需要将自定义的区域解析器注入到容器中即可。
操作步骤:
package com.bjc.commponent;
import lombok.val;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLoaderResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String code = request.getParameter("l");
Locale local = Locale.getDefault();
if(!StringUtils.isEmpty(code)){
String[] codes = code.split("_");
local = new Locale(codes[0],codes[1]);
}
return local;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
@Bean
public LocaleResolver localeResolver(){
return new MyLoaderResolver();
}
中文
English
package com.bjc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@PostMapping(value="/user/login")
public String login(Model model, String username, String password){
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password) && "123456".equals(password)){
return "dashboard";
}
model.addAttribute("errMsg","用户名或密码不正确!");
return "login";
}
}
spring.thymeleaf.cache=false
我们在前台可以正确的实现登录功能,但是,当页面登录成功之后,刷新,表单会重复提交,我们可以使用重定向的方式来防止表单重复提交。
@Controller
public class UserController {
@PostMapping(value="/user/login")
public String login(Model model, String username, String password){
if(!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password) && "123456".equals(password)){
// 登录成功,跳转到main.html页面,main.html添加了视图映射,最终会到dashboard.html
return "redirect:/main.html";
}
model.addAttribute("errMsg","用户名或密码不正确!");
return "login";
}
}
package com.bjc.intecepter;
import lombok.val;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInteceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object loginUser = request.getSession().getAttribute("loginUser");
if(null == loginUser){
//未登陆,返回登陆页面
request.setAttribute("errMsg","没有权限请先登陆!");
request.getRequestDispatcher("/index.html").forward(request,response);
return false;
}
return true;
}
}
在配置类中重写方法
public void addInterceptors(InterceptorRegistry registry) {
registry
.addInterceptor(new LoginInteceptor()) // 添加拦截器
.addPathPatterns("/**") // 指定拦截路径 /** 表示拦截所有请求
.excludePathPatterns("/index.html","/","/user/login","/asserts/**","/webjars/**"); // 指定不需要拦截的路径
}
完整的配置类
package com.bjc.config;
import com.bjc.commponent.MyLoaderResolver;
import com.bjc.intecepter.LoginInteceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MyMvcConfig extends WebMvcConfigurerAdapter {
/** 视图解析器 */
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// super.addViewControllers(registry);
// 浏览器发送 /bjc 请求,跳转到success页面
registry.addViewController("/bjc").setViewName("test");
}
@Bean
public WebMvcConfigurerAdapter getWebMvcConfigurerAdapter(){
/*WebMvcConfigurerAdapter web = new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
};*/
WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter(){
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry
.addInterceptor(new LoginInteceptor()) // 添加拦截器
.addPathPatterns("/**") // 指定拦截路径 /** 表示拦截所有请求
.excludePathPatterns("/index.html","/","/user/login","/asserts/**","/webjars/**"); // 指定不需要拦截的路径
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
registry.addViewController("/main.html").setViewName("dashboard");
}
};
return adapter;
}
@Bean
public LocaleResolver localeResolver(){
return new MyLoaderResolver();
}
}
@GetMapping("/emps")
public String list(Model model){
Collection all = employeeDao.getAll();
model.addAttribute("emps",all);
return "emp/list";
}
ID
姓名
邮箱
性别
部门
生日
操作
@GetMapping("/emp")
public String toAddEmp(Model model){
Collection deps = departmentDao.getDepartments();
model.addAttribute("deps",deps);
return "emp/add";
}
Dashboard Template for Bootstrap
@PostMapping("/emp")
public String save(Employee employee){
System.out.println(employee);
employeeDao.save(employee);
return "redirect:/emps";
}
注意:springboot中默认的日期格式是dd/mm/yyyy,我们需要更改我们自己的时间转换格式,只需要在application.properties配置文件中配置一下即可。
spring.mvc.format.date=yyyy-mm-dd
@GetMapping("/emp/{id}")
public String edit(@PathVariable("id") Integer id,Model model){
Employee employee = employeeDao.get(id);
model.addAttribute("emp",employee);
Collection deps = departmentDao.getDepartments();
model.addAttribute("deps",deps);
return "emp/add";
}
复用add.html页面做一些修改即可
注意:修改需要发送Put请求,但是form表单支持的提交方式只有get和POST两种方式,为此,我们需要更改提交方式
发送Put请求的操作步骤:
1)SpringMVC中配置HiddenHttpMethodFilter;(SpringBoot自动配置好的)
2)页面创建一个post表单
3)创建一个input项,name="_method";值就是我们指定的请求方式
例如:
完整的页面
Dashboard Template for Bootstrap
@PutMapping("/emp")
public String updateEmp(Employee employee){
employeeDao.save(employee);
return "redirect:/emps";
}
@DeleteMapping("/emp/{id}")
public String delEmp(@PathVariable("id") Integer id){
employeeDao.delete(id);
return "redirect:/emps";
}
1)修改删除按钮
2)添加form表单,修改请求方式为delete
3)js提交表单
注意:SpringBoot 2.x默认不支持==put,delete等请求方式的。所以,该请求会在后台打印如下信息
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'DELETE' not supported]
解决办法:启用hiddenMethod过滤器
# 启用hiddenMethod过滤器
spring.mvc.hiddenmethod.filter.enabled=true