2020-12-16

spring-mvc第一天笔记整理


一、概念及其优势(了解)

概念:springmvc是由spring提供的,通过java编写的,基于MVC设计思想轻量级web层框架

图解
在这里插入图片描述

springmvc的优势:
1.是spring体系的,所以可以无缝的和spring体系其它框架进行整合
2.springmvc提供了一套注解,能让一个普通的java类,变成一个可以处理请求的控制器
后期在web层不再需要编写Servlet
3.springmvc内部是基于组件的设计, 有清晰的角色划分,分工明确,易于扩展
springmvc和struts2的比较:
1. 都是基于mvc设计思想的web层框架
2. springmvc的前端控制器是通过Servlet来充当的,而struts2的前端控制器是通过Filter来充当的
3. springmvc的设计基于方法的,而struts2的设计是基于类的,因此 springmvc的性能优于struts2

二、springmvc快速入门

实现步骤

1)创建maven的web模块

2)导入springmvc相关坐标,配置tomcat7插件

<dependencies>
    <!-- servlet3.1规范的坐标 -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <!--jsp坐标-->
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
    </dependency>
    <!--spring的坐标-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <!--spring web的坐标-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    <!--springmvc的坐标-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!--具体的插件配置-->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <port>80</port>
                <path>/quickstart</path>
            </configuration>
        </plugin>
    </plugins>
</build>

3)在com.itheima.controller包下编写UserController

@Controller
public class UserController {
    @RequestMapping("/save")
    public String save(){
        System.out.println("save running....");
        return "success.jsp";
    }
}

4)在resources下编写springmvc的核心配置文件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"
       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">
    <!--注解的包扫描-->
    <context:component-scan base-package="com.itheima"/>
</beans>

5)在web.xml文件中配置springmvc的前端控制器,DispatcherServlet

<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--通过初始化参数指定springmvc的配置文件的名称-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!--指定servlet在服务器启动时加载-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

注意事项:

  1. DispatcherServlet的url-pattern是/,不是/*
  2. 通常会通过load-on-startup配置DispatcherServlet在服务器启动时加载
  3. 初始化参数contextConfigLocation用于指定配置文件名称创建spring容器,参数名固定

6)在webapp下创建success.jsp

<%@page pageEncoding="UTF-8" language="java" contentType="text/html;UTF-8" %>
<html>
    <body>
    	<h1>第一个spring-mvc页面</h1>
    </body>
</html>

7)浏览器访问http://localhost:80/quickstart/save测试

执行流程

1)服务器启动时

  • 加载web项目的web.xml
  • 由于配置了启动时加载,所以会创建DispatcherServlet实例
  • DispatcherServlet会读取初始化参数加载spring-mvc.xml
  • 通过spring-mvc.xml配置的包扫描扫描到UserController
  • 由于类上有@Controller注解,所以会创建其实例对象,并存入ioc容器
  • 方法上有@RequestMapping注解,所以会记录@RequestMapping的信息(UserController.save()==>/save)

2)通过浏览器访问http://localhost:80/quickstart/save发起请求时

  • 由于DispatcherServlet的url-pattern为/,所以DispatcherServlet会接收请求
  • 使用请求路径与所加载的@RequestMapping的内容进行比对,最终匹配到UserController中的save方法
  • 执行save方法,得到返回值"success.jsp"
  • 根据方法的返回值在webapp目录中查找对应的页面并响应

三、springmvc组件流程

springmvc三大组件

  1. 处理器映射器 HandlerMapping

    根据请求的资源路径映射要执行处理器(Controller)

  2. 处理器适配器 HandlerAdapter

    执行处理器(Controller)

  3. 视图解析器 ViewResolver

    根据处理器的执行结果寻找最终要访问的视图

流程图:
在这里插入图片描述

四、常规配置

1) Controller加载

springmvc的配置文件spring-mvc.xml文件属于web层的配置,只负责加载web层的资源。配置方式有两种。

  • 方式1(了解):在进行扫描时只加载包含@Controller注解的资源
<context:component-scan base-package="com.itheima">
    <!--只扫描包含Controller注解的类-->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • 方式2(常用):只扫描controller层的包
<!--只扫描controller包-->
<context:component-scan base-package="com.itheima.controller"/>

2)静态资源排除

由于DispatcherServlet的url-pattern配置为/,除了jsp之外的其它请求都会被DispatcherServlet处理,其中包含静态资源,如图片,css,js等。DispatcherServlet将静态资源交给HandlerMapping,无法匹配到任何Controller的访问映射。所以静态资源会出现404无法访问。解决方式有两种。

  • 方式1(了解)
<!--
    排除静态资源方式1:
        访问的资源路径如果是以/img/以及其子路径开始,则寻找当前项目下的/img/目录中的资源
        访问的资源路径如果是以/js/以及其子路径开始,则寻找当前项目下的/js/目录中的资源
        其它资源同理...
-->
<mvc:resources mapping="/img/**" location="/img/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
  • 方式2(掌握)
<!--
    排除静态资源方式2:
        所有请求还是先交给DispatcherServlet处理
        如果DispatcherServlet处理不了的请求,再交给tomcat中的名为DefaultServlet的资源处理
-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>

注意:必须配合<mvc:annotation-driven/>,否则会造成Controller中的方法无法访问

3)中文乱码过滤器

springmvc中内置了一个名为CharacterEncodingFilter的过滤器,用于解决POST请求的中文乱码。因此需要在web.xml文件中对其进行配置,配置方式如下:

<filter>
    <filter-name>CharacterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--配置初始化参数,指定编码-->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

五、注解驱动

对于springmvc的相关配置,通常都是基于xml完成,但是也可以通过纯注解配置实现,注解配置的过程比xml更为复杂,所以这部分内容仅做了解。

1)编写SpringMVCConfig配置类,需要实现WebMvcConfigurer接口

@Configuration
@ComponentScan(
        value = "com.itheima",
        includeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = {Controller.class}
        )
)
public class SpringMVCConfiguration implements WebMvcConfigurer {
    //相当于<mvc:resources mapping="/img/**" location="/img/"/>
    /*@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**").addResourceLocations("/img/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    }*/

    //相当于<mvc:default-servlet-handler/>
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}

2)编写ServletContainersInitConfig类,需要实现AbstractDispatcherServletInitializer,用于初始化Servlet容器,注册Filter,创建spring的web容器等

public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    //创建Servlet容器时,使用注解的方式加载SPRINGMVC配置类中的信息,并加载成WEB专用的ApplicationContext对象
    //该对象放入了ServletContext范围,后期在整个WEB容器中可以随时获取调用
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMVCConfiguration.class);
        return ctx;
    }

    //设置前端控制器DispatcherServlet的url-pattern
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    //在服务器启动时注册中文乱码过滤器
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        CharacterEncodingFilter cef = new CharacterEncodingFilter();
        cef.setEncoding("UTF-8");
        FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
        registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE),false,"/*");
    }
}

六.注解驱动原理(了解)

  1. 在Servlet3.0的规范中,服务器启动时,会自动在类路径下寻找META-INF/services下以ServletContainerInitializer的全路径名命名的文件

  2. 在引入的spring-web-5.1.9.RELEASE.jar包下存在此文件
    在这里插入图片描述

  3. 服务器启动时会自动加载此文件中配置的SpringServletContainerInitializer
    在这里插入图片描述

  4. 我们自定义的ServletContainersInitConfig类间接实现了WebApplicationInitializer
    在这里插入图片描述

  5. 所以服务器启动时ServletContainersInitConfig中的onStartup方法会执行
    在这里插入图片描述

七.springmvc的请求

获取请求参数

普通参数获取
  • 普通参数获取,请求参数的key与方法的形参保持一致
//方法传递普通类型参数,数量任意,类型必须匹配
//http://localhost/requestParam1?name=itheima&age=18   可以赋值
//http://localhost/requestParam1?age=18                可以赋值,name默认值为null
//http://localhost/requestParam1?name=itheima          报错,因为null无法转换为int
@RequestMapping("/requestParam1")
public String requestParam1(String name, int age){
    System.out.println(name);
    System.out.println(age);
    return "page.jsp";
}
  • 普通参数获取,请求参数的key与方法的形参不一致
//方法传递普通类型参数,使用@RequestParam参数匹配URL传参中的参数名称与方法形参名称
//http://localhost/requestParam2?userName=Jock    将请求参数中名为userName的参数值赋值给形参name
@RequestMapping("/requestParam2")
public String requestParam2(@RequestParam(value = "userName",required = true) String name){
    System.out.println(name);
    return "page.jsp";
}
POJO参数获取

(pojo即简单java对象,就是javabean)

准备User.java和Address.java

User.java

public class User {
    private String name;
    private Integer age;

    private Address address;

    private List<String> nick;

    private List<Address> addresses;

    public List<Address> getAddresses() {
        return addresses;
    }

    public Map<String,Address> addressMap;

    public Map<String, Address> getAddressMap() {
        return addressMap;
    }
    
    public void setAddressMap(Map<String, Address> addressMap) {
        this.addressMap = addressMap;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    public List<String> getNick() {
        return nick;
    }

    public void setNick(List<String> nick) {
        this.nick = nick;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                ", nick=" + nick +
                ", addresses=" + addresses +
                ", addressMap=" + addressMap +
                '}';
    }
}

Address.java

public class Address {
    private String province;
    private String city;
    private String address;

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "provice='" + province + '\'' +
                ", city='" + city + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
  • 给User中的name和age赋值

    当POJO中使用简单类型属性时,参数名称与POJO类属性名保持一致

//方法传递POJO类型参数,URL地址中的参数作为POJO的属性直接传入对象
//http://localhost/requestParam3?name=zhangsan&age=18
@RequestMapping("/requestParam3")
public String requestParam3(User user){
    System.out.println(user);
    return "page.jsp";
}
  • 给User中的address赋值(address为Address类型的对象)

    当POJO中出现对象属性时,参数名称与对象层次结构名称保持一致

//使用对象属性名.属性名的对象层次结构可以为POJO中的POJO类型参数属性赋值
//http://localhost/requestParam5?address.province=cq&address.city=spb
@RequestMapping("/requestParam5")
public String requestParam5(User user){
    System.out.println(user.getAddress().getCity());
    return "page.jsp";
}
  • 给User中的nick赋值(nick为List<String>类型)

    当POJO中出现集合,保存简单数据,使用多个相同名称的参数为其进行赋值

//通过URL地址中同名参数,可以为POJO中的集合属性进行赋值,集合属性要求保存简单数据
//http://localhost/requestParam6?nick=zs2&nick=zs3
@RequestMapping("/requestParam6")
public String requestParam6(User user){
    System.out.println(user);
    return "page.jsp";
}
  • 给User中的addresses赋值(addresses为List<Address>类型)

    当POJO中出现List,List中保存对象,请求参数名称与对象层次结构名称保持一致,使用[索引]描述

//POJO中List对象保存POJO的对象属性赋值,使用[数字]的格式指定为集合中第几个对象的属性赋值
//http://localhost/requestParam7?addresses[0].province=cq&addresses[1].province=cd
@RequestMapping("/requestParam7")
public String requestParam7(User user){
    System.out.println(user);
    return "page.jsp";
}
  • 给User中的addressMap赋值(addressMap为Map<String,Address>类型)

    当POJO中出现Map,保存对象数据,参数名称与对象层次结构名称保持一致,使用['map的key']描述

//POJO中Map对象保存POJO的对象属性赋值,使用[key]的格式指定为Map中的对象属性赋值
//http://localhost/requestParam8?addressMap['home'].province=cq&addressMap['job'].province=cd
@RequestMapping("/requestParam8")
public String requestParam8(User user){
    System.out.println(user.getAddressMap());
    return "page.jsp";
}
数组和集合参数获取
  • 数组参数(数组中的类型是普通类型)

    请求参数名与方法中数组类型的形参名保持一致

//方法传递普通类型的数组参数,URL地址中使用同名变量为数组赋值
//http://localhost/requestParam9?nick=Jockme&nick=zahc
@RequestMapping("/requestParam9")
public String requestParam9(String[] nick){
    System.out.println(Arrays.asList(nick));
    return "page.jsp";
}
  • List集合参数(List集合中的泛型类型是普通类型)

    请求参数名与方法中List集合类型的形参名保持一致

//方法传递保存普通类型的List集合时,无法直接为其赋值,需要使用@RequestParam参数对参数名称进行转换
//http://localhost/requestParam10?nick=Jockme&nick=zahc
@RequestMapping("/requestParam10")
public String requestParam10(@RequestParam("nick") List<String> nick){
    System.out.println(nick);
    return "page.jsp";
}

ps:@RequestParam('nick')的作用是限定将请求参数名为nick的参数值封装到nick这个形参中,而不是将List当成普通pojo来处理。List集合的泛型如果为引用数据类型,需要使用异步请求发送json格式数据,后续讲解。

日期类型转换
  • http请求中传输的请求参数都是String类型的,但是并不是所有参数都要封装成String
  • springmvc中内置了很多类型转换器,能够完成常见的类型转换。
  • 但是对于Date类型的参数,默认只能转换yyyy/MM/dd的日期格式。如果是其它如yyyy-MM-dd的格式会转换失败
  • 对于这种场景需要自行对日期格式进行处理,有多种方式。

方式1:通过@DateTimeFormat指定格式

@RequestMapping("/requestParam11")
public String requestParam11(@DateTimeFormat(pattern="yyyy-MM-dd") Date date){
    System.out.println(date);
    return "page.jsp";
}

注意:使用此注解时必须配置<mvc:annotation-driven />

方式2:自定义类型转换器

  1. 编写一个实现Converter<S,T>接口的自定义转换器类
// S:source,原始类型
// T:target,目标类型
public class MyDateConverter implements Converter<String,Date>{
    // 将参数转换成返回值类型
    public Date convert(String dateStr) {
        SimpleDateFormat sdf = null;
        if(dateStr.contains("/")){
            sdf = new SimpleDateFormat("yyyy/MM/dd");
        }else if (dateStr.contains("-")){
            sdf = new SimpleDateFormat("yyyy-MM-dd");
        }
        try {
            Date date = sdf.parse(dateStr);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }
}
  1. 在spring-mvc.xml文件中配置自定义转换器
<!--配置转换服务工厂(用于加载转换器),在它默认加载的转换器集合中,添加并覆盖原来的日期转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.itheima.converter.MyDateConverter"/>
        </set>
    </property>
</bean>

<!--在加载时,加载修改之后的转换器服务工厂-->
<mvc:annotation-driven conversion-service="conversionService"/>

RequestMapping注解

  • 作用

    建立请求资源路径与处理器方法的映射关系(方法通过什么路径访问)

  • 位置

    类上:用于指定一级访问路径,一般用于区分不同的模块

    方法上:用于指定二级访问路径

@Controller
@RequestMapping("/dept")
public class DeptController {
    @RequestMapping("save")
    public String save(){
        System.out.println("dept save...");
        return "/page.jsp";
    }

    @RequestMapping("/update")
    public String update(){
        System.out.println("update save...");
        return "/page.jsp";
    }
}

上述配置代表在访问DeptController中的所有方法时,都需要在前面加上一层/dept,如:

http://localhost/dept/save

http://localhost/dept/update

  • 属性

    属性名作用
    value/path限定访问路径
    method限定请求方式
    params限定请求参数
    headers限定请求头
    produces指定响应的mime类型和编码

八.springmvc的响应

在服务器向客户端浏览器进行响应有常见的两种形式:

  1. 页面跳转(由其他页面进行响应)
  2. 直接输出响应内容

页面跳转

返回不带前缀的视图名
  • 返回不带前缀的视图名时,默认是通过转发的形式访问视图,支持访问WEB-INF下的页面
@RequestMapping("/showPage")
public String showPage() {
    System.out.println("user mvc controller is running ...");
    return "/WEB-INF/page/page.jsp";
}

注意:

  1. 如果返回值前不带/,表示相对路径
  2. 如果返回值前带/,表示绝对路径,/相当于项目根目录
返回带前缀的视图名

前缀:

  • forward:

    转发,可以访问WEB-INF下的页面

@RequestMapping("/showPage1")
public String showPage1() {
    System.out.println("user mvc controller is running ...");
    return "forward:/WEB-INF/page/page.jsp";
}
  • redirect:

    重定向,不能访问WEB-INF下的页面

// 访问报错
@RequestMapping("/showPage2")
public String showPage2() {
    System.out.println("user mvc controller is running ...");
    return "redirect:/WEB-INF/page/page.jsp";
}

// 访问正常
@RequestMapping("/showPage2")
public String showPage2() {
    System.out.println("user mvc controller is running ...");
    return "redirect:/page.jsp";
}

注意:重定向的地址不需要加虚拟目录,以/代表虚拟目录

配置视图解析器简化书写

实际开发中,为了避免用户恶意访问,通常会将页面存放在WEB-INF下,避免直接访问。这样会导致在方法中编写转发路径时,返回值中的路径比较长。因此可以通过配置视图解析器ViewResolver,配置固定的前缀和后缀。这样在书写方法的返回值是就可以省略相同的前缀和后缀,只用编写页面名称

配置方式如下:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/page/"/>
    <property name="suffix" value=".jsp"/>
</bean>

方法的返回值书写形式如下:

@RequestMapping("/showPage3")
public String showPage3() {
    System.out.println("user mvc controller is running ...");
    return "page";
}

拼接原理:
在这里插入图片描述
注意事项:一旦方法的返回值带有前缀,将不经过视图解析器进行前后缀拼接。所以需要编写完整的返回值。

页面跳转时携带数据
  • 在方法中添加HttpServletRequest类型的形参(不建议)
//使用原生request对象传递参数
@RequestMapping("/showPageAndData1")
public String showPageAndData1(HttpServletRequest request){
    request.setAttribute("name","itheima");
    return "page";
}
  • 在方法中添加Module类型的形参(了解)
@RequestMapping("/showPageAndData2")
public String showPageAndData2(Model model){ // MVC m:封装数据
    // 向Model中添加数据
    Book book = new Book();
    book.setName("jpm");
    book.setPrice(100d);
    model.addAttribute("name","zhangsan");
    model.addAttribute("book",book); // 完全等价于request.setAttribute();
    return "page";
}
  • 方法的返回值是ModelAndView(重点掌握)
@RequestMapping("/showPageAndData3")
public ModelAndView showPageAndData3(){
    ModelAndView modelAndView = new ModelAndView();
    // 设置模型数据
    Book book = new Book();
    book.setName("jpm1");
    book.setPrice(1001d);
    modelAndView.addObject("name","lisi");//request.setAttribute();
    modelAndView.addObject("book",book);
    // 设置视图名称
    modelAndView.setViewName("page");
    return modelAndView;
}


//ModelAndView对象支持转发的手工设定,该设定不会启用前缀后缀的页面拼接格式
@RequestMapping("/showPageAndData4")
public ModelAndView showPageAndData4(ModelAndView modelAndView) {
    modelAndView.setViewName("forward:/WEB-INF/page/page.jsp");
    return modelAndView;
}

//ModelAndView对象支持重定向的手工设定,该设定不会启用前缀后缀的页面拼接格式
@RequestMapping("/showPageAndData5")
public ModelAndView showPageAndData6(ModelAndView modelAndView) {
    modelAndView.setViewName("redirect:page.jsp");
    return modelAndView;
}

直接响应数据

  • 方式1: 在方法上添加HttpServletResponse类型的参数,通过response进行响应(不建议)
@RequestMapping("/showData1")
public void showData1(HttpServletResponse response) throws IOException {
    response.getWriter().write("message");
}

注意:方法的返回值为void

  • 方式2:方法直接返回字符串,并在方法上添加@ResponseBody注解(了解)
@RequestMapping("/showData2")
@ResponseBody
public String showData2(){
    return "{'name':'Jock'}";
}

注意:@ResponseBody注解代表将方法的返回值作为响应体直接响应给页面,所以不会进行页面跳转

  • 方式3:方法直接返回对象或集合,并在方法上添加@ResponseBody注解,springmvc会自动将对象或集合转成json字符串,并直接响应给页面 (重点掌握)
@RequestMapping("/showData4")
@ResponseBody
public Book showData4() {
    Book book  = new Book();
    book.setName("SpringMVC入门案例");
    book.setPrice(66.66d);
    return book;
}

//转换集合类型数据
@RequestMapping("/showData5")
@ResponseBody
public List showData5() {
    Book book1  = new Book();
    book1.setName("SpringMVC入门案例");
    book1.setPrice(66.66d);

    Book book2  = new Book();
    book2.setName("SpringMVC入门案例");
    book2.setPrice(66.66d);

    ArrayList al = new ArrayList();
    al.add(book1);
    al.add(book2);
    return al;
}

注意:springmvc在进行json转换时,默认需要使用jackson,所以需要在pom.xml文件中加入jackson相关坐标

<!--json相关坐标3个-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.0</version>
</dependency>

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

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.0</version>
</dependency>

实际开发中,大多时候都需是异步请求,响应json字符串,所以这种形式是主流,需要重点掌握。

springmvc之Servlet相关API

方法中使用Servlet原生API

SpringMVC提供访问原始Servlet接口API的功能,通过形参声明即可。支持的形参类型如下:

  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
@RequestMapping("/servletApi")
public String servletApi(HttpServletRequest request, HttpServletResponse response, HttpSession session){
    System.out.println(request);
    System.out.println(response);
    System.out.println(session);
    return "page";
}

Servlet API相关注解

RequestHeader注解

  • 作用:获取指定名称请求头的值,并赋值给方法形参

    用于替换request.getHeader("请求头名称")相关方法

@RequestMapping("/headApi")
public String headApi(@RequestHeader("Accept-Encoding") String headMsg){
    System.out.println(headMsg);
    return "page";
}

CookieValue注解

  • 作用:获取指定名称Cookie的值,并赋值给方法形参

    用于替换request.getCookies(),Cookie.getValue()系列方法

@RequestMapping("/cookieApi")
public String cookieApi(@CookieValue("JSESSIONID") String jsessionid){
    System.out.println(jsessionid);
    return "page";
}

SessionAttribute注解

  • 作用:获取Session域中指定key对应的value,并赋值给方法形参

    用于替换session.getAttribute("key")方法

//测试用方法,为下面的试验服务,用于在session中放入数据
@RequestMapping("/setSessionData")
public String setSessionData(HttpSession session){
    session.setAttribute("name","itheima");
    return "page";
}

//获取session数据的快捷操作方式
@RequestMapping("/sessionApi")
public String sessionApi(@SessionAttribute(value="name",required = false) String name){
    System.out.println(name);
    return "page";
}

SessionAttributes注解

  • 作用:将所在类中,原本存入Model中的指定名称的数据批量存入session域
//设定当前类中名称为age和gender的变量放入session范围
@SessionAttributes(names = {"age","gender"})
public class UserController{
    //测试使用
    @RequestMapping("/sessionApi")
    public String sessionApi(@SessionAttribute(value="name",required = false) String name,
                             @SessionAttribute("age") int age,
                             @SessionAttribute("gender") String gender){
        System.out.println(name);
        System.out.println(age);
        System.out.println(gender);
        return "page";
    }
    
    //配合类上的@SessionAttributes(names = {"age","gender"})使用
    @RequestMapping("/setSessionData2")
    public String setSessionDate2(Model model) {
        model.addAttribute("age",39);
        model.addAttribute("gender","男");
        return "page";
    } 
}

配置解释

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值