@RestController
vs @Controller
@RestController
是 @Controller
和 @ResponseBody
的合体,如果标注在处理器上,则处理器的方法,如果返回一般对象,则返回 JSON
形式的数据给页面,如果返回字符串,则直接将字符串写给页面,二者都不会去查找静态资源 ;
而 @Controller
当返回值是字符串的时候,会先去找有没有对应的视图,有就返回视图,没有就会报错,找不到对应的视图;
如果返回对象,也是直接报错;因为它只能返回三种返回值,也就是最初学 SpringMvc
时候学的三种:ModelAndView
、Void
、String
简而言之,@Controller
需要找视图,@RestController
不会去找视图 ;
最后总结下 @Controller
方法的返回值:
当其返回值是 String
的时候,如果直接写视图名字,则会被拼接成视图地址,如果想去静态资源文件夹下面,而非去视图所在的文件夹,则使用 forward
、redirect
标注下 :return "redirect:/index.html" ;
只要没有使用 forward
、redirect
标注,都被当做是 视图名字 ;
直接写 / xx
全称也可以找到 匹配到 视图下面 ,比如: /xx.html
也会去视图下面找,多层文件夹也一样写 /xx/yy.html
;
默认访问首页
前面静态资源的时候,我们说过,Spring Boot
默认对静态资源文件下的 index.html
,做了映射,映射为 /
,这样就变成了默认首页;
如果,我们在 templates
文件夹下面配置首页,需要我们自己设置下,才可以变为默认首页;
引入 thymeleaf
模板以后,Spring Boot
的自动配置会对其进行配置,其中就有一个 视图配置:当处理器的方法,返回字符串的时候,会先去寻找 templates
文件夹下面 .html
为后缀的静态资源,看有没有名字匹配的,有就返回视图,没有就返回字符串字面值;(这里需要注意,处理器标注的是 @Controller
注解,而非 @RestController
,至于原因,上面提到了 )
至于其他地方的静态资源,对不起,默认访问不到,因为Spring Boot
没对其进行映射 ;
最简单的方法,实在处理器里面写个映射:
@RequestMapping({"/","/index"})
public String success(){
return "index" ;
}
还可以自己扩展Spring Boot
的 WebMvc
配置 ,将首页页面,进行映射,只需要在自定义的配置里面,进行如下操作:
@Bean
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
return new WebMvcConfigurerAdapter() {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/index").setViewName("index");
}
} ;
}
千万不要在配置类上,添加 @EnableWebMvc
,那样就不是扩展了,是完全代替了,取代了自动配置 ;
设置项目名
在配置文件中使用
server.servlet.context-path=/项目名
国际化
-
编写配置文件
首先编写配置文件,
IDEA
会识别出我们想进行国际化,只要按照下面的方式进行写配置文件;
然后按照如下方式进行操作:
-
配置国际化组件
Spring Boot
自动配置好了管理国际化的组件,基础名默认是message
,基础名就是去掉语言和国家,剩下的前缀。比如login_en_US
,去掉语言en
和 国家US
,就剩下login
;不是
message
,需要设置下基础名,需要写类路径下的完整路径,然后加上自己的基础名 :比如我的配置文件,在类路径下面的
i18n
文件夹下面的,基础名叫login
,就写成下面这样:
-
获取配置文件的值
然后在页面中获取配置文件的值,我们使用
thymeleaf
模板,使用#{login.tip}
这样的格式进行获取值(看仔细点,是#
而非$
),IDEA
还会有提示的,能直接看到属性的值:
如果没有标签体,则使用[[login.tip]]
语法;在页面中获取配置文件的值的时候,如果你没有编码的设定,会出现乱码,解决方法,在这个系列的前面博客中已经讲过了,或者自己百度,又或者根本就没有看这些博客呢,你自己又不是博客专家,哈哈,想这么周到干嘛呢;
-
根据浏览器语言切换
经过上面的设置以后,现在切换浏览器的语言选项,界面的文字也会随之变换;
-
通过点击链接切换
切换浏览器语言首选项,页面文字,随之切换的原理,就是有个
Locale
区域信息对象,Spring Mvc
通过LocaleResolver
获取区域信息对象, 然后只要拿到这个对象,进行设置,即可以了;Sping Boot
默认实现配置了一个Locale
区域信息对象,它的实现很简单,就是从请求头中获取区域信息;如果我们没有进行配置区域信息对象,则使用默认的,如果我们配置了,则使用我们配置的;
因此,我们可以替换默认实现,实现自己的
Locale
区域信息对象,从而定义获取区域信息的规则;实现自己的区域信息对象代码如下:
@Bean public LocaleResolver localeResolver(){ return new LocaleResolver() { @Override public Locale resolveLocale(HttpServletRequest httpServletRequest) { String l = httpServletRequest.getParameter("l"); Locale locale = Locale.getDefault() ; if(!StringUtils.isEmpty(l)){ String[] strings = l.split("_"); // 调用有2个参数的构造器,第一个参数:语言信息;第二个参数:地区信息 locale = new Locale(strings[0],strings[1]); } return locale; } @Override public void setLocale(HttpServletRequest httpServletRequest, @Nullable HttpServletResponse httpServletResponse, @Nullable Locale locale) { } }; }
将这段代码,添加到我们的配置类里面,切忌方法名字,只能为
localeResolver
,它是注入到容器中的id
,Spring Boot
也是根据这个id
来判断我们自定义了 区域信息对象 ;
登陆 & 拦截
-
禁用
thymeleaf
模板引擎的缓存在开发期间,我们需要页面被修改以后,再次访问就应该是新的页面,这样就需要禁掉
thymeleaf
的缓存 ;# 禁用缓存 spring.thymeleaf.cache=false
同时在使用
IDEA
的时候,页面被修改以后,IDEA
需要重新编译下,浏览器才会看到最新的页面,使用Ctrl + F9
进行编译 ; -
登陆
处理登陆的处理器:
@PostMapping("/user/login") 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("login",username); // 重定向到页面,防止表单重复提交 return "redirect:/main.html"; } map.put("msg","用户名或者密码错误") ; return "index"; }
上面的处理没涉及到数据库,仅仅演示处理逻辑;
登录成功以后,这里需要注意,进行页面的跳转,使用的是 重定向 ;如果,重定向的页面,是模板引擎下面的页面,则需要做个映射,因为只有 静态资源文件 下面的文件,才能被浏览器 直接 访问到;
做个映射,就像之前配置首页一样:
@Bean public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){ return new WebMvcConfigurerAdapter() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/index").setViewName("index"); // 配置映射 registry.addViewController("/main.html").setViewName("success"); } } ; }
-
拦截
像上边那样做了映射以后,其实不用登陆,直接访问映射的地址,也能访问到
thymeleaf
下面对应的文件了 ;因此,需要做个拦截,自定义拦截器:
@Component public class LoginIntercept implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); if (session.getAttribute("login") == null){ request.setAttribute("msg","没有权限访问,请登录"); request.getRequestDispatcher("/index").forward(request,response); return false; } return true; } }
然后一定还要进行配置下:
@Bean public WebMvcConfigurerAdapter webMvcConfigurerAdapter() { return new WebMvcConfigurerAdapter() { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/index").setViewName("index"); registry.addViewController("/main.html").setViewName("success"); } // 注册拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginIntercept()) // 拦截哪些资源,所有资源 .addPathPatterns("/**") // 排除哪些资源,其中静态资源: *.css,*.js ,已经由 Spring Boot 自己映射了, .excludePathPatterns("/index","/","/user/login"); } }; }
Restful 风格
以前在学习 Spring Mvc
的时候,老师也讲过一点这个概念,简而言之,就是对 URL
的一些建议要求,URL
仅仅代表对资源的标识,对资源的操作,不再体现在 url
上面 ;
Http
是有四个方法的,分别是 get,post,put,delete
,可能好多人以为只有 post,get
两种方法 ;
可以参照下面的图,看 Restful
风格的 url
: