文章目录

  • `@RestController` vs `@Controller`
  • 默认访问首页
  • 设置项目名
  • 国际化
  • 登陆 & 拦截
  • Restful 风格



@RestController vs @Controller

@RestController@Controller@ResponseBody 的合体,如果标注在处理器上,则处理器的方法,如果返回一般对象,则返回 JSON 形式的数据给页面,如果返回字符串,则直接将字符串写给页面,二者都不会去查找静态资源 ;

@Controller 当返回值是字符串的时候,会先去找有没有对应的视图,有就返回视图,没有就会报错,找不到对应的视图;

如果返回对象,也是直接报错;因为它只能返回三种返回值,也就是最初学 SpringMvc 时候学的三种:ModelAndViewVoidString

简而言之,@Controller 需要找视图,@RestController 不会去找视图 ;

最后总结下 @Controller 方法的返回值:

当其返回值是 String 的时候,如果直接写视图名字,则会被拼接成视图地址,如果想去静态资源文件夹下面,而非去视图所在的文件夹,则使用 forwardredirect 标注下 :return "redirect:/index.html" ;

只要没有使用 forwardredirect 标注,都被当做是 视图名字 ;

直接写 / 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 BootWebMvc 配置 ,将首页页面,进行映射,只需要在自定义的配置里面,进行如下操作:

@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=/项目名

国际化

  1. 编写配置文件
    首先编写配置文件,IDEA 会识别出我们想进行国际化,只要按照下面的方式进行写配置文件;

    然后按照如下方式进行操作:
  2. 配置国际化组件
    Spring Boot 自动配置好了管理国际化的组件,基础名默认是message,基础名就是去掉语言和国家,剩下的前缀。比如 login_en_US,去掉语言 en 和 国家 US ,就剩下 login
    不是 message ,需要设置下基础名,需要写类路径下的完整路径,然后加上自己的基础名 :
    比如我的配置文件,在类路径下面的 i18n 文件夹下面的,基础名叫 login,就写成下面这样:
  3. spring boot 增加resource_配置文件

  4. 获取配置文件的值
    然后在页面中获取配置文件的值,我们使用 thymeleaf 模板,使用 #{login.tip} 这样的格式进行获取值(看仔细点,是 # 而非 $),IDEA 还会有提示的,能直接看到属性的值:

    如果没有标签体,则使用 [[login.tip]] 语法;

在页面中获取配置文件的值的时候,如果你没有编码的设定,会出现乱码,解决方法,在这个系列的前面博客中已经讲过了,或者自己百度,又或者根本就没有看这些博客呢,你自己又不是博客专家,哈哈,想这么周到干嘛呢;

  1. 根据浏览器语言切换
    经过上面的设置以后,现在切换浏览器的语言选项,界面的文字也会随之变换;
  2. 通过点击链接切换
    切换浏览器语言首选项,页面文字,随之切换的原理,就是有个 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 ,它是注入到容器中的 idSpring Boot 也是根据这个 id 来判断我们自定义了 区域信息对象 ;


登陆 & 拦截

  1. 禁用 thymeleaf 模板引擎的缓存
    在开发期间,我们需要页面被修改以后,再次访问就应该是新的页面,这样就需要禁掉 thymeleaf 的缓存 ;
# 禁用缓存
spring.thymeleaf.cache=false

同时在使用 IDEA 的时候,页面被修改以后,IDEA 需要重新编译下,浏览器才会看到最新的页面,使用 Ctrl + F9 进行编译 ;

  1. 登陆
    处理登陆的处理器:
@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");
            }
        } ;
    }
  1. 拦截
    像上边那样做了映射以后,其实不用登陆,直接访问映射的地址,也能访问到 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 两种方法 ;

spring boot 增加resource_html_02


可以参照下面的图,看 Restful 风格的 url

spring boot 增加resource_html_03