整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Spring MVC 框架学习-返回页面+加载静态资

Spring MVC 框架学习-返回页面+加载静态资源

章目录

  • Spring 框架学习(六)---- 返回页面+加载静态资源
  • 2、返回 application/json
  • 1、请求转发forword 和 重定向的区别2、请求转发的访问资源问题演示

Spring 框架学习(六)---- 返回页面+加载静态资源

一、返回页面

不加 @ResponseBody ,默认是返回一个网页

@RequestMapping("/getPage")
    public String getPage(){
 
        return "index.html";
    }

二、返回非页面的数据

??返回非页面的数据,必须在方法或者类上加 @ResponseBody,同时 我们返回的类型 springmvc会自动解析成对应的格式,不需要我们进行手动指定

1、返回 text/html

@RequestMapping("/getText")
    @ResponseBody
    public String getHTML(String name){
 
        return "<h1>你好,欢迎用户:"+name+"<h1>";
    }

访问接口,自动解析成 html格式

通过 Fiddler 进行抓包,查看返回响应的格式为 text/html。

2、返回 application/json

使用map存储数据,返回map

@RequestMapping("/getmap")
    @ResponseBody
    public Object getJson(){
 
        HashMap<Object,Object> map=new HashMap<>();
        map.put("msg","登陆成功");
        map.put("status",200);

        return map;
    }

自动解析称为 json 格式的数据

三、加载静态资源

咱们就直接定死了写的格式

在webapp目录下创建static文件夹保存 css、js、html 资源

同时在spring-mvc.xml 文件中加入 过滤静态资源、加载静态资源的配置

<!--    过滤静态资源,  /.jsp  /.html 不会经过-->
    <mvc:default-servlet-handler/>


 <!--加载静态资源location表示访问的路径return"/static/login.html",mapping表示映射的静态资源位置-->
    <mvc:resources location="/static/css/" mapping="/static/css/**"/>
    <mvc:resources location="/static/js/" mapping="/static/js/**"/>
    <mvc:resources location="/static/" mapping="/static/**"/>

我们来试一下访问静态资源

在wbeapp目录下创建static文件,将css/js/html等文件添加进去

web.xml 配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <multipart-config>
      <max-file-size>20848820</max-file-size>
      <max-request-size>418018841</max-request-size>
      <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
  </servlet>

  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

spring-mvc.xml 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    

    <!--    开启注解扫描,将使用注解的类托管到spring 容器中-->
    <context:component-scan base-package="com.*"/>

    <!--    过滤静态资源,  /.jsp  /.html 不会经过-->
    <mvc:default-servlet-handler/>

<!--    加载静态资源文件-->
    <mvc:resources location="/static/css/" mapping="/static/css/**"/>
    <mvc:resources location="/static/js/" mapping="/static/js/**"/>
    <mvc:resources location="/static/" mapping="/static/**"/>

    <!--    开启mvc注解驱动-->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>



    </mvc:annotation-driven>

</beans>

在controller层进行访问静态html文件(经过css、js渲染)

@RequestMapping("/login")
    public String getLog(){
 
        return "redirect:/static/login.html";
    }

四、转发和重定向

1、请求转发forword 和 重定向的区别

(1) 重定向 将请求重新定位到资源的位置,请求转发是服务器端进行转发的

(2)请求重定向url地址发生改变,请求转发地址不发生变化

(3)请求重定向于直接访问新地址的效果一样,不存在原来的外部资源不能访问,请求转发服务器端的转发可能会造成外部资源不能访问(js、css)

如果外部资源与转发访问的页面不在同一级目录下,会造成外部资源不可访问。

2、请求转发的访问资源问题演示

通过转发的请求资源都直接通过 8080:/a/login 这个接口的同一级目录下直接访问,当然找不到资源

请求重定向相当于 输入的url变了,直接访问到 /static/login/html,同时附带的资源在在这一目录下能够访问到。

3、页面跳转

1、请求转发: 服务器放客户进行请求转发并将结果响应给客户端,URL是不会变的

2、请求重定向:服务器端请求重新定义到要访问的地址。URL会放生改变。

总结:

  • 请求转发的URL地址不变,因为是服务器端进行转发和响应的,所以重定向URL地址会发生改变,因为服务器端直接将请求重定向到具体的地址上
  • 使用请求转发那么有可能会发生资源丢失,访问不到外部资源。请求重定向是直接重定向到URL地址,所以请求重定向和直接访问目标地址的效果是一样的,所以不会存在外部资源丢失的情况。

五、组合注解

@RestController

相当于 @Controller + @ResponseBody

只能加到类上

绍一下SpringMVC视图解析器。当我们对SpringMVC控制的资源发起请求时,这些请求都会被SpringMVC的DispatcherServlet处理,接着spring会分析看哪一个HandlerMapping定义的所有请求映射中存在对该请求的最合理的映射。然后通过该HandlerMapping取得其对应的Handler,接着再通过相应的HandlerAdapter处理该Handler。HandlerAdapter在对Handler进行处理之后会返回一个ModelAndView对象。在获得了ModelAndView对象之后,Spring就需要把该View渲染给用户,即返回给浏览器。在这个渲染的过程中,发挥作用的就是ViewResolver和View。当Handler返回的ModelAndView中不包含真正的视图,只返回一个逻辑视图名称的时候,ViewResolver就会把该逻辑视图名称解析为真正的视图View对象。View是真正进行视图渲染,把结果返回给浏览器的。

ViewResolver和View介绍

SpringMVC用于处理视图最重要的两个接口是ViewResolver和View。ViewResolver的主要作用是把一个逻辑上的视图名称解析为一个真正的视图,SpringMVC中用于把View对象呈现给客户端的是View对象本身,而ViewResolver只是把逻辑视图名称解析为对象的View对象。View接口的主要作用是用于处理视图,然后返回给客户端。

Spring为我们提供了非常多的视图解析器,下面将列举一些视图解析器。

AbstractCachingViewResolver:这是一个抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。

UrlBasedViewResolver:它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了。如prefix=/WEB-INF/jsps/,suffix=.jsp,返回的视图名称viewName=test/indx,则UrlBasedViewResolver解析出来的视图URL就是/WEB-INF/jsps/test/index.jsp。默认的prefix和suffix都是空串。URLBasedViewResolver支持返回的视图名称中包含redirect:前缀,这样就可以支持URL在客户端的跳转,如当返回的视图名称是”redirect:test.do”的时候,URLBasedViewResolver发现返回的视图名称包含”redirect:”前缀,于是把返回的视图名称前缀”redirect:”去掉,取后面的test.do组成一个RedirectView,RedirectView中将把请求返回的模型属性组合成查询参数的形式组合到redirect的URL后面,然后调用HttpServletResponse对象的sendRedirect方法进行重定向。同样URLBasedViewResolver还支持forword:前缀,对于视图名称中包含forword:前缀的视图名称将会被封装成一个InternalResourceView对象,然后在服务器端利用RequestDispatcher的forword方式跳转到指定的地址。使用UrlBasedViewResolver的时候必须指定属性viewClass,表示解析成哪种视图,一般使用较多的就是InternalResourceView,利用它来展现jsp,但是当我们使用JSTL的时候我们必须使用JstlView。下面是一段UrlBasedViewResolver的定义,根据该定义,当返回的逻辑视图名称是test的时候,UrlBasedViewResolver将把逻辑视图名称加上定义好的前缀和后缀,即“/WEB-INF/test.jsp”,然后新建一个viewClass属性指定的视图类型予以返回,即返回一个url为“/WEB-INF/test.jsp”的InternalResourceView对象。

Xml代码


  1. <bean
  2. class="org.springframework.web.servlet.view.UrlBasedViewResolver">
  3. <property name="prefix" value="/WEB-INF/" />
  4. <property name="suffix" value=".jsp" />
  5. <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
  6. </bean>

跳转关键字 forward: redirect:

注意:返回值不写关键字时 默认是转发跳转

返回值写了关键字时,视图解析器不在为你拼接前后缀,写完整的跳转路径

1、C--->V

由C(控制器)跳转到页面V(视图)

@RequestMapping("/test1")
public String test1(){
    System.out.println("c--->v");
    //重定向跳转   index.jsp
    return "redirect:/index.jsp";
    //转发跳转    /view/hello.jsp
    //return "forward:/view/hello.jsp";
}

2、C--->C

由由C(控制器)跳转到C(控制器)

@RequestMapping("/test2")
public String test2(){
    System.out.println("c--->c");
    //转发跳转   /jump/test1           
    //return "forward:/jump/test1";    绝对路径,适用于跨类的跳转
    //跳转到当前类下的路径为test1的方法中 
    //return "forward:/test1";         相对路径
    //重定向到  /jump/test1            
    //return "redirect:/jump/test1";   绝对路径
    return "redirect:/test1";         
}

3、跳转细节

在增删改之后,为了防止请求重复提交,进行重定向跳转

在查询之后,可以做转发跳转

C---->C :增删改后衔接一个查询

C---->V:查询后衔接一个视图

4、JSP细节

不应该直接访问jsp,应该先过C,查到数据后,在转发jsp

可以将所有jsp都放入WEB-INF目录下,即可强制不接受外界直接访问,只能由C转发

传值

C得到数据后,转发V,并向V传递数据,进而V中可以渲染数据,让用户看到含有数据的页面

转发跳转(在一个请求中):Request作用域

重定向跳转(在一个会话中):Session作用域

1、获得Request和Session

<!--导入依赖-->
<!--=====================Servlet======================-->
    <!--jstl支持-->
    <dependency>
      <groupId>javax.servlet.jsp.jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <!--servlet编译环境-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

    <!--jsp编译环境-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
    <!--=====================Servlet======================-->
@RequestMapping("test1")
public String test1(HttpServletRequest request, HttpSession session){
    request.setAttribute("name","张三");
    session.setAttribute("age",19);
    return "data";
}

2、JSP中取值

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<body>
<h2>Hello World!</h2>
${requestScope.name}--${sessionScope.age}
</body>
</html>

注意:1、requestScope和sessionScope可以忽略,这样的写法更加精确的取哪个作用域的值
     2、EL表达式取作用域的值时页面显示的时${requestScope.name}--${sessionScope.age}
       解决方法1:页面上加上 isELIgnored(是否忽略EL表达式)="false"
       解决方法2:web.xml在<jsp-property-group>里设置一组jsp文件是否忽略EL

了解:Model, ModelAndView

ModelAndView:springmvc底层使用的一个类,封装了视图跳转的名称和传递的值

Model:视图技术有很多(jsp、velocity、freeMarker等等),有些视图可能取不到常用的作用域的值

Model中存值则避免了视图取不到作用域中值得问题,实现了视图和作用域之间得解耦。

@RequestMapping("test2")
public String test2(Model model,HttpSession session){
    model.addAttribute("name","张三");
    session.setAttribute("age",29);
    return "data";
}

@RequestMapping("test3")
public ModelAndView test3(){
    ModelAndView modelAndView=new ModelAndView();
    modelAndView.setViewName("data");
    modelAndView.addObject("name","张三");
    modelAndView.addObject("age",19);
    return modelAndView;
}

静态资源

<!--tomcat中的web.xml全局配置文件-->
<!-- The default servlet for all web applications, that serves static resources-->
<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

静态资源:html、js文件、css文件、图片文件

tomcat中有个全局的servlet:org.apache.catalina.servlets.DefaultServlet,专门用于处理静态资源问题。

但在springmvc的配置文件中DispatcherServlet也采用了"/"作为url-pattern,则项目中不会在使用全局的servlet,则静态资源不能完成访问

1、解决方案1

DispatcherServlet中的url-pattern使用其他的,例如 *.action

出现的问题:所有请求的结尾都要加上.action,比较麻烦

<servlet>
    <servlet-name>mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>mvc</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

2、解决方案2

<!--在项目中  自动添加一个映射("/**":DefaultServletHttpRequestHandler)
    请求进入前端后,会先匹配自定义的handler,如果没有匹配则进入DefaultServletHttpRequestHandler
    DefaultServletHttpRequestHandler会将请求转发给tomcat中名为"default"的servlet
    这个servlet就是tomcat中全局配置web.xml中处理静态资源的servlet
    -->
<mvc:default-servlet-handler/>

JSON处理

springMVC默认的json解决方案选择是Jackson,所以只需要导入jackson的jar包,即可使用。

Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言。

远古时代采用xml格式进行数据交换(重量级)

1、导入依赖

<!--jackson-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.5</version>
</dependency>

2、@ResponseBody

@RequestMapping("test1")
//将handler的返回值,转换成json,并将json响应给客户端
@ResponseBody
public User test1(){
    System.out.println("test1");
    return new User(1,"张三",true,new Date());
}

3、日期格式化

public class User {
    private Integer id;
    private String name;
    private Boolean gender;
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
    private Date registerTime;
}

//@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
//在日期上添加如上格式,就是一个拆装箱的过程。将数据交换时日期格式转换成自己想要的格式

4、FastJson

<!--导入fastjson依赖-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>

4.1、安装FastJson

由于springmvc默认支持的是Jackson,所以要想使用第三方json处理方案,让springmvc识别FastJsonHttpMessageConverter,必须加上如下配置:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <!--声明转换类型:json-->
            <property name="supportedMediaTypes">
                <list>
                    <!--顺序不能反,不然使用ie时会出现下载提示-->
                    <value>text/html;charset=utf-8</value>
                    <value>application/json;charset=utf-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

4.2、日期格式化

public class User {
    private Integer id;
    private String name;
    private Boolean gender;
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date registerTime;
}

//@JSONField(format="yyyy-MM-dd HH:mm:ss")
//在日期上添加如上格式,就是一个拆装箱的过程。将数据交换时日期格式转换成自己想要的格式

5、@RestController

这是一个复合注解

相当于@Controller + @ResponseBody

@RestController
@RequestMapping("json")
public class JsonController {
    @RequestMapping("test1")
    //@ResponseBody
    public User test1(){
        System.out.println("test1");
        return new User(1,"张三",true,new Date());
    }

    @RequestMapping("test2")
    //@ResponseBody
    public List<User> test2(){
        System.out.println("test2");
        List<User> users=Arrays.asList(new User(1, "张三", true, new Date()), new User(2, "李四", true, new Date()));
        return users;
    }
}

6、@RequestBody

@RequestBody,接收json参数 (post请求)