第十五节:SpringMvc简介、基本配置、Get请求和响应、Post请求和响应

一. SpringMvc简介

1. 说明

  SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 中。

  SpringMVC 已经成为目前最主流的MVC框架之一,并且随着Spring3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。

2. 技术架构图

 

二. 基本配置

1. XML形式的配置

(1). 导入相应的坐标

  这里导入spring (用5.2.9版本)、servlet、jsp、json相关坐标 和 tomcat7插件。

<dependencies>
        <!--Spring 坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!--spring web的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!--springmvc的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!--servlet 4.0规范-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!--jsp 坐标-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>
        <!--json相关坐标3个-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.9</version>
        </dependency>
    </dependencies>


    <build>
        <finalName>01_Basic</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <port>8888</port>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
View Code

(2). 配置spring-mvc.xml核心配置文件

A. 加载扫描类→B. 开启SpringMvc注解驱动(全局处理乱码问题)→C.开启静态资源配置(普通和通用两种方式)

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

    <!-- 1.加载扫描类   -->
    <!--1.1 扫描加载所有的控制类-->
    <context:component-scan base-package="com.ypf"/>

    <!--1.2 扫描加载所有的控制类 + 过滤器-->
    <!--    <context:component-scan base-package="com.ypf">-->
    <!--        &lt;!&ndash;只有@Controller标记的bean才会被Spring识别&ndash;&gt;-->
    <!--        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->
    <!--    </context:component-scan>-->

    <!--2开启springmvc注解驱动-->
    <!--,对@ResponseBody的注解进行格式增强,追加其类型转换的功能,具体实现由MappingJackson2HttpMessageConverter进行-->
    <mvc:annotation-driven>
        <!-- 全局解决中文乱码问题 -->
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/plain;charset=utf-8</value>
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>


    <!--3. 放行指定类型静态资源配置方式-->
    <!--3.1 单独配置-->
    <!--<mvc:resources mapping="/img/**" location="/img/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>-->

    <!--3.2 SpringMVC提供的通用资源放行方式-->
    <mvc:default-servlet-handler/>


</beans>
View Code

(3). 在web.xml中进行配置

配置请求模型,加载spring-mvc.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
          http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">


  <!--一. 请求模型-->
  <servlet>
    <servlet-name>DispatcherServlet</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>
  </servlet>
  <servlet-mapping>
    <servlet-name>DispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>


</web-app>
View Code

(4). 配置action进行测试

//设置当前类为Spring的控制类
@Controller
@RequestMapping("/User1")
public class UserController {

    //设定当前方法的访问映射地址
    //http://localhost:8888/01_Basic/User1/save
    @RequestMapping("/save")
    @ResponseBody
    //设置当前方法返回值类型为String
    public String save(){
        System.out.println("user mvc controller is running ...");
        return "user mvc controller is running ...";
    }

    //跳转到指定页面  (需要加个forward,否则和控制器上匹配规则冲突)
    //http://localhost:8888/01_Basic/User1/save2
    @RequestMapping("/save2")
    //设置当前方法返回值类型为String
    public String save2(){
        System.out.println("user mvc controller is running ...");
        return "forward:/index.jsp";
    }

}

剖析:@Controller标注该类为控制器类,@RequestMapping标注请求路径,@ResponseBody标注响应值

2. 注解形式的配置 

(1). 导入相应的坐标,同上

(2). 两个核心配置文件

SpringMvcConfig
//使用注解形式转化SpringMVC核心配置文件为配置类
@Configuration
@ComponentScan(value = "com.ypf",includeFilters =
                                 @ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class}))
public class SpringMvcConfig implements WebMvcConfigurer {

    //静态资源放行(1)
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**").addResourceLocations("/img/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    }

    //静态资源放行(2)-通用的模式
//    @Override
//    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
//        configurer.enable();
//    }

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

    //注解配置映射地址方式,服务于SpringMVC的核心控制器DispatcherServlet
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

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

    //乱码处理作为过滤器,在servlet容器启动时进行配置,相关内容参看Servlet零配置相关课程
    @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,"/*");
    }
}
View Code

(3). 编写测试方法,同上

 

三. Get请求和响应

 前提准备:

 ①:相关配置,详见上面 二 中的xml形式配置

 ②:相关实体类准备

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;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                ", nick=" + nick +
                ", addresses=" + addresses +
                ", addressMap=" + 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;
    }

}

public class Book {
    private String name;
    private Double price;

    public String getName() {
        return name;
    }

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

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
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{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

}
View Code

1. 各种参数接收

(1). 普通类型接收

    //1.方法传递普通类型参数,数量任意,类型必须匹配(ok)
    //http://localhost:8888/03_request_response_Get/User1/requestParam1?name=ypf&age=14
    @RequestMapping("/requestParam1")
    @ResponseBody
    public String requestParam1(String name,int age){
        System.out.println(name+","+age);
        return name+","+age;
    }

    //2.方法传递普通类型参数,使用@RequestParam可以修改传参中的参数名称以及设置默认值(ok)
    // http://localhost:8888/03_request_response_Get/User1/requestParam2?userName=Jock
    @RequestMapping("/requestParam2")
    @ResponseBody
    public String requestParam2(@RequestParam(
            name = "userName",
            required = true,
            defaultValue = "ypf1") String name){
        System.out.println("name="+name);
        return "name="+name;
    }

剖析:可以在接收参数上加 @RequestParam,修改参数名称,并且配置默认值。

(2). 实体接收

 //1. 普通实体接收(ok)
    //访问URL: http://localhost:8888/03_request_response_Get/User1/requestParam3?name=ypf&age=14
    @RequestMapping("/requestParam3")
    @ResponseBody
    public String requestParam3(User user){
        System.out.println("name="+user.getName());
        return "name="+user.getName()+"age="+user.getAge();
    }

    // 2。 **参数冲突**(ok)
    //当POJO类型属性与其他形参出现同名问题时,将被同时赋值
    //建议使用@RequestParam注解进行区分
    //访问URL: http://localhost:8888/03_request_response_Get/User1/requestParam4?name=ypf&age=14
    @RequestMapping("/requestParam4")
    @ResponseBody
    public String requestParam4(User user,String age){
        System.out.println("user.age="+user.getAge()+",age="+age);
        return "user.age="+user.getAge()+",age="+age;
    }

    //3. 当POJO中出现对象属性时,参数名称与对象层次结构名称保持一致(ok)
    //访问URL: http://localhost:8888/03_request_response_Get/User1/requestParam5?address.province=beijing
    @RequestMapping("/requestParam5")
    @ResponseBody
    public String requestParam5(User user){
        System.out.println("user.address="+user.getAddress().getProvince());
        return "user.address="+user.getAddress().getProvince();
    }

    //4. 当实体中出现List,保存对象数据,参数名称与对象层次结构名称保持一致,使用数组格式描述集合中对象的位置(有问题)
    //访问URL: http://localhost:8888/03_request_response_Get/User1/requestParam7?addresses[0].province=bj&addresses[1].province=tj
    @RequestMapping("/requestParam7")
    @ResponseBody
    public String requestParam7(User user){
        System.out.println("user.addresses="+user.getAddress());
        return "user.addresses="+user.getAddress();
    }

    //5. 当POJO中出现Map,保存对象数据,参数名称与对象层次结构名称保持一致,使用映射格式描述集合中对象的位置(ok)
    // 访问URL:http://localhost:8888/03_request_response_Get/User1/requestParam8?addressMap[’home’].province=bj&addressMap[’job’].province=tj
    @RequestMapping("/requestParam8")
    @ResponseBody
    public String requestParam8(User user){
        System.out.println("user.addressMap="+user.getAddressMap());
        return "user.addressMap="+user.getAddressMap();
    }

(3). 数组和集合接收

    //1.数组类型参数(ok)
    //请求参数名与处理器方法形参名保持一致,且请求参数数量> 1个
    //http://localhost:8888/03_request_response_Get/User1/requestParam9?nick=Jockme&nick=zahc
    @RequestMapping("/requestParam9")
    @ResponseBody
    public String requestParam9(String[] nick){
        System.out.println(nick[0]+","+nick[1]);
        return nick[0]+","+nick[1];
    }

    //2.**集合类型参数**(ok)
    // 保存简单类型数据,请求参数名与处理器方法形参名保持一致,且请求参数数量> 1个
    //访问URL:http://localhost:8888/03_request_response_Get/User1/requestParam10?nick=Jockme&nick=zahc
    @RequestMapping("/requestParam10")
    @ResponseBody
    public List requestParam10(@RequestParam("nick") List<String> nick){
        System.out.println(nick);
        return nick;
    }

剖析:

  SpringMVC默认将List作为对象处理,赋值前先创建对象,然后将nick作为对象的属性进行处理。由于 List是接口,无法创建对象,报无法找到构造方法异常;修复类型为可创建对象的ArrayList类型后,对象可 以创建,但没有nick属性,因此数据为空。此时需要告知SpringMVC的处理器nick是一组数据,而不是一个单 一数据。通过@RequestParam注解,将数量大于1个names参数打包成参数数组后, SpringMVC才能识别该数 据格式,并判定形参类型是否为数组或集合,并按数组或集合对象的形式操作数据。

(4). 类型转换器

A. 通用类型转换器

    //1.通用类型转换器(ok)
    //@DateTimeFormat注解设定日期格式,依赖springmvc的注解启动才能运行
    //http://localhost:8888/03_request_response_Get/User1/requestParam11?date=1999-09-09
    @RequestMapping("/requestParam11")
    @ResponseBody
    public String requestParam11(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
        System.out.println(date);
        return date.toString();
    }

B. 自定义时间转换

    //2. 使用自定义日期格式转换器(ok)
    //依赖springmvc的注解启动才能运行
    //http://localhost:8888/03_request_response_Get/User1/requestParam12?date=1999-09-09
    @RequestMapping("/requestParam12")
    @ResponseBody
    public String requestParam12(Date date){
        System.out.println(date);
        return date.toString();
    }

在springmvc核心配置文件夹添加

    <!-- 5. 自定义日期转换器,配合不带@DateTimeFormat的requestParam12使用-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--1.设定格式类型Converter,注册为Bean,受SpringMVC管理-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <!--2.自定义Converter格式类型设定,该设定使用的是同类型覆盖的思想-->
        <property name="formatters">
            <!--3.使用set保障相同类型的转换器仅保留一个,避免冲突-->
            <set>
                <!--4.设置具体的格式类型-->
                <bean class="org.springframework.format.datetime.DateFormatter">
                    <!--5.类型规则-->
                    <property name="pattern" value="yyyy-MM-dd"/>
                </bean>
            </set>
        </property>
    </bean>
View Code

C. 自定义格式转换

     //3. 使用自定义格式转换器(ok)
    //依赖springmvc的注解启动才能运行
    //http://localhost:8888/03_request_response_Get/User1/requestParam13?date=1999-09-09
    @RequestMapping("/requestParam13")
    @ResponseBody
    public String requestParam13(Date date){
        System.out.println(date);
        return date.toString();
    }

在springmvc核心配置中添加

    <!--  6.自定义格数据类型转换器案例,配合requestParam13使用-->
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!--自定义类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!--覆盖类型转换器定义规则,该规则是一个set集合,对类型转换器来说是追加和替换的思想,而不是覆盖整体格式化转换器-->
        <property name="converters">
            <set>
                <!--添加自定义的类型转换器,会根据定义的格式覆盖系统中默认的格式-->
                <!--当前案例中是将String转换成Date的类型转换器进行了自定义,所以添加后,系统中原始自带的String——>Date的类型转换器失效-->
                <bean class="com.ypf.converter.MyDateConverter"/>
            </set>
        </property>
    </bean>
//自定义类型转换器,实现Converter接口,接口中指定的泛型即为最终作用的条件
//本例中的泛型填写的是String,Date,最终出现字符串转日期时,该类型转换器生效
public class MyDateConverter implements Converter<String, Date> {
    //重写接口的抽象方法,参数由泛型决定
    public Date convert(String source) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        //类型转换器无法预计使用过程中出现的异常,因此必须在类型转换器内部捕获,不允许抛出,框架无法预计此类异常如何处理
        try {
            date = df.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}
View Code

补充:

   @RequestMapping 注解的相关参数

@RequestMapping(
    value="/requestURL3", //设定请求路径,与path属性、 value属性相同
    method = RequestMethod.GET, //设定请求方式
    params = "name", //设定请求参数条件
    headers = "content-type=text/*", //设定请求消息头条件
    consumes = "text/*", //用于指定可以接收的请求正文类型(MIME类型)
    produces = "text/*" //用于指定可以生成的响应正文类型(MIME类型)
)
public String requestURL3() {
    return "/page.jsp";
}

2. 各种返回值

(1). 返回Json数据(重点)

 只要pom.xml中导入json相关的三个坐标即可。 

 //使用原生response对象响应数据(ok)
    //http://localhost:8888/03_request_response_Get/User2/showData1
    @RequestMapping("/showData1")
    public void showData1(HttpServletResponse response) throws IOException {
        response.getWriter().write("message");
    }

    //使用@ResponseBody将返回的结果作为响应内容,而非响应的页面名称
    //5.3.0以上版本报错,这里改为5.2.9)
    @RequestMapping("/showData2")
    @ResponseBody
    public String showData2() {
        return "{'name':'Jock'}";
    }

    //使用jackson进行json数据格式转化
    //5.3.0以上版本报错,这里改为5.2.9)
    @RequestMapping("/showData3")
    @ResponseBody
    public String showData3() throws JsonProcessingException {
        Book book = new Book();
        book.setName("SpringMVC入门案例");
        book.setPrice(66.66d);

        ObjectMapper om = new ObjectMapper();
        return om.writeValueAsString(book);
    }

    //使用SpringMVC注解驱动,对标注@ResponseBody注解的控制器方法进行结果转换,
    // 由于返回值为引用类型,自动调用jackson提供的类型转换器进行格式转换(ok)
    @RequestMapping("/showData4")
    @ResponseBody
    public Book showData4() {
        Book book = new Book();
        book.setName("SpringMVC入门案例");
        book.setPrice(66.66d);
        return book;
    }

    //转换集合类型数据(ok)
    @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;
    }
View Code

(2). 页面跳转

//测试服务器是否正常工作使用
    //http://localhost:8888/03_request_response_Get/User2/showPage0
    // (报错!!和控制器上的路径冲突! 解决:在webapp下建1个User2文件夹,然后复制success.jsp一份进去)
    @RequestMapping("/showPage0")
    public String showPage0() {
        System.out.println("user mvc controller is running ...");
        return "success.jsp";
    }

    //forward:page.jsp转发访问 (ok)
    @RequestMapping("/showPage1")
    public String showPage1() {
        System.out.println("user mvc controller is running ...");
        return "forward:/success.jsp";
    }

    //forward:page.jsp转发访问,支持访问WEB-INF下的页面(ok)
    @RequestMapping("/showPage2")
    public String showPage2() {
        System.out.println("user mvc controller is running ...");
        return "forward:/WEB-INF/page/success.jsp";
    }

    //redirect:page.jsp重定向访问,不支持访问WEB-INF下的页面(报错)
    @RequestMapping("/showPage3")
    public String showPage3() {
        System.out.println("user mvc controller is running ...");
        return "redirect:success.jsp";
    }

    //redirect:page.jsp重定向访问,不支持访问WEB-INF下的页面(ok)
    @RequestMapping("/showPage4")
    public String showPage4() {
        System.out.println("user mvc controller is running ...");
        return "redirect:/WEB-INF/page/success.jsp";
    }
View Code

(3). 页面访问快捷设定

配置:

         <!--4.页面快捷访问    -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/pages/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    //需要在配置文件中事先开启配置
    //页面简化配置格式,使用前缀+页面名称+后缀的形式进行,类似于字符串拼接 (报错,404 未调试通)
    //http://localhost:8888/03_request_response_Get/User2/showPage5
    @RequestMapping("/showPage5")
    public String showPage5() {
        System.out.println("user mvc controller is running ...");
        return "success";
    }

    //页面简化配置格式不支持书写forward(报错,404 未调试通)
    //http://localhost:8888/03_request_response_Get/User2/showPage6
    @RequestMapping("/showPage6")
    public String showPage6() {
        System.out.println("user mvc controller is running ...");
        return "forward:success";
    }
View Code

(4). 带数据的页面跳转

  // 方式一:使用HttpServletRequest类型形参进行数据传递
    //    http://localhost:8888/03_request_response_Get/User2/showPageAndData1
    @RequestMapping("/showPageAndData1")
    public String showPageAndData1(HttpServletRequest request) {
        request.setAttribute("name", "ypf");
        return "forward:/success.jsp";
    }

    //方式二:使用Model类型形参进行数据传递
   //    http://localhost:8888/03_request_response_Get/User2/showPageAndData2
    @RequestMapping("/showPageAndData2")
    public String showPageAndData2(Model model) {
        model.addAttribute("name","itheima");
        Book book = new Book();
        book.setName("SpringMVC入门实战");
        book.setPrice(66.6d);
        model.addAttribute("book",book);
        return "forward:/success.jsp";
    }

    //方式三:使用ModelAndView形参传递参数,该对象还封装了页面信息(404找不到)
    @RequestMapping("/showPageAndData3")
    public ModelAndView showPageAndData3(ModelAndView modelAndView) {
        //ModelAndView mav = new ModelAndView();    替换形参中的参数
        Book book  = new Book();
        book.setName("SpringMVC入门案例");
        book.setPrice(66.66d);
        //添加数据的方式,key对value
        modelAndView.addObject("book",book);
        //添加数据的方式,key对value
        modelAndView.addObject("name","Jockme");
        //设置页面的方式,该方法最后一次执行的结果生效
        modelAndView.setViewName("success");
        //返回值设定成ModelAndView对象
        return modelAndView;
    }
View Code

 

四. Post请求和响应

1. text、表单提交 → 后台分参数接受

前端:

 //1.为id="testAjax"的组件绑定点击事件
        $("#testAjax").click(function () {
            //发送异步调用
            $.ajax({
                //请求方式:POST请求
                type: "POST",
                //请求的地址
                url: "ajaxController",
                //请求参数(也就是请求内容)
                data: 'ypf123',
                //请求正文的MIME类型
                contentType: "application/text",
                success: function (data) {
                    console.log(data);
                }
            });
        });
        $("#testAjax2").click(function () {
            //发送异步调用
            $.ajax({
                //请求方式:POST请求
                type: "POST",
                //请求的地址
                url: "ajaxController2",
                data: {"name":"Jock","sex":"男"},
                success: function (data) {
                    console.log(data);
                }
            });
        });

后台:

    //1.使用@RequestBody注解,可以将请求体内容封装到指定参数中
    @RequestMapping("/ajaxController")
    @ResponseBody
    public String ajaxController(@RequestBody String msg) {
        System.out.println("ajax request is running..." + msg);
        return msg;
    }

    //接收表单提交的数据,后面的produces = "text/html;charset=utf-8"(是解决中文乱码问题)
    //@RequestMapping(value = "/ajaxController2", produces = "text/html;charset=utf-8")
    @RequestMapping(value = "/ajaxController2")
    @ResponseBody
    public String ajaxController2(String name, String sex) {
        System.out.println("ajax request is running..." + name + "," + sex);
        return name + "," + sex;
    }

2. Json数据提交、表单提交 → 后台实体接收

前端:

        //2. json数据提交
        $("#testAjaxPojo").click(function () {
            $.ajax({
                type: "POST",
                url: "ajaxPojoToController",
                data: '{"name":"Jock","age":39}',
                dataType: "text",
                contentType: "application/json",
                success: function (data) {
                    console.log(data);
                }
            });
        });
        //表单数据提交
        $("#testAjaxPojo2").click(function () {
            $.ajax({
                type: "POST",
                url: "ajaxPojoToController2",
                data: {"name":"Jock","age":39},
                dataType: "text",
                success: function (data) {
                    console.log(data);
                }
            });
        });

后台:

    //2.如果处理参数是POJO,且页面发送的请求数据格式与POJO中的属性对应,@RequestBody注解可以自动映射对应请求数据到POJO中
    //注意:POJO中的属性如果请求数据中没有,属性值为null,POJO中没有的属性如果请求数据中有,不进行映射
    @RequestMapping("/ajaxPojoToController")
    @ResponseBody
    public User ajaxPojoToController(@RequestBody User user) {
        System.out.println("controller pojo :" + user);
        return user;
    }

    @RequestMapping("/ajaxPojoToController2")
    @ResponseBody
    public User ajaxPojoToController2(User user) {
        System.out.println("controller pojo :" + user);
        return user;
    }

3. json格式提交List → 后台list接收,返回List

前端:

       //3. 为id="testAjaxList"的组件绑定点击事件
        $("#testAjaxList").click(function () {
            $.ajax({
                type: "POST",
                url: "ajaxListToController",
                data: '[{"name":"Jock","age":39},{"name":"Jockme","age":40}]',
                dataType: "text",
                contentType: "application/json",
                success: function (data) {
                    console.log(data);
                }
            });
        });

后台:

    //3.如果处理参数是List集合且封装了POJO,且页面发送的数据是JSON格式的对象数组,数据将自动映射到集合参数中
    @RequestMapping("/ajaxListToController")
    @ResponseBody
    public List<User> ajaxListToController(@RequestBody List<User> userList) {
        System.out.println("controller list :" + userList);
        return userList;
    }

 

4.  返回json数据和json数组数据

前端:

  //4.为id="testAjaxReturnJson"的组件绑定点击事件
        $("#testAjaxReturnJson").click(function () {
            //发送异步调用
            $.ajax({
                type: "POST",
                url: "ajaxReturnJson",
                //回调函数
                success: function (data) {
                    console.log(data);
                }
            });
        });

        //5.为id="testAjaxReturnJsonList"的组件绑定点击事件
        $("#testAjaxReturnJsonList").click(function () {
            //发送异步调用
            $.ajax({
                type: "POST",
                url: "ajaxReturnJsonList",
                success: function (data) {
                    console.log(data);
                }
            });
        });

后台:

//4.基于jackon技术,使用@ResponseBody注解可以将返回的POJO对象转成json格式数据
    @RequestMapping("/ajaxReturnJson")
    @ResponseBody
    public User ajaxReturnJson() {
        System.out.println("controller return json pojo...");
        User user = new User();
        user.setName("Jockme");
        user.setAge(39);
        return user;
    }

    //5.基于jackon技术,使用@ResponseBody注解可以将返回的保存POJO对象的集合转成json数组格式数据
    @RequestMapping("/ajaxReturnJsonList")
    @ResponseBody
    public List ajaxReturnJsonList() {
        System.out.println("controller return json list...");
        User user1 = new User();
        user1.setName("Tom");
        user1.setAge(3);

        User user2 = new User();
        user2.setName("Jerry");
        user2.setAge(5);

        ArrayList al = new ArrayList();
        al.add(user1);
        al.add(user2);

        return al;
    }

5. 跨域请求

前端:

  //6.为id="testCross"的组件绑定点击事件
        $("#testCross").click(function () {
            //发送异步调用
            $.ajax({
                type: "POST",
                url: "http://www.ypf.com:8888/03_request_response_Get/cross",
                //回调函数
                success: function (data) {
                    console.log(data);
                    alert("跨域调用信息反馈:" + data['name'] + " ,  " + data['age']);
                }
            });
        });

后台:

    //6.使用@CrossOrigin开启跨域访问
    //标注在处理器方法上方表示该方法支持跨域访问
    //标注在处理器类上方表示该处理器类中的所有处理器方法均支持跨域访问
    @RequestMapping("/cross")
    @ResponseBody
    @CrossOrigin
    public User cross(HttpServletRequest request) {
        System.out.println("controller cross..." + request.getRequestURL());
        User user = new User();
        user.setName("Jockme");
        user.setAge(39);
        return user;
    }

扩展在本机模拟跨域:

 A. 进入C盘:C:\Windows\System32\drivers\etc, 选择hosts文件。

B. 进行如下编辑:

 C. CMD中运行下面指令

动态刷新DNS

*  命令: ipconfig /displaydns
*  命令: ipconfig /flushdns   

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

 

posted @ 2021-08-11 20:46  Yaopengfei  阅读(246)  评论(1编辑  收藏  举报