使用springboot来编写web项目的一些实现
1. 默认访问首页
1.将首页添加到templates下,以启用thymeleaf模板
2.编写配置类实现WebMvcConfigurer接口,重写addViewControllers方法来添加自定义视图解析器,使“/”请求可以直接映射到首页(定义内部类时要添加@Bean注解)
@Configuration
//WebMvcConfigurer接口中有很多方法的对应的是以往Springmvc配置文件中的属性
//使用其来扩展SpringMVC的功能
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送/jiat请求来到 success
registry.addViewController("/jiat").setViewName("success");
}
//所有的WebMvcConfigurer组件都会一起起作用
@Bean
public WebMvcConfigurer webMvcConfigurer(){
WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login.html").setViewName("login");
}
};
return webMvcConfigurer;
}
2.国际化
- 编写国际化配置文件;
- 使用ResourceBundleMessageSource管理国际化资源文件
- 在页面使用fmt:message取出国际化内容
现在的步骤:
-
编写国际化配置文件,抽取页面需要显示的国际化消息
三个文件: login.properties 默认 login_en_US.properties 英文 login_zh_CN.properties 中文 login.btn=登录 login.password=密码 login.remrember=记住 login.tip=登录 login.username=用户名
-
SpringBoot自动配置好了管理国际化资源文件的组件
public class MessageSourceAutoConfiguration { private static final Resource[] NO_RESOURCES = new Resource[0]; public MessageSourceAutoConfiguration() { } @Bean @ConfigurationProperties( prefix = "spring.messages" ) public MessageSourceProperties messageSourceProperties() { return new MessageSourceProperties(); } @Bean public MessageSource messageSource(MessageSourceProperties properties) { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); //setBasenames 设置国际化资源文件的基础名(去掉语言国家代码的) if (StringUtils.hasText(properties.getBasename())) { messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename()))); } public class MessageSourceProperties { private String basename = "messages"; //说明不做任何配置时,配置文件可以直接放在类路径下叫messages.properties,也可以识别 private Charset encoding;
配置时只需要去到spring.messages.basename=“” 直接赋值基本名则在root路径下,如果有包路径则通过路径查找
spring.messages.basename=i18n.login
-
去页面获取国际化的值
th:text="#{login.tip}
效果:根据浏览器语言设置的信息切换了国际化信息
原理:
国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象)
//springboot配置了一个解析区域信息的解析器
@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
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
}
//默认使用AcceptHeaderLocaleResolver,从请求头中获取区域信息(request.getLocale())
public class AcceptHeaderLocaleResolver implements LocaleResolver {
public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = this.getDefaultLocale();
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
} else {
Locale requestLocale = request.getLocale();
List<Locale> supportedLocales = this.getSupportedLocales();
if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
-
点击链接切换国际化
链接携带上区域信息:zh_CN或者en_US
/** * 能连接上携带区域信息的解析器 **/ public class MyLocaleResolver implements LocaleResolver { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String l = httpServletRequest.getParameter("l"); Locale locale=Locale.getDefault(); //注意要为locale设置默认,否则会报空指针,设置为request.getLocale()可以实现跟随浏览器语言改动 if (!StringUtils.isEmpty(l)){ String[] split = l.split("_"); locale = new Locale(split[0],split[1]); } return locale; }
//WebMvcConfigurer配置类中 @Bean public LocaleResolver localeResolver(){ return new MyLocaleResolver(); }
3.登陆
开发期间模板引擎页面修改以后, 要实时生效
1.禁用模板缓存
#禁用缓存
spring.thymeleaf.cache=false
页面修改完成后ctrl+f9;重新编译
错误消息的显示:
<p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>
2.防止表单重复提交
登陆成功后重定向页面,因为页面需要通过模板引擎渲染,要添加到试图解析器的映射中
// springboot 有Rest风格的mapping注解代替原先的RequestMapping
// @DeleteMapping
// @PutMapping
// @GetMapping
@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, HttpSession session){
if (!StringUtils.isEmpty(username) && "123456".equals(password)){
session.setAttribute("loginUser",username); //登陆状态记录到session中
//防止表单重复提交
return "redirect:/main.html"; //不能有空格
}
map.put("msg","用户名密码错误");
return "login";
}
将重定向的/main.html在视图解析器中映射到实际的页面
registry.addViewController("/main.html").setViewName("dashboard");
3. 拦截器进行登陆检查
防止直接通过/main.html请求越过登陆,所以要使用拦截器进行拦截检查
- 定义拦截器:实现HandlerInterceptor接口重写preHandle方法,检查登陆状态,成功则放行,不然request放入错误信息,并转发到登陆页面
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;
}
}
}
-
在实现WebMvcConfigurer的配置类中注册拦截器加入到容器中
//注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { //注册登陆拦截器:排除掉去往登陆页面的请求,登陆请求也不能被拦截 //spring boot2.x 版本需要重新对静态资源放行,不然也会被拦截; registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html","/","/user/login","/assets/**"); } };