SpringBoot视图解析

1、项目结构

在正式介绍之前,首先看一下项目的整体结构,下文的所有内容都是在该结构的基础之上实现的。

首先解释一下每个文件夹的作用,如果你是用的是idea创建的springboot项目,会在项目创建的一开始resources文件夹下自动创建static以及templates文件夹。也就是说项目初始时有java、resource、static以及templates 这几个文件夹。一般static下存放js以及css样式文件,templates存放html页面。
以上是默认会创建的文件夹以及其作用
首先static文件夹以及templates文件夹是受保护的,也就是说相当于你将文件放到了传统的ssh或ssm项目的WEB-INF下了。所以也就是说这两个文件夹下的文件是无法通过url直接访问的,以至于在springmvc下使用会报404。
在讲重定向与转发之前先讲一下目录优先级的情况,webapp>META-INF/resources>resources>static>public
那么如何能够直接访问到html或者css呢?
方法一 
我们可以在resources下创建一个名为public的文件夹,顾名思义,放在此文件夹下的文件是共有的,可以直接通过url访问,当然也可以springmvc重定向访问啦。
方法二
在main下创建webapp文件夹,如上图所示,将文件放到此文件夹下,效果同上。
注!文件夹名字是固定的,起别的名字还是会报404或者无效
首先呢public与webapp这二个在使用过程中一般创建一个目录就好了。

注意:这里我使用了thymeleaf模版,配置文件如下

server.port=80

spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

这里的thymeleaf可以不写,其实都是默认的配置。

2、请求转发

SpringMVC请求转发区别于重定向,请求转发地址栏不会发生改变、只发送一次请求、能携带原有的参数,但只可以在同一个服务器中进行转发。

注意:请求转发的转发内容可以是地址和页面,如果是页面则需要直接放到webapp目录或者public目录下。

2.1、传统Servlet的请求转发

    @RequestMapping("/forwardCommon")
    public void forwardCommon(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("c.html").forward(request,response);
    }

这里的c.html是在webapp下的。

2.2、SpringMVC不经过视图解析器的请求转发


@RequestMapping("/forwardView1")
    public String forwardViewOne(){
        return "forward:/forwardCommon";
    }
//这里转发的是地址

这里的请求转发的是上一个地址。

@RequestMapping("/forwardView2")
    public ModelAndView forwardView(){
        ModelAndView mv=new ModelAndView();
        //这里不能直接访问WEB-INF下面的页面,例如不能写/WEB-INF/e.html
        mv.setViewName("forward:f.html");
        return mv;
    }

这里访问的是f.html,该页面在public目录下

2.3、SpringMVC经过视图解析器的请求转发


@RequestMapping("/view1")
    private String view1(String id) {
        //这里可以直接写a,因为thymeleaf会自动拼接为a.html,并且到templates下面找
        return "a";  // 和 return "/a" 一样,都会去templates下面找a.html。即是controller中存在/a的请求地址,也还是会去templates下面寻找a.html,而不是走对应的请求路径。
    }
@RequestMapping("/view2")
    private ModelAndView view2(ModelAndView model) {
        ModelAndView mv=new ModelAndView();
        mv.setViewName("b");//也是请求转发,会经过视图解析器
        return mv;
    }

这里是直接返回页面,可以携带数据,这两种方式是经常使用的,其实不经过视图解析起的路由也是请求转发。

即使是如下极端的情况:

  @GetMapping("/index")
    public String index(){
        return "/index";  
    }

这种也是去templates中寻找index.html页面,而不是在controller中寻找/index请求的路径。

3、重定向(地址会变)

传统的重定向请求地址会改变(两次请求)、不能传递参数,但是利用SpringMVC的重定向可以携带和传递参数。重定向相比于请求转发可以跨服,但是不能直接重定向访问WEB-INF下的资源(可重定向后再进行一次请求转发)。

注意:重定向的内容可以是地址和页面,如果是页面则需要直接放到webapp目录或者public目录下。

3.1、传统Servlet重定向

    @RequestMapping(value="/redirect",method = { RequestMethod.POST, RequestMethod.GET })
    public void testRedirect(HttpServletResponse response) throws IOException {
        response.sendRedirect("c.html"); //这里也可以重定向到一个controller中的请求地址,例如: "/a"
    }

这里是访问直接放到webapp下的页面,也可以直接访问放到public下的页面

3.2、SpringMVC不带参数的重定向

第一种方式:

@RequestMapping(value="/redirect2",method = { RequestMethod.POST, RequestMethod.GET })
    public String testRedirect2(){
        return "redirect:/view1"; //这里/view1 或者是前面不加/,都会在controller中寻找地址,而不是去寻找html页面
    }

这里是重定向到view1地址。

第二种方式:

@RequestMapping(value="/redirect3",method = { RequestMethod.POST, RequestMethod.GET })
    public ModelAndView testRedirect3(){
        ModelAndView mv=new ModelAndView();
        mv.setViewName("redirect:/forwardView2");
        return mv;
    }

这里通过ModelAndView重定向

3.3、SpringMVC带参数的重定向

重定向的同时传递参数

第一种

redirectAttributes.addAttributie("prama",value); 这种方法相当于在重定向链接地址上追加传递的参数

@RequestMapping("/test1")
    private String paraRed(RedirectAttributes ra) {
        ra.addAttribute("id", 1);
        return "redirect:/view1";
    }

浏览器的地址栏会自动拼接成http://localhost/test1?id=1   ,注意这里我的端口号是80

第二种

redirectAttributes.addFlashAttributie("prama",value); 这种方法是隐藏了参数,链接地址上不直接暴露,用(@ModelAttribute(value = "prama")String prama)的方式获取参数。

@RequestMapping("/test2")
    private String paraRed2(RedirectAttributes ra) {
        ra.addFlashAttribute("id", 1);
        return "redirect:/view1";
    }

这种方式浏览器不会自动拼接后面的字符串,重定向的地址也可以访问到对应的参数。

接收参数

在浏览器输入地址 http://localhost/test3?id=1

@RequestMapping("/test3")
    private String paraRed3(@ModelAttribute("id") String id) {
        System.out.println(id);//输出1
        return "redirect:/view1";
    }

这种方式也可以使用@PathVariable接收。

4、扩展

1.不使用thymeleaf模板引擎的时候

默认根路径为static

    @RequestMapping("/loginSys1")
    public String toHtml1(){
        System.out.println("进入");
        return "/login.html";      //找到resources下的static下的login.html
    }

可以配置前后缀

spring:
  mvc:
    view:
      prefix: /     //这里如果不加/,那么返回的视图前就需要加上/
      suffix: .html
 @RequestMapping("/loginSys2")
    public String toHtml2(){
        System.out.println("进入");
        return "login";      //找到resources下的static下的login.html
    }
2.使用thymeleaf模板后

添加thymeleaf依赖后,默认根路径改为templates

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
@RequestMapping("/loginSys3")
    public String toHtml3(){
        System.out.println("进入");
        return "user/login";      //找到resources下的templates下的user下的login.html
    }
@RequestMapping("/loginSys4")
    public String toHtml4(){
        System.out.println("进入");
        return "login";      //找到resources下的templates下的login.html
    }

注意,thymeleaf默认配置

spring.thymeleaf.cache=true //默认为true,开启devtools的时候要把缓存关闭,设置成false
spring.thymeleaf.prefix=classpath:/templates/  //默认springmvc会自动到templates目录下寻找
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.mode=HTML
以上内容都是Thymeleaf默认配置好的,可以不用写。

5、常用注解

@RequestParam,@PathVariable,


@RequestParam@PathVariable 注解是用于从request中接收请求的,两个都可以接收参数,关键点不同的是@RequestParam 是从request里面拿取值,而 @PathVariable 是从一个URI模板里面来填充

例如:

    @RequestMapping("/hello")
    @ResponseBody
    public String testRequest(@RequestParam(value = "param1") String param1){
        System.out.println(param1);
        return param1;
    }

此时访问路径为 localhost/hello?param1=666 ,此时该方法会获取到请求路径中的参数,打印出666。

@RequestParam 支持下面四种参数

  • 1.defaultValue 如果本次请求没有携带这个参数,或者参数为空,那么就会启用默认值
  • 2.name 绑定本次参数的名称,要跟URL上面的一样
  • 3.required 这个参数是不是必须的
  • 4.value 跟name一样的作用,是name属性的一个别名
@RequestMapping("/world/{id}")
    @ResponseBody
    public String testPath(@PathVariable(value = "id") String id){
        System.out.println(id);
        return id;
    }

此时访问的路径为 localhost/world/123   ,此时该方法会把123认为就是路径中id的值,此时会打印出123。

全部评论