• (5)Spring Boot web开发 --- Restful CRUD



    @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. 获取配置文件的值

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

      在这里插入图片描述
      如果没有标签体,则使用 [[login.tip]] 语法;

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

    4. 根据浏览器语言切换

      经过上面的设置以后,现在切换浏览器的语言选项,界面的文字也会随之变换;

    5. 通过点击链接切换

      切换浏览器语言首选项,页面文字,随之切换的原理,就是有个 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 进行编译 ;

    2. 登陆

      处理登陆的处理器:

          @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");
                  }
              } ;
          }
      
    3. 拦截

      像上边那样做了映射以后,其实不用登陆,直接访问映射的地址,也能访问到 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
    在这里插入图片描述

  • 相关阅读:
    Visual Studio Code 配置C/C++环境
    二叉链的基本操作
    回文自动机
    吊打线段树的超级树状数组
    Treap平衡树
    uni-app nvue页面动态修改导航栏按钮
    uni-app map组件关于marker标记点动态设置的问题
    uni-app 提示 v-for 暂不支持循环数据
    uni-app APP端隐藏导航栏自定义按钮
    uni-app路径规划(打开第三方地图实现)
  • 原文地址:https://www.cnblogs.com/young-youth/p/11665580.html
Copyright © 2020-2023  润新知