目標:開發一個spingboot的web項目,項目地址:點我
首先導入實體類和dao層,然後導入靜態資源到static文件夾下,頁面放入templates文件夾下,項目目錄如下所示
1. 默認訪問首頁
我們想將login.html作爲默認的首頁,有兩種方法
- 在控制類中使用
RequestMapping("/login")
構建視圖映射 - 在配置類中添加視圖控制器從而構建視圖映射,springboot主要採取這種方法
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/santiago").setViewName("success");
}
//所有WebMvcConfigurer會一起起作用
@Bean //將組件註冊在容器中
public WebMvcConfigurer webMvcConfigurer(){
WebMvcConfigurer adapter = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
}
};
return adapter;
}
}
然後配置login.html,使用thymeleaf語法
2. 國際化
如果在SpringMVC中要使用國際化,需要以下3步:
- 編寫國際化配置文件
- 使用ResourceBundleMessageSource管理國際化資源文件
- 在頁面使用fmt:message取出國際化內容
在SpringBoot中,步驟就簡單多了
2.1 編寫國際化配置文件
在resources根目錄下新建一個文件夾i18n,在裏面建立三個文件login.properties、login_zh_CN.properties、login_en_US.properties,分別代表默認,中文,英文顯示的login頁面。
接下來根據login頁面中的元素,編寫國際化文件
打開login_en_US.properties或者login_zh_CN.properties,切換到Resource Bundle視圖,可以方便地編輯三個文件
2.2 管理國際化資源文件
這裏springboot的MessageSourceAutoConfiguration
已經幫我們配置好了
public class MessageSourceAutoConfiguration {
@Bean
@ConfigurationProperties(
prefix = "spring.messages"
)
//設置國際化資源文件的基礎名(去掉語言國家代碼的)
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) { messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
......
}
public class MessageSourceProperties {
private String basename = "messages";
spingboot設置國際化配置文件的基礎名爲message
,我們的國際化配置文件可以直接放在類路徑下叫messages.properties
,但是根據第一步我們自己寫的國際化配置文件,要重新制定國際化配置文件的基礎名
在application.properties文件中添加如下代碼
spring.messages.basename=i18n.login
2.3 去頁面獲取國際化的值
根據thymeleaf,獲取國際化值的方法時使用#{*}
2.4 文件編碼
最好按以下方式設置,相當於修改了項目的默認文件編碼,包括當前項目
2.5 測試
使用Chrome瀏覽器,選擇瀏覽器語言爲中文,且移至首位。之所以將其放在第一個位置,是因爲每發一個請求的時候,請求頭裏的Accept-Language
屬性的第一個值爲zh_CN
首頁顯示如下
將Chrome瀏覽器的語言設置爲英文(美國),且移到頂部
首頁顯示爲
2.6 點擊切換語言
頁面底部有個中英文按鈕,我們如何使用點擊的方式來切換瀏覽器的語言呢,這就要了解一下國際化的原理。
國際化的配置主要是根據Locale
(區域信息對象);LocaleResolver
(獲取區域信息對象)
WebMvcAutoConfiguration
類中有以下方法可以獲取locale值
@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;
}
}
這個locale值對應着請求頭裏的Accept-Language
屬性的第一個值,當項目中沒有用戶建立的LocaleResolver時會使用這個默認的LocaleResolver
,於是我們創建一個自己的MyLocaleResolver
,並將其添加進容器
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String l = request.getParameter("l");
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(l)){
//從請求域中獲取屬性l的值,將其以"_"分開,split[0]代表語言,split[1]代表地區
String[] split = l.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
}
}
在配置類MyMvcConfig中將自己創建的LocaleResolver添加進容器,
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
對login.html做如下修改,將l值傳入請求域
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
這樣,點擊頁面上的中文或英文標籤就能切換語言。
3. 配置登錄頁面
-
添加LoginController,設置admin以及123456分別爲用戶名和密碼,添加錯誤登錄信息提示
@Controller public class LoginController { @PostMapping(value = "/user/login") // @RequestMapping(value = "/user/login", method = RequestMethod.POST) public String login(@RequestParam("username") String username, @RequestParam("password") String password, Map<String, Object> map){ if(!StringUtils.isEmpty(username) && "123456".equals(password)){ //登錄成功 return "dashboard"; }else{ //登錄失敗 map.put("msg", "用戶名密碼錯誤"); return "login"; } } }
-
開發期間模板引擎頁面修改以後,要實時生效
首先在application.properties禁用緩存
# 禁用緩存 spring.thymeleaf.cache=false
每當頁面重新編輯以後,按
Ctrl+F9
重新編譯 -
在login.html中修改form表單中的action請求路徑
<form class="form-signin" th:action="@{/user/login}" th:method="post">
-
在login頁面中添加a標籤提示錯誤信息
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1> <!-- 判斷--> <p style="color:red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p> <label class="sr-only" th:text="#{login.username}">Username</label>
如果msg爲空,不顯示錯誤信息。
-
登錄成功後,進入dashboard.html,刷新頁面的時候,瀏覽器會提示要重新提交表單。爲了防止表單的重複提交,我們修改LoginController,重定向到dashboard頁面,在配置類中添加請求映射“/main.html”
MyMvcConfig.java
@Bean //將組件註冊在容器中 public WebMvcConfigurer webMvcConfigurer(){ WebMvcConfigurer adapter = new WebMvcConfigurer() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login"); registry.addViewController("/index.html").setViewName("login"); registry.addViewController("/main.html").setViewName("dashboard"); } }; return adapter; }
LoginController
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Map<String, Object> map){ if(!StringUtils.isEmpty(username) && "123456".equals(password)){ //登錄成功 return "redirect:/main.html"; }else{ //登錄失敗 map.put("msg", "用戶名密碼錯誤"); return "login"; }
-
上一步配置好以後,可以通過請求路徑
localhost:8080/main.html
直接訪問dashboard,這就失去了登錄頁面的意義。我們可以配置攔截器,攔截請求查看是否已經登錄,如果已經登錄可以通過localhost:8080/main.html
直接訪問dashboard。首先修改LoginController,往session添加已登錄的用戶名
loginUser
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Map<String, Object> map, HttpSession session){ if(!StringUtils.isEmpty(username) && "123456".equals(password)){ //登錄成功 session.setAttribute("loginUser", username); return "redirect:/main.html"; // return "dashboard"; }else{
創建攔截器
component.LoginHandlerInterceptor
做登錄檢查public class LoginHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user = request.getSession().getAttribute("loginUser"); if(user == null){ //未登錄 request.setAttribute("msg", "沒有權限,請先登錄"); request.getRequestDispatcher("/index.html").forward(request, response); return false; }else{ //已登錄,放行 return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
之後在配置類中把攔截器添加進去,攔截所有請求
/**
,然後把訪問登錄頁面的請求/
、/index.html
、/user/login
排除掉。對於如css等靜態資源的訪問,SpringBoot已經做好了配置,我們不用管。@Bean //將組件註冊在容器中 public WebMvcConfigurer webMvcConfigurer(){ WebMvcConfigurer adapter = new WebMvcConfigurer() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("login"); registry.addViewController("/index.html").setViewName("login"); registry.addViewController("/main.html").setViewName("dashboard"); } //註冊攔截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**") .excludePathPatterns("/index.html", "/", "/user/login"); } }; return adapter; }
-
修改dashboard.html,使用
[[${session.loginUser}]]
在該頁面顯示登錄的用戶名<body> <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0"> <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">[[${session.loginUser}]]</a> <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search"> ......
-
使用thymeleaf方式修改dashboard.html的代碼。