最后
文章中涉及到的知识点我都已经整理成了资料,录制了视频供大家下载学习,诚意满满,希望可以帮助在这个行业发展的朋友,在论坛博客等地方少花些时间找资料,把有限的时间,真正花在学习上,所以我把这些资料,分享出来。相信对于已经工作和遇到技术瓶颈的朋友们,在这份资料中一定都有你需要的内容。
我们去看一下SpringBoot对国际化的自动配置!这里又涉及到一个类:MessageSourceAutoConfiguration
里面有一个方法,这里发现SpringBoot已经自动配置好了管理我们国际化资源文件的组件 ResourceBundleMessageSource;
// 获取 properties 传递过来的值进行判断
@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;
}
我们真实的情况是放在了i18n目录下,所以我们要去配置这个messages的路径;
spring.messages.basename=i18n.login
配置页面国际化值
去页面获取国际化的值,查看Thymeleaf的文档,找到message取值操作为:#{…}。我们去页面测试下:
IDEA还有提示,非常智能的!
我们可以去启动项目,访问一下,发现已经自动识别为中文的了!
但是我们想要更好!可以根据按钮自动切换中文英文!
配置国际化解析
在Spring中有一个国际化的Locale (区域信息对象);里面有一个叫做LocaleResolver (获取区域信息对象)的解析器!
我们去我们webmvc自动配置文件,寻找一下!看到SpringBoot默认配置:
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = “spring.mvc”, name = “locale”)
public LocaleResolver localeResolver() {
// 容器中没有就自己配,有的话就用用户配置的
if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
}
// 接收头国际化分解
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
AcceptHeaderLocaleResolver 这个类中有一个方法
public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = this.getDefaultLocale();
// 默认的就是根据请求头带来的区域信息获取Locale进行国际化
if (defaultLocale != null && request.getHeader(“Accept-Language”) == null) {
return defaultLocale;
} else {
Locale requestLocale = request.getLocale();
List supportedLocales = this.getSupportedLocales();
if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
} else {
return defaultLocale != null ? defaultLocale : requestLocale;
}
} else {
return requestLocale;
}
}
}
那假如我们现在想点击链接让我们的国际化资源生效,就需要让我们自己的Locale生效!
我们去自己写一个自己的LocaleResolver,可以在链接上携带区域信息!
修改一下前端页面的跳转连接:
我们去写一个处理的组件类!
package com.kuang.component;
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 MyLocaleResolver implements LocaleResolver {
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request) {
String language = request.getParameter(“l”);
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 httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
为了让我们的区域化信息能够生效,我们需要再配置一下这个组件!在我们自己的MvcConofig下添加bean;
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
我们重启项目,来访问一下,发现点击按钮可以实现成功切换!搞定收工!
注意点
4.1、登录
禁用模板缓存
说明:页面存在缓存,所以我们需要禁用模板引擎的缓存
#禁用模板缓存
spring.thymeleaf.cache=false
模板引擎修改后,想要实时生效!页面修改完毕后,IDEA小技巧 : Ctrl + F9 重新编译!即可生效!
登录
我们这里就先不连接数据库了,输入任意用户名都可以登录成功!
1、我们把登录页面的表单提交地址写一个controller!
//这里面的所有表单标签都需要加上一个name属性
2、去编写对应的controller
@Controller
public class LoginController {
@RequestMapping(“/user/login”)
public String login(
@RequestParam(“username”) String username ,
@RequestParam(“password”) String password,
Model model){
//具体的业务
if(!StringUtils.isEmpty(username)&&“123456”.equals(password)){
return “redirect:/main.html”;
}
else{
//告诉用户,你登录失败
model.addAttribute(“msg”,“用户名或者密码错误!”);
return “index”;
}
}
}
OK ,测试登录成功!
3、登录失败的话,我们需要将后台信息输出到前台,可以在首页标题下面加上判断
重启登录失败测试:
优化,登录成功后,由于是转发,链接不变,我们可以重定向到首页!
4、我们再添加一个视图控制映射,在我们的自己的MyMvcConfifig中:
registry.addViewController(“/main.html”).setViewName(“dashboard”);
5、将 Controller 的代码改为重定向;
//登录成功!防止表单重复提交,我们重定向
return “redirect:/main.html”;
重启测试,重定向成功!后台主页正常显示!
4.2、登录拦截器
但是又发现新的问题,我们可以直接登录到后台主页,不用登录也可以实现!怎么处理这个问题呢?我
们可以使用拦截器机制,实现登录检查!
1、在LoginController添加serssion
session.setAttribute(“loginUser”,username);
2、自定义一个拦截器:
//自定义拦截器
public class LoginHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取 loginUser 信息进行判断
Object user = request.getSession().getAttribute(“loginUser”);
if(user == null){//未登录,返回登录页面
request.setAttribute(“msg”,“没有权限,请先登录”);
request.getRequestDispatcher(“/index.html”).forward(request,response);
return false;
}else{
//登录,放行
return true;
}
}
}
3、然后将拦截器注册到我们的SpringMVC配置类当中!
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,及拦截请求和要剔除哪些请求!
// 我们还需要过滤静态资源文件,否则样式显示不出来
registry.addInterceptor(new LoginHandlerInterceptor())
.addPathPatterns(“/**”)
.excludePathPatterns(“/index.html”,“/user/login”,“/”,“/css/*”,“/img/“,”/js/”);
}
4、我们然后在后台主页,获取用户登录的信息
[[ s e s s i o n . l o g i n U s e r ] ] < ! − − {session.loginUser}]] <!-- session.loginUser]]<!−−取EL表达式–>
然后我们登录测试拦截!完美!
5.1、员工列表页面跳转
我们在主页点击Customers,就显示列表页面;我们去修改下
1、将首页的侧边栏Customers改为员工管理
2、a链接添加请求
3、将list放在emp文件夹下
4、编写处理请求的controller
//员工列表
@Controller
public class EmployeeController {
@Autowired
EmployeeDao employeeDao;
@RequestMapping(“/emps”)
public String list(Model model){
Collection employees = employeeDao.getALL();
model.addAttribute(“emps”,employees);
return “emp/list”;
}
}
我们启动项目,测试一下看是否能够跳转,测试OK!我们只需要将数据渲染进去即可!
但是发现了一个问题,侧边栏和顶部都相同,我们是不是应该将它抽取出来呢?
5.2、Thymeleaf公共页面元素抽取
步骤:
1、抽取公共片段 th:fragment 定义模板名
2、引入公共片段 th:insert 插入模板名
实现:
1、我们来抽取一下,使用list列表做演示!我们要抽取头部nav标签,我们在dashboard中将nav部分定
义一个模板名;
-
2、然后我们在list页面中去引入,可以删掉原来的nav
3、启动再次测试,可以看到已经成功加载过来了!
说明:
除了使用insert插入,还可以使用replace替换,或者include包含,三种方式会有一些小区别,可以见名
知义;
我们使用replace替换,可以解决div多余的问题,可以查看thymeleaf的文档学习
侧边栏也是同理,当做练手,可以也同步一下!
定义模板:
然后我们在list页面中去引入:
启动再试试,看效果!
我们发现一个小问题,侧边栏激活的问题,它总是激活第一个;按理来说,这应该是动态的才对!
为了重用更清晰,我们建立一个commons文件夹,专门存放公共页面;
我们去页面中引入一下
我们先测试一下,保证所有的页面没有出问题!ok!
侧边栏激活问题:
1、将首页的超链接地址改到项目中
2、我们在a标签中加一个判断,使用class改变标签的值;
首页 (current)
员工管理
3、修改请求链接
4、我们刷新页面,去测试一下,OK,动态激活搞定!
5.3、员工信息页面展示
现在我们来遍历我们的员工信息!顺便美化一些页面,增加添加,修改,删除的按钮!
id lastName email gender department birth编辑
删除
OK,显示全部员工OK!
6.1、表单及细节处理
1、将添加员工信息改为超链接
添加员工
2、编写对应的controller
//to员工添加页面
@GetMapping(“/emp”)
public String toAddPage(){
return “emp/add”;
}
3、添加前端页面;复制list页面,修改即可
bootstrap官网文档 : https://v4.bootcss.com/docs/4.0/components/forms/
我们去可以里面找自己喜欢的样式!我这里给大家提供了编辑好的:
添加
4、部门信息下拉框应该选择的是我们提供的数据,所以我们要修改一下前端和后端
Controller
@GetMapping(“/emp”)
public String toAddPage(Model model){
//查询所有的部门信息
Collection departments = departmentDao.getDepartments();
model.addAttribute(“departments”,departments);
return “emp/add”;
}
前端
OK,修改了controller,重启项目测试!
6.2、具体添加功能
1、修改add页面form表单提交地址和方式
12、编写controller;
//员工添加功能
//接收前端传递的参数,自动封装成为对象[要求前端传递的参数名,和属性名一致]
@PostMapping (“/emp”)
public String addEmp(Employee employee){
//保存员工的信息
System.out.println(employee);
employeeDao.save(employee);
// 回到员工列表页面,可以使用redirect或者forward,就不会被视图解析器解析
return “redirect:/emps”;
}
回忆:重定向和转发以及 /的问题?
时间格式问题
生日我们提交的是一个日期 , 我们第一次使用的 / 正常提交成功了,后面使用 - 就错误了,所以这里面
应该存在一个日期格式化的问题;
SpringMVC会将页面提交的值转换为指定的类型,默认日期是按照 / 的方式提交 ; 比如将2019/01/01
转换为一个date对象。
那思考一个问题?我们能不能修改这个默认的格式呢?
这个在配置类中,所以我们可以自定义的去修改这个时间格式化问题,我们在我们的配置文件中修改一
下;
spring.mvc.date-format=yyyy-MM-dd
这样的话,我们现在就支持 - 的格式了,但是又不支持 / 了 , 2333吧
测试OK!
逻辑分析:
我们要实现员工修改功能,需要实现两步;
1、点击修改按钮,去到编辑页面,我们可以直接使用添加员工的页面实现
2、显示原数据,修改完毕后跳回列表页面!
实现
1、我们去实现一下,首先修改跳转链接的位置;
2、编写对应的controller
//员工修改页面
@GetMapping(“/emp/{id}”)
public String toUpdateEmp(@PathVariable(“id”) Integer id,Model model){
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute(“emp”,employee);
//查询所有的部门信息
Collection departments = departmentDao.getDepartments();
model.addAttribute(“departments”,departments);
return “emp/update”;
}
3、我们需要在这里将add页面复制一份,改为update页面;需要修改页面,将我们后台查询数据回显
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
逻辑分析:
我们要实现员工修改功能,需要实现两步;
1、点击修改按钮,去到编辑页面,我们可以直接使用添加员工的页面实现
2、显示原数据,修改完毕后跳回列表页面!
实现
1、我们去实现一下,首先修改跳转链接的位置;
2、编写对应的controller
//员工修改页面
@GetMapping(“/emp/{id}”)
public String toUpdateEmp(@PathVariable(“id”) Integer id,Model model){
Employee employee = employeeDao.getEmployeeById(id);
model.addAttribute(“emp”,employee);
//查询所有的部门信息
Collection departments = departmentDao.getDepartments();
model.addAttribute(“departments”,departments);
return “emp/update”;
}
3、我们需要在这里将add页面复制一份,改为update页面;需要修改页面,将我们后台查询数据回显
总结
大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。
麻烦帮忙转发一下这篇文章+关注我
[外链图片转存中…(img-nPIw8L53-1715694218777)]